Rust에서는 데이터 구조체가 기본적으로 불변입니다. 이는 mut 키워드 없이 선언된 모든 변수나 참조가 초기화 후 변경될 수 없음을 의미합니다.
let mut value = 10; // 가변 변수 value += 5; let value2 = 10; // 불변 변수 // value2 += 5; // 컴파일 오류: cannot assign twice to immutable variable
같은 논리는 구조체의 필드에도 적용됩니다:
struct Point { x: i32, y: i32 } let mut pt = Point { x: 1, y: 2 }; pt.x = 5; // OK, pt가 mut로 선언되었으므로
그러나 가변성은 변수의 "최상위" 수준에만 영향을 미칩니다. 만약 구조체가 불변 참조로 저장된다면, 구조체 내부에 mut가 선언되어 있더라도 구조체의 데이터를 변경할 수 없습니다.
제한을 우회하는 또 다른 방법은 RefCell<T>와 같은 특수 타입이나 원자적 컨테이너를 사용하는 것입니다. 이는 **"내부 가변성" (interior mutability)**을 통해 불변으로 보이는 컨테이너 내에서 데이터를 변경할 수 있게 합니다. 예를 들어:
use std::cell::RefCell; struct Counter { count: RefCell<i32>, } let counter = Counter { count: RefCell::new(0) }; *counter.count.borrow_mut() += 1; // 안전함, mut 없음에도 불구하고
질문: 구조체 변수가 mut로 선언되지 않았지만 구조체의 필드가 명시적으로 mut로 선언된 경우 그 필드의 값을 변경할 수 있나요?
일반적인 잘못된 답변: 네, 필드가 mut로 선언되면 변경할 수 있습니다.
올바른 답변: mut 키워드는 구조체 필드 선언에 사용할 수 없습니다. 가변성은 변수 자체나 얻어진 참조에만 적용됩니다. 구조체의 필드를 수정하려면, 변수를 mut로 선언하거나 "내부 가변성" 타입을 사용해야 합니다 (예: RefCell).
예시:
struct Foo { val: i32 } // 필드는 mut 없이 선언됨 let mut foo = Foo { val: 1 }; foo.val = 2; // OK let foo2 = Foo { val: 3 }; foo2.val = 4; // 오류! 변수는 mutable이 아님
이야기
대형 프로젝트에서 한 개발자가 구조체 필드를 수정하려고 했으나 필드를 mut로 선언한다고 해서 필요한 가변성이 부여된다고 생각했습니다. 이는 컴파일되지 않았고, 구조체가 아닌 변수의 소유에 대한 가변성이 특징이라는 것을 설명하는데 몇 시간이 걸렸습니다.
이야기
멀티스레딩과 관련된 프로젝트에서 모든 데이터 접근 제어 논리가 전역 정적 구조체에 있었습니다.
RefCell을 통한 "내부 가변성"을 알지 못해 팀은Arc<Mutex<T>>또는RwLock<T>를 통한 간단한 해결책 대신 과도하게 복잡한 잠금 및 경쟁 메커니즘을 작성했습니다.
이야기
개발자가 함수 시그니처에서 인수를 mut로 선언하는 것을 잊어버려, 함수가 전달된 구조체를 변경할 수 없었습니다. 그 결과 이 버그는 실제 운영 환경에서만 나타났습니다 (함수 호출 후 데이터가 업데이트되지 않음). 기본적으로 불변 참조로 전달된다는 것을 알고 있었다면 초기 단계에서 오류 없이 문제를 해결할 수 있었을 것입니다.