본문 바로가기
08.개발&프로그래밍/4.Rust(러스트)

5장: 소유권(Ownership)과 빌림(Borrowing)

by JWJ Family 2025. 7. 28.
728x90

Garbage Collector 없이도 런타임 오류를 막아 주는 Rust의 비밀은 소유권(Ownership), 빌림(Borrowing), 라이프타임(Lifetime)이라는 세 규칙입니다. 이 장에서는 메모리가 누구의 것인지를 명확히 기록하고, 필요할 때만 안전하게 빌려 쓰며, 빌림이 유효한 기간을 컴파일 타임에 증명하는 Rust만의 설계를 단계별로 배웁니다. 


5-1. Rust의 핵심: 소유권(Ownership) 개념

① 세 가지 기본 규칙

  • 모든 값은 하나의 변수만이 소유한다. 
  • 값은 스코프를 벗어나면 자동으로 drop 되어 자원이 해제된다.
  • 소유권은 변수 대입이나 함수 호출 시 이동(move)한다. 

② Move vs Copy

스택 기반 정수·불리언처럼 Copy 트레이트가 구현된 타입은 값이 그대로 복사되지만, String·Vec 처럼 힙을 소유한 타입은 move 되어 원본 변수를 더 이상 사용할 수 없습니다. 

let s1 = String::from("hi");
let s2 = s1;          // s1  →  s2 (move)
// println!("{s1}");  // ❌ use of moved value 컴파일 오류 :contentReference[oaicite:5]{index=5}

③ 함수 호출 시 소유권 흐름

fn consume(v: Vec) { /* v drop */ }

fn main() {
    let data = vec![1, 2, 3];
    consume(data);    // data 이동
    // data 사용 불가
}

5-2. 빌림(Borrowing)과 가변 빌림

① 불변 참조(&)

불변 참조는 여러 개 동시에 허용되며 데이터를 읽기 전용으로 빌립니다. 

② 가변 참조(&mut)

가변 참조는 동시에 하나만 허용돼 데이터 레이스를 컴파일 타임에 원천 차단합니다. 

let mut msg = String::from("hello");
let r1 = &msg;          // 불변
let r2 = &msg;
// let r3 = &mut msg;   // ❌ r1,r2 생존 → 가변 빌림 불가
println!("{r1}, {r2}");
let r3 = &mut msg;      // OK: r1,r2 범위 종료
r3.push_str(" 🦀");

③ 빌림 검사기(Borrow Checker)

Rust 컴파일러는 빌림 규칙 위반(두 개의 동시 가변 참조 등)을 정적 분석으로 차단하여 data race를 예방합니다. 


5-3. 라이프타임(Lifetime) 기본 이해

① 라이프타임이 필요한 이유

참조 인자 간 유효 기간이 모호할 때, 제네릭 라이프타임 파라미터 (&'a T)로 관계를 명시해 안전성을 증명합니다. 

② 함수에 라이프타임 표기

// 두 문자열 중 더 긴 값을 반환
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

③ 구조체·메서드와 라이프타임

struct Word<'a> { text: &'a str }

impl<'a> Word<'a> {
    fn len(&self) -> usize { self.text.len() }
}

5-4. 종합 실습: 안전한 로그 시스템 만들기

fn add_entry<'a>(log: &'a mut Vec, msg: &str) -> &'a str {
    log.push(String::from(msg));   // 가변 빌림
    &log[log.len()-1]              // 같은 라이프타임 'a
}

fn main() {
    let mut history = Vec::new();
    let last = add_entry(&mut history, "Start");
    println!("마지막 기록: {last}");
}

출력 결과

마지막 기록: Start

5-5. 오늘 배운 핵심 요약

  • 값은 오직 하나의 소유자만 가진다(Ownership).
  • 읽기 참조는 다수, 가변 참조는 단독(Borrowing 규칙).
  • 라이프타임 표기로 참조의 유효 범위를 명확히 한다(Lifetime).

다음 6장에서는 fn, mod, pub, use를 활용해 코드를 레고 블록처럼 구조화하는 방법을 알아봅니다!

반응형