← Rust 강의 목록으로
🦀
기초
기초 · 선수: 01강

02. 변수·상수·섀도잉·타입 추론

Rust 의 변수는 기본적으로 불변(immutable) 입니다. mut 키워드로 명시해야 가변. 이런 디자인이 어떻게 멀티스레드 안정성과 코드 가독성을 동시에 끌어올리는지, 그리고 shadowing 이 어떻게 mut 없이도 값을 재사용하게 해 주는지 살펴봅니다. const 와 let 의 차이, 타입 어노테이션과 타입 추론도 함께 정리합니다.

Rust변수letmutconstshadowing타입 추론
소요 시간
약 1시간
난이도
📊 초급
선수 조건
🎯 01강
결과물
Rust 의 변수는 기본적으로 불변(immutable) 입니다. mut 키워드로 명시해야 가변. 이런 디자인이 어떻게 멀티스레드 안정성과 코드 가독성을 동시에 끌어올리는지, 그리고 shadowing 이 어떻게 mut 없이도 값을 재사용하게 해 주는지 살펴봅니다. const 와 let 의 차이, 타입 어노테이션과 타입 추론도 함께 정리합니다.

이 강의에서 배우는 것

  • 1let 으로 변수 바인딩을 만들고 기본이 불변임을 확인한다
  • 2mut 를 붙여 가변 변수로 전환한다
  • 3const 와 let 의 차이를 설명할 수 있다
  • 4shadowing 을 활용해 타입을 바꿔가며 값을 재사용한다
  • 5타입 어노테이션이 필요한 경우와 추론에 맡겨도 되는 경우를 구분한다

소개

다른 언어를 써 본 사람이 Rust 를 처음 만나서 가장 당황하는 지점이 이것입니다. `let x = 5; x = 6;` 가 컴파일 에러. 변수가 기본 불변이라는 것은 단순한 스타일 규칙이 아니라 **데이터 경합 방지의 출발점** 입니다. 멀티스레드에서 공유되는 값이 변경 불가하다는 사실이 컴파일 타임에 보장되면, 그것만으로 락의 절반은 필요 없어집니다.

핵심 개념

1) let — 변수 바인딩의 기본 형태

`let 이름 = 값;` 형태. 한 번 바인딩되면 재대입 불가.

rust
let x = 5;
x = 6; // error[E0384]: cannot assign twice to immutable variable `x`

2) mut — 가변으로 명시

`let mut 이름 = 값;` 형태. **선언 시점부터** 가변임을 명시해야 합니다.

rust
let mut x = 5;
x = 6;             // OK
println!("{}", x); // 6

3) const — 컴파일 타임 상수

  • 반드시 **타입 명시** 필요: `const PI: f64 = 3.14;`
  • 스코프 어디든 선언 가능 (모듈 최상단, 함수 안 등)
  • 값은 컴파일 타임에 평가 가능한 식이어야 함 (런타임 함수 호출 불가)
  • 관례상 **SCREAMING_SNAKE_CASE**

4) shadowing — 같은 이름으로 다시 바인딩

let 으로 같은 이름을 다시 선언하면 새 변수가 생기고 기존 것을 가립니다. **타입까지 바뀔 수 있다**는 것이 mut 와 결정적 차이.

rust
let spaces = "   ";
let spaces = spaces.len(); // &str -> usize 로 타입 변경 OK
println!("{}", spaces);    // 3
관점mutshadowing
같은 메모리 재사용✗ (새 바인딩)
타입 변경
스코프 끝나면 원복

핵심 예제

타입 추론과 명시의 조합 — 정수 리터럴은 기본 i32 이지만 어노테이션으로 강제 가능.

rust
fn main() {
    let a = 10;            // 추론: i32
    let b: i64 = 10;       // 명시: i64
    let c = 10_u8;         // 접미사 표기: u8
    let pi: f64 = 3.14;
    println!("a={}, b={}, c={}, pi={}", a, b, c, pi);
}

shadowing 으로 입력 파싱 흐름을 깔끔하게:

rust
fn main() {
    let input = "42";           // &str
    let input: i32 = input        // shadow -> i32
        .trim()
        .parse()
        .expect("숫자가 아닙니다");
    println!("{}", input + 1);   // 43
}

자주 하는 실수

Q. mut 가 붙으면 변수의 타입도 바꿀 수 있나요?

A. 아닙니다. mut 는 **값** 만 바꿀 수 있고 타입은 그대로입니다. 타입을 바꾸려면 shadowing 을 쓰세요.

Q. const 와 let 의 차이가 뭔가요?

A. const 는 컴파일 타임에 평가되며 항상 타입 명시 필요. let 은 런타임에 평가 가능한 임의의 식. 또 const 는 절대 변경 불가(mut const 같은 건 없음).

Q. 변수가 불변이면 너무 불편하지 않나요?

A. 의외로 일상 코드 80% 는 한 번 만들고 그대로 쓰는 값입니다. 정말 변경이 필요할 때만 mut 를 붙이면 코드 의도가 명확해지고, 멀티스레드 코드에서 안전성도 올라갑니다.

정리

  • let 은 기본 불변, 변경하려면 mut
  • const 는 컴파일 타임 상수, 타입 명시 필수
  • shadowing 은 새 바인딩이라 타입까지 바꿀 수 있다
  • 타입 추론이 강력하지만, 가독성·명시성을 위해 어노테이션을 쓰는 경우도 흔하다

과제

  1. 불변 변수에 재대입을 시도해 에러 메시지를 확인하고, mut 를 붙여 고친다
  2. shadowing 을 활용해 `" 3.14 "` 같은 문자열을 f64 로 파싱하는 코드를 작성한다
  3. const 로 원주율을 정의하고 함수 안에서 참조해 본다
예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗