본문 바로가기

Rust

[Rust] 패턴 바인딩 (Pattern Binding)

 

안녕하세요.

오늘은 Rust의 패턴 바인딩 (Pattern Binding) 에 대해 알아보겠습니다.


서론

Rust를 공부하다가 다음과 같은 코드를 봤습니다.

fn main() {
    let x = Some(5);
    let y = 15;

    match x {
        Some(y) if y == 5 => println!("A, inner y: {}", y),
        _ => println!("B"),
    }

    println!("x, y: {}, {}", x.unwrap(), y);
}

 

처음에는 바깥의 y(=15) 와 비교한다고 생각했지만,

실제 출력은 다음과 같았습니다.

A, inner y: 5
x, y: 5, 15

 

예상과 달랐습니다.

이를 계기로 Rust의 패턴 바인딩 (Pattern Binding) 개념을 알게 되었습니다.


패턴 바인딩이란?

패턴 바인딩이란,

패턴에 매칭된 값을 새로운 변수에 연결(bind)하는 것

입니다.

 

다음 예제를 보겠습니다.

let x = Some(5);

match x {
    Some(y) => println!("{}", y),
    _ => {}
}

 

여기서 Some(y)는 단순히

“Some 안에 값이 있는가?” 를 검사하는 것이 아닙니다

 

의미는 다음과 같습니다

  • x가 Some인지 확인한다.
  • 내부 값을 꺼낸다.
  • 그 값을 새로운 변수 y에 바인딩한다. (y는 5가 됨)

즉, 이 코드는 ‘값 비교’가 아니라 ‘구조 분해 + 변수 생성’ 입니다


Rust에서 식별자는 기본적으로 ‘항상 새로운 변수 바인딩’ 입니다

 

따라서 Some(y)는 비교가 아니라:

Some(inner_value)

와 동일합니다.

 

그리고 내부적으로는 다음과 같은 동작이 이루어집니다.

let y = inner_value;

 

이때 기존에 같은 이름의 변수가 있다면, 그 변수는 가려지게 됩니다.

이것을 Shadowing 이라고 합니다.


 

패턴의 종류와 바인딩

패턴은 크게 다음과 같이 나눌 수 있습니다

 

1) 리터럴 패턴 (값 비교)

Some(50)

 

이 경우에는 실제로 값 50과 비교합니다

 

2) 변수 패턴 (바인딩)

Some(y)

 

항상 새로운 변수 바인딩입니다.

 

3) 와일드카드 패턴

_

 

값을 무시합니다. 바인딩하지 않습니다.

 

4) 구조 분해 패턴

struct Point { x: i32, y: i32 }

let p = Point { x: 1, y: 2 };

match p {
    Point { x, y } => println!("{} {}", x, y),
}

 

여기서 x, y 역시 새로 바인딩 됩니다.


 

Other Cases

패턴 바인딩은 match 에서만 일어나진 않습니다

아래 경우도 전부 바인딩 입니다

 

1) let

let (a, b) = (1, 2);

2) if let

if let Some(v) = x {
    println!("{}", v);
}

3) while let

while let Some(v) = iterator.next() {
    println!("{}", v);
}

4) 함수 파라미터

fn print_point((x, y): (i32, i32)) {
    println!("{} {}", x, y);
}

 

바인딩과 소유권 (Move / Borrow)

패턴 바인딩은 소유권과도 밀접한 관련이 있습니다.

let x = Some(String::from("hello"));

match x {
    Some(s) => println!("{}", s),
    None => {}
}

 

여기서 s는

  • String 타입 이므로 소유권을 가져옵니다 (move)
  • 따라서 이후에 x를 사용할 수 없습니다
error[E0277]: `Option<String>` doesn't implement `std::fmt::Display`
  --> src\\main.rs:14:20
   |
14 |     println!("{}", x);
   |               --   ^ `Option<String>` cannot be formatted with the default formatter
   |               |
   |               required by this formatting parameter
   |
   = help: the trait `std::fmt::Display` is not implemented for `Option<String>`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

 

만약 값을 소비하지 않고 참조만 하고 싶다면:

match &x {
    Some(s) => println!("{}", s),
    None => {}
}
  • 이 경우 s는 &String 타입이 되며,
  • borrow가 발생합니다.

 

Match Guard

바깥 변수를 비교하고 싶다면, 다음과 같이 사용할 수 있습니다

let x = Some(10);
let y = 10;

match x {
    Some(n) if n == y => println!("equal"),
    _ => {}
}
  • n은 새로 바인딩된 변수
  • if n == y 에서 바깥 변수 y를 사용

 

이것을 match guard 라고 합니다


 

@ 패턴

바인딩과 패턴 매칭을 동시에 하고 싶다면 @를 사용할 수 있습니다.

match x {
    val @ Some(5) => println!("{:?}", val),
    _ => {}
}
  • x를 Some(5)와 매칭
  • 전체 값을 val에 바인딩

 

그래서 다음 코드에서 출력 값은 이렇게 나옵니다

let x = Some(6);

match x {
    val @ Some(5) => println!("equals to 5, {:?}", val),
    val @ Some(6) => println!("equals to 6, {:?}", val),
    _ => println!("else branch")
}
equals to 6, Some(6)

 

정리

다시 처음 코드로 돌아가 보면

fn main() {
    let x = Some(5);
    let y = 15;

    match x {
        Some(y) if y == 5 => println!("A, inner y: {}", y),
        _ => println!("B"),
    }

    println!("x, y: {}, {}", x.unwrap(), y);
}
  • Some(y) 에서 y는 새로 바인딩 됩니다. (y=5)
  • if y == 5는 바인딩 된 y를 검사합니다.
  • match 블록이 끝나면, 바인딩된 y는 스코프를 벗어납니다.
  • 바깥 y는 여전히 15입니다.

 

따라서 출력이 이렇게 나옵니다.

A, inner y: 5
x, y: 5, 15

패턴 바인딩은

  • 값 비교가 아니라 구조 분해입니다.
  • 식별자는 기본적으로 새로운 변수 바인딩입니다.
  • 기존 변수와 이름이 같다면 shadowing이 발생합니다.
  • 소유권(move/borrow)과 직접 연결됩니다.
  • match뿐 아니라 let, if let, 함수 파라미터 등 다양한 곳에서 사용됩니다.

 

감사합니다.

'Rust' 카테고리의 다른 글

[Rust] 실제 코드로 확인해보는 Monomorphization  (0) 2026.02.18
[Rust] Generic Lifetime  (0) 2026.02.16
[Rust] unwrap 이해하기  (0) 2026.02.14
[Rust] 동시성  (0) 2025.04.27
[Rust] 컬렉션 (Collection)  (0) 2025.04.22