Rust의 패턴 매칭 깊게 파헤쳐보기
Emily Parker
Product Engineer · Leapcell

소개
Rust에서 패턴 매칭은 다양한 패턴에 따라 다른 작업을 수행할 수 있는 강력한 언어 기능입니다. 패턴 매칭은 열거형 타입 작업, 튜플 및 구조체 해체, 조건식 처리 등 다양한 시나리오에서 사용될 수 있습니다. 이 기사에서는 Rust의 패턴 매칭 구문에 대한 자세한 소개와 예제 코드를 통해 사용법과 장점을 보여줍니다.
기본 사용법
Rust는 패턴 매칭에 match
키워드를 사용합니다. match
표현식은 여러 개의 암(arm)으로 구성되며, 각 암은 패턴과 패턴이 일치할 때 실행할 코드 블록을 포함합니다. Rust는 암을 순서대로 평가하고 첫 번째로 일치하는 패턴에 해당하는 블록을 실행합니다. 간단한 예는 다음과 같습니다.
fn main() { let number = 3; match number { 1 => println!("One"), 2 => println!("Two"), 3 => println!("Three"), _ => println!("Other"), } }
위 코드에서 number
변수를 정의하고 값 3을 할당합니다. 그런 다음 match
표현식을 사용하여 number
에 대해 매칭합니다. 먼저 Rust는 패턴 1
을 가진 첫 번째 암을 확인합니다. number
가 1이 아니므로 해당 암은 건너뜁니다. 두 번째 암 2
로 진행하지만 이 역시 일치하지 않습니다. 마지막으로 세 번째 암 3
을 확인하고, 이것이 일치하므로 블록을 실행하고 Three
를 출력합니다.
어떤 패턴도 일치하지 않으면 마지막 밑줄 _
이 다른 언어의 default
와 유사한 기본 케이스 역할을 하며 해당 블록을 실행합니다.
열거형 타입 매칭
Rust에서 열거형은 여러 개의 다른 베리언트 중 하나가 될 수 있는 값을 정의할 수 있는 타입입니다. 패턴 매칭은 열거형을 처리하는 가장 일반적인 방법 중 하나이며, 베리언트에 따라 다른 로직을 실행할 수 있습니다.
세 개의 다른 베리언트인 Move
, Write
, ChangeColor
를 가진 Message
라는 열거형을 정의하는 다음 예제를 고려해 보세요.
enum Message { Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), }
이제 match
표현식을 사용하여 Message
의 다양한 베리언트를 처리합니다.
fn process_message(msg: Message) { match msg { Message::Move { x, y } => println!("Move to coordinates (x={}, y={})", x, y), Message::Write(text) => println!("Write: {}", text), Message::ChangeColor(r, g, b) => println!("Change color to (r={}, g={}, b={})", r, g, b), } } fn main() { let msg1 = Message::Move { x: 10, y: 20 }; let msg2 = Message::Write(String::from("Hello, world!")); let msg3 = Message::ChangeColor(255, 0, 0); process_message(msg1); process_message(msg2); process_message(msg3); }
위 코드에서 Message
열거형을 파라미터로 받는 함수 process_message
를 정의합니다. match
표현식 내에서 다양한 열거형 베리언트를 다른 로직으로 처리합니다. Message::Move
베리언트의 경우, 패턴을 해체하여 x
와 y
를 가져온 다음 좌표를 출력합니다. Message::Write
의 경우 문자열을 직접 출력합니다. Message::ChangeColor
의 경우 r
, g
, b
를 해체하고 RGB 값을 출력합니다.
main
함수에서 세 개의 다른 Message
값을 생성하고 처리를 위해 process_message
에 전달합니다. 베리언트에 따라 다른 로직이 실행됩니다.
구조체 해체 및 매칭
열거형 외에도 Rust는 구조체 해체 및 매칭을 지원합니다. 구조체는 여러 필드로 구성된 사용자 정의 데이터 타입입니다. 패턴을 사용하여 구조체를 해체하고 필드 값을 기반으로 작업을 실행할 수 있습니다.
다음 예제를 고려해 보세요. 여기서 Point
라는 구조체를 정의하여 2D 공간의 점을 나타냅니다.
struct Point { x: i32, y: i32, }
이제 match
표현식을 사용하여 다양한 Point
구조체를 해체하고 매칭합니다.
fn process_point(point: Point) { match point { Point { x, y } => println!("Point coordinates: x={}, y={}", x, y), } } fn main() { let p1 = Point { x: 10, y: 20 }; let p2 = Point { x: -5, y: 15 }; process_point(p1); process_point(p2); }
위 코드에서 Point
를 파라미터로 받는 함수 process_point
를 정의합니다. match
표현식에서 Point { x, y }
패턴을 사용하여 구조체의 필드를 해체하고 출력합니다.
main
함수에서 두 개의 다른 Point
인스턴스를 생성하고 process_point
에 전달합니다. 패턴 매칭을 통해 구조체 필드에 쉽게 접근하고 작업할 수 있습니다.
if let
을 사용한 매칭 단순화
경우에 따라 특정 패턴이 일치하는지 여부만 신경 쓰고 다른 패턴을 처리할 필요가 없는 경우가 있습니다. 이러한 경우 if let
표현식을 사용하면 매칭 프로세스를 단순화할 수 있습니다.
두 개의 베리언트인 Number
와 Text
를 가진 Value
라는 열거형을 정의하는 다음 예제를 고려해 보세요.
enum Value { Number(i32), Text(String), }
이제 if let
을 사용하여 Value
인스턴스가 Number
인지 확인합니다.
fn main() { let value = Value::Number(42); if let Value::Number(n) = value { println!("The value is a number: {}", n); } else { println!("The value is not a number"); } }
위 코드에서 Value
변수를 정의하고 Value::Number(42)
를 할당합니다. 그런 다음 if let
을 사용하여 Number
베리언트인지 확인합니다. 그렇다면 숫자를 해체하고 출력합니다. 그렇지 않으면 숫자가 아니라는 메시지를 출력합니다.
if let
을 사용하면 특히 하나의 패턴만 관심이 있을 때 코드를 더 간결하고 읽기 쉽게 만들 수 있습니다.
여러 패턴 매칭
때로는 여러 패턴을 일치시키고 동일한 코드 블록을 실행하고 싶을 수 있습니다. Rust는 |
연산자를 제공하여 단일 암에서 여러 패턴을 일치시킵니다.
변수 number
를 정의하고 여러 패턴을 매칭하는 다음 예제를 고려해 보세요.
fn main() { let number = 42; match number { 0 | 1 => println!("Zero or one"), 2 | 3 | 4 => println!("Two, three, or four"), _ => println!("Other"), } }
위 코드에서 match
를 사용하여 number
를 평가합니다. 첫 번째 암은 0 | 1
을 사용하여 0과 1을 모두 일치시킵니다. 두 번째 암은 2 | 3 | 4
를 사용하여 2, 3, 4를 일치시킵니다. 마지막 밑줄 _
은 다른 모든 값에 대한 기본 케이스 역할을 합니다.
|
연산자는 여러 값을 깔끔하게 일치시키고 코드 중복을 방지하는 데 도움이 됩니다.
if let
및 while let
match
외에도 Rust는 조건부 패턴 매칭을 위해 if let
과 while let
을 제공합니다.
if let
표현식은 매칭을 수행하고 조건이 참이면 블록을 실행합니다. 일치하지 않으면 아무 일도 일어나지 않습니다.
while let
표현식은 if let
과 유사하게 작동하지만 패턴이 일치하는 한 루프에서 프로세스를 반복합니다.
다음은 둘 다 보여주는 예입니다.
fn main() { let values = vec![Some(1), Some(2), None, Some(3)]; for value in values { if let Some(num) = value { println!("Number: {}", num); } else { println!("None"); } } let mut values = vec![Some(1), Some(2), None, Some(3)]; while let Some(value) = values.pop() { if let Some(num) = value { println!("Number: {}", num); } else { println!("None"); } } }
위 코드에서 먼저 Option
값의 벡터를 정의합니다. for
루프와 if let
을 사용하여 각 요소가 Some
인지 확인하고 값을 출력하거나 "None"을 출력합니다.
다음으로, 다른 벡터를 정의하고 while let
을 사용하여 요소를 하나씩 꺼냅니다. 요소가 Some
인 한 해당 값을 출력합니다. 그렇지 않으면 "None"을 출력합니다.
if let
과 while let
을 사용하여 조건을 유연하게 일치시키고 패턴을 처리할 수 있습니다.
match
의 Exhaustiveness Checking
Rust에서 match
표현식은 철저합니다(exhaustive). 즉, 컴파일러는 잠재적인 오류를 방지하기 위해 match
표현식에서 가능한 모든 케이스가 처리되었는지 확인합니다.
match
표현식이 철저하지 않으면 컴파일러는 잠재적인 오류를 방지하는 데 도움이 되도록 경고를 표시합니다. 철저성을 보장하기 위해 match
끝에 _
암을 폴백 케이스로 추가할 수 있습니다.
다음은 철저성 검사를 보여주는 예입니다.
enum Color { Red, Green, Blue, } fn main() { let color = Color::Red; match color { Color::Red => println!("Red"), Color::Green => println!("Green"), // Missing the Color::Blue branch } }
위 코드에서 세 개의 베리언트가 있는 열거형 Color
를 정의합니다. 그런 다음 match
표현식을 사용하여 color
변수를 매칭합니다. Color::Red
와 Color::Green
에 대한 암을 제공하지만 Color::Blue
는 생략합니다.
이 코드를 컴파일하려고 하면 Rust 컴파일러는 다음 경고를 생성합니다.
warning: non-exhaustive patterns: `Color::Blue` not covered
이 경고는 match
표현식이 가능한 모든 케이스를 처리하지 않기 때문에 철저하지 않음을 나타냅니다.
이 문제를 해결하려면 _
브랜치를 추가하거나 모든 열거형 베리언트를 명시적으로 매칭할 수 있습니다.
결론
패턴 매칭은 Rust의 강력하고 유연한 언어 기능으로, 다양한 패턴에 따라 다른 작업을 수행할 수 있습니다.
이 기사에서는 Rust에서 패턴 매칭의 기본 사용법을 소개했습니다. 여기에는 열거형 및 구조체 매칭, if let
및 while let
을 사용하여 매칭 로직 단순화, 가능한 모든 케이스를 처리하기 위해 match
표현식에서 철저성을 보장하는 방법이 포함됩니다.
Rust 프로젝트 호스팅을 위한 최고의 선택, Leapcell입니다.
Leapcell은 웹 호스팅, 비동기 작업 및 Redis를 위한 차세대 서버리스 플랫폼입니다.
다국어 지원
- Node.js, Python, Go 또는 Rust로 개발하세요.
무제한 프로젝트 무료 배포
- 사용량에 대해서만 지불하세요. 요청도, 요금도 없습니다.
타의 추종을 불허하는 비용 효율성
- 유휴 요금 없이 사용한 만큼 지불하세요.
- 예: $25로 평균 응답 시간 60ms에서 694만 건의 요청을 지원합니다.
간소화된 개발자 경험
- 간편한 설정을 위한 직관적인 UI.
- 완전 자동화된 CI/CD 파이프라인 및 GitOps 통합.
- 실행 가능한 통찰력을 위한 실시간 메트릭 및 로깅.
손쉬운 확장성 및 고성능
- 쉬운 고 동시성 처리를 위한 자동 스케일링.
- 운영 오버헤드가 없으므로 구축에만 집중하세요.
설명서에서 자세히 알아보세요!
X 팔로우: @LeapcellHQ