rust borrowing

agnusdei·2025년 1월 24일

빌림의 핵심 개념

  1. 소유권(Ownership):

    • Rust에서 모든 값은 하나의 소유자(Owner)를 가집니다.
    • 소유자가 범위를 벗어나면(Rust에서는 이를 "스코프가 끝난다"고 표현) 메모리가 자동으로 해제됩니다.
  2. 빌림(Borrowing):

    • 데이터를 다른 변수나 함수에서 사용하고 싶을 때, 소유권을 넘기지 않고 데이터를 참조할 수 있습니다.
    • 빌림은 읽기 전용 또는 가변 참조로 이루어집니다.

빌림의 두 종류

1. 불변 참조(읽기 전용 Borrowing)

  • 데이터를 읽기만 하고 수정하지 않는 경우 사용.
  • 여러 개의 불변 참조를 동시에 허용.

규칙:

  • 불변 참조는 동시에 여러 개가 가능합니다.
fn main() {
    let s = String::from("Hello, Rust!"); // 소유자 s
    let r1 = &s; // r1은 불변 참조
    let r2 = &s; // r2도 불변 참조

    println!("r1: {}, r2: {}", r1, r2); // 동시에 읽기 가능
}

2. 가변 참조(수정 가능한 Borrowing)

  • 데이터를 수정하려면 가변 참조를 사용.
  • 단, 가변 참조는 한 번에 하나만 허용됩니다.

규칙:

  • 가변 참조는 한 번에 하나만 가능합니다.
  • 불변 참조와 가변 참조를 동시에 사용할 수 없습니다.
fn main() {
    let mut s = String::from("Hello"); // mut 키워드로 가변 변수 선언
    let r1 = &mut s; // r1은 가변 참조

    r1.push_str(", Rust!"); // 가변 참조를 통해 s를 수정
    println!("{}", r1); // "Hello, Rust!"
}

빌림이 필요한 이유

빌림은 메모리 안전성을 유지하면서도 데이터의 중복 사용을 가능하게 만듭니다. 아래에서 몇 가지 상황을 통해 빌림의 필요성을 이해해 보겠습니다.

1. 소유권이 이동하지 않도록 하려면 빌림이 필요

fn print_length(s: &String) { // &String은 빌림을 통해 데이터 접근
    println!("Length: {}", s.len());
}

fn main() {
    let s = String::from("Hello"); // 소유자
    print_length(&s); // 빌림
    println!("s: {}", s); // 소유권 유지 -> 여전히 s를 사용할 수 있음
}

위 코드에서 print_length 함수가 String을 빌려가기 때문에, 함수가 끝난 뒤에도 s의 소유권은 유지됩니다.


2. 불변성과 가변 참조를 동시에 사용하면 에러 발생

fn main() {
    let mut s = String::from("Hello");
    let r1 = &s;        // 불변 참조
    let r2 = &mut s;    // 가변 참조 (에러 발생!)

    println!("{}, {}", r1, r2);
}

위 코드는 불변 참조(r1)가변 참조(r2)가 동시에 존재하기 때문에 에러가 발생합니다. 이는 데이터 경합(Race Condition)을 방지하기 위한 Rust의 설계입니다.


3. 빌림 해제를 통한 안전한 동작

빌림은 스코프가 끝나면 해제됩니다. 즉, 더 이상 참조가 존재하지 않을 때, 새로운 참조를 만들 수 있습니다.

fn main() {
    let mut s = String::from("Hello");
    {
        let r1 = &mut s; // r1이 가변 참조
        r1.push_str(", Rust!");
    } // r1은 여기서 스코프 종료 -> 빌림 해제

    let r2 = &s; // 새로운 불변 참조 가능
    println!("{}", r2);
}

빌림의 이점

  1. 데이터 경합 방지:
    • Rust는 컴파일 타임에 참조 규칙을 강제하여 런타임 문제를 방지합니다.
  2. 명확한 메모리 관리:
    • 빌림이 끝나면 자동으로 해제되므로 불필요한 참조가 남지 않습니다.
  3. 소유권 유지:
    • 빌림을 통해 데이터를 안전하게 공유할 수 있으며, 소유권을 넘기지 않아도 됩니다.

빌림을 기억하기 쉬운 규칙으로 요약

  1. 불변 참조는 여러 개 가능하지만, 가변 참조는 한 번에 하나만 허용됩니다.
  2. 불변 참조와 가변 참조는 동시에 존재할 수 없습니다.
  3. 참조는 스코프가 끝나면 해제됩니다.

빌림의 규칙은 Rust가 안전하고 오류가 적은 코드를 작성하도록 돕는 중요한 원칙입니다. 초반에는 약간 복잡하게 느껴질 수 있지만, 익숙해지면 Rust의 강력함을 느낄 수 있는 핵심 개념입니다!

profile
DevSecOps, Pentest, Cloud(OpenStack), Develop, Data Engineering, AI-Agent

0개의 댓글