Rust에서의 Borrowing(차용)은 변수에 대한 참조를 통해 임시로 "빌리는" 메커니즘입니다. Rust는 불변 차용(&T)과 가변 차용(&mut T)을 구분합니다. 동시에 여러 개의 불변 참조가 존재할 수 있지만, 가변 참조는 하나만 존재할 수 있습니다. 한 객체에 대해 가변 참조와 불변 참조가 동시에 존재하는 것은 허용되지 않습니다.
이 규칙은 컴파일 단계에서 데이터 경쟁이 발생하지 않도록 보장하며, Rust를 안전한 병렬 프로그래밍 언어로 만듭니다.
예시:
let mut value = 5; let r1 = &value; let r2 = &value; // let r3 = &mut value; // 오류: &가 있는 동안 &mut를 생성할 수 없음 println!("{} {}", r1, r2); // r3는 r1/r2의 유효 범위가 끝날 때까지 금지됨
질문: 같은 유효 범위 내에서 하나의 &mut 참조와 여러 개의 & 참조를 하나의 객체에 대해 생성할 수 있나요?
전형적인 잘못된 답변: 네, 하지만 그들이 생존 기간에 겹치지 않는다면 가능합니다.
올바른 답변: 동일한 객체에 대해 가변 참조와 불변 참조가 동시에 존재할 수 없습니다(코드에서 정적으로 접근이 겹치지 않는 경우에도 마찬가지입니다). 하나가 살아 있는 동안 다른 것은 금지됩니다. 안전성은 borrow checker에 의해 검증됩니다.
예시:
let mut x = 10; let y = &x; let z = &mut x; // 오류, y가 여전히 유효 범위에 있음 println!("{}", y); // y는 나중에 필요함
이야기
대규모 데이터 병렬 처리 프로젝트에서 개발자는 벡터에 대한 불변 참조를 사용하기로 결정한 후 정렬을 위해 가변 참조를 얻으려고 시도했습니다. 코드는 테스트에서 작동했지만, 리팩토링 후 불변 참조의 생존 기간이 늘어나면서 더 이상 컴파일되지 않았습니다.
이야기
내부 서비스에서는 &mut를 통해 구조를 수정하면서 필드를 다른 스레드로 전송하기 위해 참조를 유지했습니다. 차용 규칙을 준수하지 않아 데이터 경쟁과 충돌이 발생했습니다. Rust는 이를 컴파일 단계에서만 보호하며, 오류는 안전하지 않은 블록에서 발생하여 보장이 없었습니다.
이야기
API 문서화 오류: 라이브러리는 구조체의 서로 다른 필드에 대해 동시에 &와 &mut를 받을 수 있었지만, aliasing으로 인해 불변성이 위배되어 이 라이브러리를 통합한 서비스에서 찾기 힘든 버그가 발생했습니다.