Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

소유권과 빌림: Rust의 심장부 이해하기

학습 목표: Rust의 가장 혁신적인 기능인 소유권(Ownership) 시스템을 배웁니다. C#의 가비지 컬렉터(GC)가 하던 일을 Rust는 어떻게 컴파일 타임에 해결하는지, **이동(Move)**과 **빌림(Borrowing)**의 규칙을 통해 메모리 안전성을 어떻게 확보하는지 마스터합니다.


1. 소유권의 세 가지 황금률

Rust의 모든 메모리 관리 전략은 다음 세 가지 규칙에서 시작됩니다.

  1. 단일 소유자: 모든 값은 단 하나의 변수(소유자)에 속합니다.
  2. 이동(Move): 소유권이 다른 변수로 넘어가면, 이전 변수는 더 이상 사용할 수 없습니다.
  3. 자동 해제(Drop): 소유자가 스코프(Scope)를 벗어나면, 그 값은 즉시 메모리에서 해제됩니다.
#![allow(unused)]
fn main() {
// [C# 관점에서의 비교]
// C#: 여러 변수가 하나의 객체를 참조하고 GC가 나중에 치웁니다.
// Rust: 오직 하나만 소유하며, 그 주인이 사라지면 즉시 치웁니다.

let s1 = String::from("hello");
let s2 = s1; // 소유권 이전 (Move)
// println!("{}", s1); // ❌ 에러: s1은 이제 빈 껍데기입니다.
}

2. 빌림(Borrowing): 소유권은 그대로, 사용권만 빌려주기

매번 소유권을 넘기는 것은 불편합니다. 그래서 Rust는 참조(&)를 통해 데이터를 빌려주는 기능을 제공합니다.

  • 불변 빌림 (&T): 읽기 전용으로 빌려줍니다. 여러 명이 동시에 빌릴 수 있습니다.
  • 가변 빌림 (&mut T): 수정 가능하게 빌려줍니다. 오직 단 한 명에게만 빌려줄 수 있으며, 그동안 아무도 읽을 수 없습니다.

💡 빌림의 대원칙 (Data Race 방지)

"여러 명이 읽거나, 딱 한 명만 쓰거나." (동시에 두 가지는 안 됩니다.)


3. GC vs RAII (메모리 관리의 철학 차이)

특징C# (Garbage Collection)Rust (RAII / Ownership)
정리 시점불분명함 (GC가 판단할 때)결정론적 (스코프가 끝날 때 즉시)
런타임 비용GC 실행 시 일시 중단 발생제로 비용 (추가 오버헤드 없음)
리소스 정리using, Dispose() 필요Drop 트레이트가 자동으로 처리
데이터 경합런타임에 발생 가능컴파일 타임에 원천 차단

4. 이동 의미론(Move Semantics)과 Copy 타입

  • Move 타입: String, Vec 등 힙 메모리를 쓰는 타입. 대입 시 소유권이 넘어갑니다.
  • Copy 타입: i32, bool, f64 등 단순한 값. 대입 시 값이 복사되어 원본도 유지됩니다. (C#의 struct와 유사)

💡 실무 팁: "공짜" 참조를 활용하세요

C#에서는 객체를 넘길 때 항상 참조 오버헤드가 발생하지만, Rust의 소유권 모델은 컴파일러가 데이터의 흐름을 완벽히 파악하므로 불필요한 복사나 참조를 제거하여 네이티브 수준의 성능을 뽑아냅니다. 빌림 검사기(Borrow Checker)의 에러 메시지는 당신을 괴롭히는 것이 아니라, 미래의 버그(Null 참조, 데이터 경합)를 미리 막아주는 것입니다.