← SEARCHABLE ARCHIVE
Rust · 2026-08-08

Rust 기초부터 마스터까지 — 8화

Box, Rc, Arc로 소유 구조 선택하기

INTERACTIVE READING MODE →

본 블로그 작성 글들은, 강의를 목표로 하고 제작되었습니다. 또한 작성된 글의 정보도 틀렸을 수 있으니, 주의해주세요.

대부분의 값은 지역 변수와 컬렉션만으로 소유할 수 있다. 힙에 고정하거나 여러 소유자가 공유해야 할 때는 목적에 맞는 스마트 포인터를 선택한다.

Box

enum Node {
    Value(i32, Box<Node>),
    End,
}

let list = Node::Value(
    10,
    Box::new(Node::Value(20, Box::new(Node::End))),
);

재귀 타입은 다음 값의 크기를 컴파일할 때 바로 알 수 없다. Box는 값을 힙에 두고 현재 타입에는 고정 크기의 포인터를 저장한다.

Box라고 자동으로 공유되는 것은 아니며 기본 소유자는 여전히 하나다.

Rc와 Arc

use std::rc::Rc;

let data = Rc::new(String::from("ItemTable"));
let ui_data = Rc::clone(&data);
let game_data = Rc::clone(&data);

Rc는 단일 스레드에서 같은 값을 여러 곳이 소유하게 한다. 마지막 Rc가 사라질 때 값이 정리된다.

여러 스레드에서 공유하려면 원자적 참조 횟수를 사용하는 Arc가 필요하다. Rc와 Arc는 기본적으로 내부 값을 변경 가능하게 만들지 않는다.

내부 가변성

use std::cell::RefCell;
use std::rc::Rc;

let score = Rc::new(RefCell::new(0));
*score.borrow_mut() += 10;

RefCell은 빌림 규칙을 컴파일 시간이 아니라 실행 시간에 확인한다. 동시에 잘못 빌리면 프로그램이 panic하므로 컴파일 검사가 사라진 것이 아니다.

스레드 사이에서는 보통 Arc와 Mutex를 조합해 변경 접근을 동기화한다.

스마트 포인터를 많이 겹치면 소유 구조를 이해하기 어려워진다. Box는 단독 힙 소유, Rc는 단일 스레드 공유, Arc는 스레드 간 공유라는 목적부터 확인하고 가장 단순한 타입을 선택해야 한다.