소개
함수형 프로그래밍에 관심이 많은 백엔드 개발자입니다. 카카오(Daum) 개발팀장, NHN 수석, LINE+ 리드를 지내며 개발팀 리딩을 했고, 현재는 컨스택츠라는 작은 스타트업에서 다시 백엔드 개발자로 일하고 있습니다.
https://hatemogi.com/ 에 개발자 개인 홈을 운영중입니다.
강의
전체 5수강평
- 우아한 고성능 프로그래밍 언어 Rust 입문 및 활용
- 우아한 고성능 프로그래밍 언어 Rust 입문 및 활용
게시글
질문&답변
2024.08.13
메모리 관리규칙에서 질문드립니다.
수강 및 예리한 질문 감사드립니다.실험해보신 내용처럼 (s, s.len())으로 응답 튜플의 순서를 바꾸었을 때, 아래와 같은 컴파일 오류가 발생하는 것을 확인하였습니다. (사진) 에러의 내용은, 튜플의 첫번째 요소로써, s를 반환하기로 했기 때문에, 이 시점에 이미 소유권 반납이 이뤄졌다고 보는 거라고 이해하면 될 것 같습니다. 이미 소유권이 반납된 s를 이용해서 .len()메소드를 호출하려 할 때의 상황입니다. 이 문제를 해결하려면, len을 미리 값을 구해두면 되겠습니다. fn main() { let s: String = String::from("헬로"); let (s, len) = string_length(s); println!("문자열 {}의 길이는 {}", s, len); } fn string_length(s: String) -> (String, usize) { let len = s.len(); (s, len) }괜한 번거로움이니, 원래대로 usize를 앞에 담은 튜플을 반환하는 것이 편하겠고, 더 나아가 이후 강의에 설명드리는 임대 개념을 사용하면 좋을 것 같습니다.우선 이 질문과 답변의 핵심은, 소유권의 이동 시점에 관한 것이겠습니다. 감사합니다.
- 1
- 1
- 65
질문&답변
2024.08.09
튜플과 구조체 차이 설명에 관한 질문
수강 및 좋은 질문 감사합니다. 구조체와 튜플 혼동 차이struct Color(i32, i32, i32); struct Point(i32, i32, i32);사실 Color는 보통 (u8, u8, u8) 같은 타입을 쓰겠지만, 편한 비교를 위해 i32 3개로 구성했다고 칩시다. 이 상황에서fn drawSphere(point: Point, color: Color) { // ... 반지름 1인 구를 그리는 함수 } fn main() { let point = Point(0, 0, 0); let color = Color(255, 255, 255); drawSphere(point, color); }이렇게 원점에다가 흰색의 반지름 1짜리 구를 그리려는 상황이라면, drawSphere에 첫번째 파라미터에는 반드시 Point타입의 구조체 튜플이 들어가야 하고, 두번째는 반드시 Color타입의 구조체 튜플이 들어가야 하므로, 두 파라미터가 섞일 일이 없겠습니다.fn drawSphere(point: (i32, i32, i32), color: (i32, i32, i32)) { // ... 반지름 1인 구를 그리는 함수 } fn main() { let point = (0, 0, 0); let color = (255, 255, 255); drawSphere(color, point); }그런데 이번에는 그냥 평범한 튜플을 써보았는데요, 이때는 두 값의 타입이 (i32, i32, i32)로 동일하므로, drawSphere를 호출하는 시점에, 두 파라미터를 혼동해서 거꾸로 적었음에도, 타입체커 입장에서는 문제가 없으므로 정상 컴파일이 되겠습니다. 하지만, 실행하면, (255, 255, 255) 좌표에 검은색 구가 그려지겠죠.이런 상황을 말씀드리는 것이긴 합니다. 하지만 한편, 요새는 코드 에디터에서 명시적으로 파라미터 이름을 잘 보여주기도 하니, 크게 문제가 되지 않을 수도 있기도 하겠습니다.구조체 튜플과 구조체 끝에 세미콜론 차이사실 저도 크게 모르고 쓰고 있는 부분인데, 이 부분은 러스트 컴파일러나 린터, 포맷터가 알아서 잘 관리해주기 때문에 시키는대로 하면 되는 부분 같습니다. 아마도 문법적으로나 관습적으로 두 경우에 세미콜론 사용여부를 갈라놓은 것 같습니다. 정확한 것은 문법 규칙을 자세히 살펴보면 알 수 있겠습니다.(사진)그냥 편하게는 코드에디터에서 (아마도 러스트 포맷터나 린터가 알려주는 정보를 토대로) 'braced struct declarations are not followed by a semicolon'이라면서 잘 알려주고 빨갛게 표시해주므로, 세미콜론 없이 쓰면 되는 상황입니다. 혹시 더 궁금하셔서 문법 규칙을 살펴보셨다면, 제게도 알려주시면 감사하겠습니다. 감사합니다.
- 0
- 1
- 124
질문&답변
2024.04.27
trait를 인자로 받을 때 &impl과 &dyn차이
심도 깊은 질문 감사합니다. impl은 정적 디스패치라고, 컴파일 타임에 해당 트레이트를 구현한 구체적인 타입을 파악할 수 있는 경우이고, dyn같은 경우 동적으로 런타임에 파악하는 경우에 활용합니다. 전자는 컴파일타임에 구체적인 정보를 파악해야 하는 대신에 성능 페널티가 없고, 후자는 컴파일 타임에 미리 정해지지 않은 해당 트레이트 구현체를 활용할 수 있지만, 런타임에 해당 구현체를 쫓아가야 하는 부담이 있습니다.해당 주제는 중급 강의에 잘 정리해볼게요.수강 및 질문 감사드립니다.
- 1
- 2
- 186
질문&답변
2024.04.19
구조체는 언제나 Heap에 저장되나요??
예리한 질문 감사드립니다. 덕분에 저도 다시 한번 학습하게 되었습니다. 구현하신 구조체는 스택에 저장되는 것이 맞겠습니다. 구성멤버의 메모리 크기가 컴파일타임에 사전 결정되기 때문에 더욱 가능합니다. 스택과 힙 메모리 어디에 할당되는가를 중요하게 설명드렸기에 혼란을 끼친 것 같습니다.소유권 이전은 사실 엄밀하게 따지면 소유권의 대상(즉 메모리를 차지하고 있는 데이터)이 복사 되는가 아닌가가 더 중요하다고 볼 수 있습니다. 스택에 위치하는 기본 데이터형(i32 등)은 기본적으로 Copy 트레이트가 구현된 상태이고, 직접 선언하는 Struct는 기본적으로는 Copy트레이트가 구현되지 않습니다. 따라서 복제(Copy)가 발생하지 않고 소유권이 이동되어 버리는 상황인데요, 구현하신 코드에서 해당 구조체에 대해 Copy트레이트를 구현하신다면, 소유권이 이동되지 않고 복사되어 활용 가능합니다. #[derive(Clone, Copy)] struct Rectangle { width: u32, height: u32, } fn main() { let rect = Rectangle { width: 20, height: 30, }; println!( "가로가 {}, 세로가 {}인 사각형의 면적은 {}이다.", rect.width, rect.height, area(rect) ); print!("{:?}", rect.width); } fn area(rect: Rectangle) -> u32 { rect.width * rect.height } 이렇게 구현하시면 컴파일됩니다. 첫줄의 derive를 이용해서 Copy트레이트를 구현하였기 때문입니다. 대신 main함수의 스택공간과, area함수의 스택 공간 모두를 중복해서 차지하고 있게 되겠습니다.다시 정리하면, Heap을 차지하는 데이터라고 하더라도 Copy트레이트를 구현하면 내용이 복사되면서, 소유권 이동이 일어나지 않겠습니다.중급과정을 제작할 예정인데, 보충해서 잘 설명해보도록 하겠습니다. 수강과 질문 감사드립니다.
- 2
- 2
- 237
질문&답변
2024.04.04
혹시 어떤 폰트일까요?
여러 폰트를 썼는데요, 고운돋움IBM Plex Sans KRPretendard 입니다. 도움이 되셨기를 바랍니다.
- 0
- 2
- 295