구조적 분해와 match

구조체와 열거형은 Rust에서 중요한 사용자 정의 타입이며, 이를 매치(match) 구문과 결합해 사용하면 상당히 강력한 패턴 매칭 기능을 제공한다. 패턴 매칭은 데이터 구조를 원하는 형태로 ‘구조적 분해’(destructuring)하여 필요한 값이나 상태에 따라 분기 처리를 간결하게 해준다. 구조적 분해는 말 그대로 구조를 해체하여 내부 데이터를 추출하는 과정을 의미하며, match 구문을 활용하면 이 과정을 정교하게 제어할 수 있다.

구조체의 경우, 명명된 필드 구조체이든, 튜플 구조체이든, match를 통해 필드를 분해하고 필요한 필드만 선택적으로 사용하거나, 일부는 무시하는 등 다양한 방식을 적용할 수 있다. 열거형 또한 특정 variant를 식별하고 variant 내부의 필드를 분해하는 동시에 필요한 로직을 매끄럽게 처리할 수 있다. 이러한 매칭 과정에서 상황에 따라 값 자체를 이동시키거나 참조만 빌리는 방법(ref 키워드 등)을 사용할 수도 있다.

구조체의 구조적 분해는 다음과 같이 기본적인 예시로 확인할 수 있다.

struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let point = Point { x: 10, y: 20 };

    match point {
        Point { x, y } => {
            println!("좌표는 ({}, {})", x, y);
        }
    }
}

이 예시에서 match 구문은 Point { x, y } 패턴을 사용해 구조체를 구성하는 필드를 각각 추출한다. 필드 이름이 같으므로 별도의 바인딩을 만들 필요 없이 해당 값을 바로 사용할 수 있다. 만약 특정 필드만 필요하거나 일부를 무시하고 싶다면 _ 혹은 .. 문법을 활용할 수 있다.

struct Point3D {
    x: i32,
    y: i32,
    z: i32,
}

fn main() {
    let point3 = Point3D { x: 3, y: 4, z: 5 };

    match point3 {
        Point3D { x, .. } => {
            println!("x 좌표 값은 {}", x);
        }
    }
}

이처럼 Point3D { x, .. } 패턴을 사용하면 x 이외의 필드는 무시된다. ..를 사용하면 y, z 등 매치에 명시적으로 사용하지 않은 필드가 있더라도 에러 없이 무시가 가능하다. 가령 y, z 모두를 매치 과정에서 사용하지 않으려면 위와 같이 표현할 수 있다.

필요에 따라 변수 이름을 변경하여 바인딩하는 것도 가능하다.

열거형에서도 동일하게 패턴 매칭을 활용하여 구조적 분해가 가능하다. 예를 들어, Option 열거형을 매칭해 내부의 값을 꺼내 쓸 수 있다.

열거형이 조금 더 복잡해질 때에도 각 variant별로 내부에 담긴 데이터를 적절히 패턴 매칭으로 꺼낼 수 있다.

이 예시는 Message 열거형의 다양한 variant를 매치 구문으로 구분하고 각각 구조적 분해를 수행한다. Move variant는 x와 y라는 필드 값을 분해해 쓰고, Write variant는 String 타입 데이터를 추출해 사용한다. ChangeColor variant도 내부에 저장된 세 개의 u8 값을 순차적으로 꺼내어 매칭 로직을 수행한다.

패턴 매칭에서 변수를 빌리는 방식(ref)도 쓸 수 있다. 구조체나 열거형의 데이터를 참조로만 가져오고 싶다면 패턴에서 ref를 붙일 수 있다.

match 구문에서는 소유권 이동을 엄격히 따르므로, 구조 분해 과정에서 값이 이동하면 이후에는 해당 값을 더 이상 사용할 수 없다. 하지만 ref를 사용하면 참조만 가져가므로 이후에도 값이 유효하다. 구조적인 분해와 함께 소유권 및 빌림 규칙이 어떻게 작동하는지 유의하면서 로직을 구성해야 한다.

구조적 분해를 적극적으로 활용하면 복잡해 보일 수 있는 데이터 구조도 직관적으로 조작할 수 있고, 분기 조건 또한 간단하고 명확하게 표현할 수 있다. 특히 여러 필드가 있는 구조체나 서로 다른 variant가 존재하는 열거형을 다룰 때 중복되는 if-else 구문을 줄여 가독성을 높일 수 있다. Rust의 풍부한 패턴 매칭 문법은 반드시 숙지하고 활용해야 할 핵심 기능이며, 구조적 분해는 그 중심에 있는 중요한 기법이다.

Last updated