Rust의 참조(Reference)와 대여(Borrowing)는 메모리 안전성을 보장하는 핵심 개념입니다. 이를 통해 데이터를 소유권 없이 효율적으로 사용할 수 있습니다. 아래에서 관련 개념을 차근차근 설명하겠습니다.
참조는 데이터를 직접 소유하지 않고, 해당 데이터를 가리키는 포인터와 같은 역할을 합니다. 참조는 &를 사용하여 생성됩니다.
let s1 = String::from("hello");
let r = &s1; // s1을 참조
println!("{}", r); // r을 통해 s1에 접근
대여는 참조를 생성하여 데이터를 소유권 없이 빌려주는 과정을 의미합니다. 대여는 두 가지 형태로 나뉩니다.
let s1 = String::from("hello");
let r1 = &s1; // 불변 참조 1
let r2 = &s1; // 불변 참조 2
println!("{}, {}", r1, r2); // r1과 r2를 통해 데이터를 읽음
let mut s1 = String::from("hello");
let r = &mut s1; // 가변 참조
r.push_str(", world!"); // 가변 참조를 통해 값 변경
println!("{}", r); // 변경된 값 출력
Rust의 안전한 메모리 관리를 위해 다음 규칙을 따릅니다:
1. 여러 불변 참조를 동시에 생성할 수 있습니다.
2. 가변 참조는 한 번에 하나만 생성할 수 있습니다.
3. 불변 참조와 가변 참조는 동시에 사용할 수 없습니다.
4. 참조는 데이터를 소유하지 않으므로 원본 데이터는 여전히 유효합니다.
불변 참조와 가변 참조는 동시에 사용할 수 없지만, 불변 참조의 사용이 끝난 후에는 가변 참조를 생성할 수 있습니다. 이는 Rust의 스코프 규칙 때문입니다.
let mut s1 = String::from("hello");
// 불변 참조
let r1 = &s1;
println!("{}", r1); // r1 사용 완료
// r1의 사용이 끝났으므로 가변 참조 생성 가능
let r2 = &mut s1;
r2.push_str(", world!");
println!("{}", r2);
r1이 불변 참조로 데이터를 읽습니다.println! 이후, r1의 사용이 끝나므로 r2라는 가변 참조를 생성할 수 있습니다.let mut s1 = String::from("hello");
let r1 = &s1; // 불변 참조
let r2 = &mut s1; // 에러 발생: 불변 참조가 사용 중인데 가변 참조 생성 시도
println!("{}", r1); // r1이 사용되므로 에러 원인
r1이 여전히 사용 중인데, 가변 참조 r2를 생성하려고 했습니다.&) &mut) &): 읽기 전용. 여러 개 허용. &mut): 읽기/쓰기 가능. 단, 한 번에 하나만 허용.