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의 단일 소유권 원칙이 한계에 부딪힐 때 사용하는 스마트 포인터들을 마스터합니다. 힙 할당(Box), 공유 소유권(Rc/Arc), 내부 가변성(RefCell), 그리고 효율적인 리소스 관리를 위한 CowDrop 트레이트를 배웁니다.


1. Box<T>: 단순한 힙 할당

C#의 모든 클래스 인스턴스는 힙에 저장되지만, Rust는 스택이 기본입니다. Box<T>를 사용하여 명시적으로 데이터를 힙으로 보낼 수 있습니다. 주로 재귀적 데이터 구조트레이트 객체를 만들 때 사용합니다.

#![allow(unused)]
fn main() {
// [C# 스타일의 객체 생성과 유사]
let b = Box::new(42); // 42라는 값을 힙에 저장하고 포인터를 스택에 둠
}

2. Rc<T>Arc<T>: 공유 소유권

데이터를 여러 곳에서 동시에 소유해야 할 때(예: 그래프 구조, 공유 설정값) 사용합니다.

  • Rc<T>: 단일 스레드용. 참조 횟수를 기록하여 마지막 주인이 사라질 때 메모리를 해제합니다.
  • Arc<T>: 멀티 스레드용. 원자적(Atomic) 연산을 사용하여 여러 스레드 간에 안전하게 공유합니다.

3. 내부 가변성: RefCell<T>Mutex<T>

불변 참조(&self) 뒤에 있는 데이터를 수정해야 할 때 쓰는 '치트키'입니다.

  • RefCell<T>: 런타임에 빌림 검사를 수행합니다. 단일 스레드에서 유용합니다.
  • Mutex<T> / RwLock<T>: 스레드 안전한 수정을 가능하게 합니다.
#![allow(unused)]
fn main() {
// [불변 참조임에도 데이터를 수정하는 예시]
let logger = Logger { entries: RefCell::new(vec![]) };
logger.entries.borrow_mut().push("로그 기록".to_string());
}

4. Drop: Rust의 IDisposable

C#의 using 블록이나 Dispose() 호출을 잊어버려 리소스가 새는 걱정을 하셨나요? Rust는 Drop 트레이트를 통해 값이 스코프를 벗어나는 순간 관련 리소스를 확정적으로 정리합니다.

  • RAII 패턴: "리소스 획득은 초기화이며, 수명 종료는 곧 반납이다."

💡 스마트 포인터 선택 가이드

  1. 단순 힙 할당이 필요하다면? → Box<T>
  2. 단일 스레드에서 소유권을 공유한다면? → Rc<T>
  3. 멀티 스레드에서 소유권을 공유한다면? → Arc<T>
  4. 불변 참조로 데이터를 고쳐야 한다면? → RefCell<T> (단일) 또는 Mutex<T> (멀티)
  5. 읽기 우선이지만 가끔 수정하고 싶다면? → Cow<'a, T>