[Rust] 변수와 가변성: 불변 변수, mut, 상수, 섀도잉
이 글은 The Rust Programming Language 3.1장 "Variables and Mutability"을 읽고 정리한 내용이에요. 예제도 이 장의 예제를 바탕으로 했어요.
Rust의 가장 기초인 변수와 가변성, 그리고 상수와 섀도잉을 정리해 볼게요.
변수는 기본적으로 바꿀 수 없어요 (Immutability)
Rust에서 let으로 선언한 변수는 기본적으로 불변(immutable) 이에요. 한 번 값을 정하면 나중에 바꿀 수 없다는 뜻이에요. 이렇게 만든 이유는 데이터의 안정성 때문이에요. 코드 한쪽은 값이 그대로라고 가정하는데 다른 쪽에서 값을 바꾸면 버그가 생기기 쉬워요.
예시를 볼게요. 이 코드는 컴파일되지 않아요.
fn main() {
let x = 5;
println!("x의 값: {x}");
x = 6; // 여기서 에러 발생!
println!("x의 값: {x}");
}
컴파일하면 error[E0384]: cannot assign twice to immutable variable x``(불변 변수 x에 두 번 할당할 수 없다는 에러)가 나요.
값을 바꿔야 할 때: mut 키워드
프로그램을 만들다 보면 값이 바뀌어야 하는 상황이 생겨요. 그럴 때는 변수 이름 앞에 mut 키워드를 붙이면 돼요. "이 변수는 앞으로 값이 바뀔 수 있다"고 미리 선언하는 거예요.
fn main() {
let mut x = 5;
println!("처음 x의 값: {x}");
x = 6; // 이제 가능해요!
println!("바뀐 x의 값: {x}");
}
mut를 쓰면 나중에 코드를 읽는 사람도 "x는 중간에 값이 바뀌는 변수구나"라고 바로 알 수 있어요.
바뀌지 않는 값: 상수 (Constants)
변수와 비슷해 보이지만 더 엄격한 게 상수(constants) 예요. 상수는 const 키워드로 선언해요.
변수와 다른 점은 세 가지예요.
mut를 쓸 수 없어요. 항상 불변이에요.- 타입을 반드시 적어야 해요. (
u32같은 타입은 다음 장에서 다뤄요.) - 실행 중에 계산되는 값은 넣을 수 없고, 컴파일 시점에 계산할 수 있는 값만 넣을 수 있어요.
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
이름은 보통 전부 대문자로 쓰고 단어 사이를 밑줄(_)로 이어요. 게임의 최대 점수나 빛의 속도처럼 프로그램 어디서든 바뀌지 않는 값을 정할 때 써요.
같은 이름을 다시 쓰는 섀도잉 (Shadowing)
Rust에는 섀도잉(shadowing) 이라는 개념이 있어요. 이미 쓴 변수 이름을 let으로 다시 선언하는 거예요. 그러면 뒤에 선언한 변수가 앞의 변수를 가려요.
fn main() {
let x = 5;
let x = x + 1; // 5 + 1 = 6
{
let x = x * 2; // 6 * 2 = 12
println!("안쪽 중괄호에서의 x 값: {x}");
}
println!("바깥쪽 x 값: {x}"); // 다시 6이 출력돼요
}
mut와 섀도잉은 뭐가 다를까요?
- 타입을 바꿀 수 있어요: 섀도잉은 이름은 같지만 타입이 다른 새 변수를 만들 수 있어요. 예를 들어 공백 문자열
" "을 받아서 그 길이인 숫자3으로 바꿔 같은 이름에 다시 담을 수 있어요.mut로는 타입을 바꿀 수 없어요. - 불변성이 유지돼요: 섀도잉은 새 변수를 만드는 거라서, 값을 바꾼 뒤에도 그 변수는 다시 불변이에요.
요약
| 개념 | 설명 |
|---|---|
| Immutability | Rust 변수는 기본적으로 불변이에요. 코드의 안정성을 높여 줘요. |
mut | 변수 이름 앞에 붙여서 값을 바꿀 수 있게 해요. |
| Constants | const로 선언하고, 바뀌지 않는 고정값에 써요. 타입을 반드시 적어야 해요. |
| Shadowing | let으로 같은 이름을 다시 선언해요. 타입을 바꿀 수 있어요. |