러스트의 고유 개념은 아니지만, 프로그래밍에 필요한 개념을 다룰 것이다.
특히 변수, 기본 타입, 함수, 주석, 제어 흐름은 모든 러스트 프로그램에서 기초적으로 알아야하는 개념이다.
러스트에서의 변수는 기본적으로 불변(immutable)이다.
불변인 이유는 안정성과 쉬운 동시성을 활용하는 방식으로 코드를 작성하도록 하는 넛지 (nudge, 슬며시 선택 유도하기) 중 하나다.
그럼에도 앞에서 본 것처럼 가변(mutable)도 가능하다.
왜 러스트가 불변성을 권하는지, 언제 가변을 사용해야 하는지 알아보자.
먼저 $ cargo new variables로 프로젝트를 생성하고 src/main.rs를 다음처럼 고친다.
fn main() {
let x = 5;
println!("The value of x is: {x}");
x = 6;
println!("The value of x is: {x}");
}
이후에 $ cargo run을 실행하면 불변성 관련 에러 메시지를 받을 수 있다.

사진에서처럼 cannot assign twice to immutable variable 에러가 발생했는데, 불변으로 선언된 변수의 값을 바꿀려고 해서이다.
코드를 작성하다 보면, 안 바뀌어야하는 값을 모르고 중간에 바꾸어 버려 버그가 발생하는 경우가 많고, 이 경우에는 어디서 잘못되었는지 찾는 것이 매우 어렵다.
하지만, 러스트는 불변, 가변을 나눔으로써 한 번 불변으로 선언된 것은 값이 바뀌지 않음을 보장한다.
물론, 가변 변수도 매우 유용하게 많이 사용되기 때문에, mut를 추가함으로써 변수를 가변으로 선언할 수 있고, 이 방식은 다른 사람이 내 코드를 읽었을 때 명시적으로 가변임을 알려줄 수 있기 때문에도 유용하다.
src/main.rs 코드를 다음처럼 개선하자.
fn main() {
let mut x = 5;
println!("The value of x is: {x}");
x = 6;
println!("The value of x is: {x}");
}
지금은 mut로 x를 선언했기 때문에 정상적으로 컴파일되고 결과도 출력한다.
이 코드의 결과는 다음과 같다.
The value of x is: 5
The value of x is: 6
상수(constant)는 불변 변수와 비슷하지만, 약간 다른 점도 있다.
mut와 함께 사용할 수 없다. 상수는 항상 불변이다.let 대신에 const 키워드로 선언하고 값의 타입이 반드시 명시되어야 한다.러스트에서는 반드시 상수는 대문자로 이름을 짓고 단어 사이에는 밑줄을 사용한다.
예를 들어, 코드에서 10,800이라는 숫자를 고정적으로 사용해야 한다고 했을 때, 당장 코드를 작성하는 사람은 왜 10,800을 사용했는지, 이것이 어떤 의미인지를 알 수 있지만, 미래에 코드를 보는 사람은 이 숫자가 어떤 의미인지, 왜 10,800인지 모른다. 그렇기 때문에 상수로 선언하면 이 숫자가 어떤 의미인지, 왜 사용했는지 전달하는데 유용하다.
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
앞에서 본 것처럼 새 변수를 이전 변수명과 같은 이름으로 선언할 수 있다.
첫 번째 변수가 두 번째 변수에 의해 가려졌다(shadowed)라고 표현하고 해당 변수명을 사용할 때
컴파일러가 두 번째 변수를 보게 될 것임을 의미한다.
하지만, 주의할 점은 코드 진행 중에 특정 함수 안에서 섀도잉을 했다면, 해당 함수에서는 섀도잉한 두 번째 값으로 사용되지만, 함수를 벗어난 이후에는 다시 섀도잉 전의 값을 사용한다는 점이다.
다음 코드를 한 번보자.
fn main() {
let x = 5;
let x = x + 1;
{
let x = x * 2;
println!("The value of x in the inner scope is: {x}");
}
println!("The value of x is: {x}");
}
먼저 x에 5를 불변으로 묶고, 그 이후에 다시 x에 6을 불변으로 묶는다.
안쪽 스코프에서는 x가 12로 불변으로 묶이고 첫 번째 출력에서는 12를 출력한다.
다시 바깥쪽 스코프로 나가면 섀도잉이 끝나고, x는 다시 6으로 돌아온다.
실행 결과는 다음과 같다.
The value of x in the inner scope is: 12
The value of x is: 6
mut와는 다른게 mut는 계속 값을 수정할 수 있고, 섀도잉은 섀도잉한 이후에 다른 섀도잉이 없으면 현재 값을 유지한다는 점이다.
또 다른 차이점은 mut와 다르게 let 키워드를 통해 다른 타입으로 지정할 수 있다는 점이다.
다음 예제 코드를 통해서 보자
let spaces = " ";
let spaces = spaces.len();
첫 번째 spaces는 문자열이고 두 번째는 숫자 타입이다.
여기서 mut를 사용하면 변수 타입을 바꿀 수 없다는 에러를 출력하게 된다.