러스트에서 열거형(enum)은 값(variants)뿐만 아니라 그에 연관된 데이터(payload)도 저장할 수 있습니다. 이로 인해 상태나 매개변수를 가진 메시지를 나타내는 등의 대수적 데이터 타입을 만드는 데 특히 유용합니다. 예를 들어:
enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), }
이런 열거형을 처리하기 위해 일반적으로 match 연산자를 사용하여 각 변형의 내부 값을 펼칠 수 있습니다:
let msg = Message::Move { x: 10, y: 20 }; match msg { Message::Quit => println!("Quit message"), Message::Move { x, y } => println!("Move to ({}, {})", x, y), Message::Write(text) => println!("Text: {}", text), Message::ChangeColor(r, g, b) => println!("Change color to ({}, {}, {})", r, g, b), }
이런 접근 방식은 모든 가능한 경우를 안전하고 명확하게 처리할 수 있도록 하여 프로그램 논리의 오류를 최소화합니다.
러스트에는 열거형(enum)에 대한 null이 존재하지 않는 이유와 존재하지 않는 변형으로의 패턴 매칭 시 반환되는 값은 무엇인가요?
자주 틀린 답변: "모든 enum 변형을 match에서 처리하지 않으면 컴파일러가 오류를 무시합니다."
사실, 컴파일러는 모든 가능한 변형이 고려되지 않으면 오류를 발생시키거나 catch-all(_)을 추가하라고 요구합니다. 예를 들어:
enum Status { Ok, Err(String) } let st = Status::Ok; match st { Status::Ok => println!("Ok"), // Status::Err를 잊으면 컴파일러가 불만을 표시합니다. }
이야기 하나의 프로젝트에서 enum을 확장할 때, 사용된 모든 곳에서 새로운 변형에 대한 처리를
match에 추가하지 않았습니다. 이로 인해match가 완전하지 않아 릴리스에서 panic!이 발생했습니다. 이때 테스트는 모든 케이스를 커버하지 않았습니다.
이야기 다른 경우에는 일반적인
==를 사용하여 enum을 비교하려고 했으나, 연관 데이터가 있는 복합 변형에 대해 PartialEq를 구현하지 않아 예상치 못한 컴파일 오류가 발생했습니다.
이야기 팀이 변형 처리를 위해 catch-all(
_)을 사용했으며, 나중에 새로운 변형을 추가할 때 로직이 조용히 새로운 사례를 무시하게 되어 찾기 힘든 결함의 원인이 되었습니다.