enum 선언하기
enum은 값이 명명된 변종의 고정 집합인 타입을 선언합니다.
enum Status {
ready,
failed,
}
이제 Status는 정확히 두 값 — Status.ready와 Status.failed — 을 가진 타입입니다. 그 외에는 Status가 될 수 없어요.
문법은 의도적으로 작습니다.
enum Name {이 선언을 엽니다.- 각 줄에 변종 이름을 하나씩, 쉼표로 구분해서 적습니다.
}로 닫습니다.
페이로드도, 판별 값도, 파생 메서드도 없습니다. 그 덕분에 enum이 Zero에서 "작은 합타입"의 자리를 유지하고 있어요.
enum 사용하기
enum 타입으로 한정해서 변종 이름을 적습니다.
let state: Status = Status.ready
오른쪽이 타입을 결정해 주는 경우 : Status 어노테이션은 선택입니다. 대부분의 경우 이렇게 적을 수 있어요.
let state = Status.ready
컴파일러는 타입을 Status로 추론합니다.
enum 값 비교하기
같은 변종이라면 두 enum 값은 같습니다.
if state == Status.ready {
check world.out.write("ready\n")
} else {
check world.out.write("not ready\n")
}
enum 위에서 가장 단순한 분기 방법이에요. 망라 분석 — 모든 변종을 명시적으로 처리 — 이 필요하다면 match를 꺼내세요.
match state {
.ready => { check world.out.write("ready\n") }
.failed => { check world.out.write("failed\n") }
}
if/else if 대신 match를 쓸 때의 이점은 세 번째 변종을 추가하는 순간 드러납니다. 컴파일러가 새 경우가 빠진 모든 match를 알려주거든요. if/else 체인은 조용히 기본 분기로 흘려보냅니다.
choice와 match에서 match를 자세히 다룹니다. enum과 choice 모두에 동작해요.
작동 예제
공식 Zero 샘플은 같은 파일 안에 enum과 choice를 나란히 두고 보여줍니다.
Status는 이 스니펫에서 아무 일도 하지 않습니다. 대비를 보여주려고 두었을 뿐이에요. choice 변종은 매치되면 페이로드(value, message)를 바인딩하고, enum 변종은 바인딩할 것이 없으니 아무것도 바인딩하지 않습니다.
enum vs. choice: 짧은 결정 트리
간단한 규칙:
- 변종이 _그냥 라벨_이면 →
enum. - 변종이 데이터를 담아야 하면 →
choice.
라이프사이클 상태를 모델링하다가 결국 "failed" 상태에 에러 메시지를 붙여야 한다면, 타입을 enum에서 choice로 바꾸세요. 각 변종이 페이로드 타입을 갖게 되고, 이후 match 분기들이 그 페이로드용 바인딩을 얻게 됩니다. 컴파일러가 안내해 주는 리팩토링입니다.
구체적으로:
// Before — enum, 페이로드 없음
enum Status {
ready,
failed,
}
// After — 각 변종에 페이로드가 있는 choice
choice Status {
ready: Void,
failed: String,
}
페이로드가 Void인 변종은 choice 형태의 라벨일 뿐입니다. 같은 논리적 상태에 대해 enum과 choice 둘 다 쓸 수 있어요. 데이터를 붙일 필요가 정말 없다면 enum을 고르세요.
사용 예시
enum이 정답인 일상적인 예시들:
- 메타데이터 없는 라이프사이클.
Loading,Ready,Empty— 순수 상태, 페이로드 없음. - 모드. 파일 오픈 모드용
Read,Write,Append. - 방향.
North,South,East,West. - 로그 레벨.
Trace,Debug,Info,Warn,Error. (나중에 메시지를 추가하게 되면choice로 옮기게 되겠죠.) - 요일. 정석적인 예시입니다.
매직 정수 상수(0 = pending, 1 = active, 2 = done)에 손이 가려는 자리라면, enum이 거의 항상 더 명확합니다.
스타일 노트
- 소문자 변종 이름은 언어 전반의 식별자 스타일과 맞춥니다.
- 마지막 변종 뒤에 쉼표를 두는 건 괜찮고, diff 친화적인 측면에서도 권장됩니다 — 새 변종을 추가할 때 이전 줄이 변경되지 않거든요.
- enum 목록을 작게 유지하세요. 변종이 열 개가 넘고 그중 다수가 페이로드를 원한다면,
choice또는 설계 자체를 다시 보는 게 더 큰enum보다 나을 수 있어요.
다음 글: choice와 match
자연스러운 다음 단계는 enum의 더 풍부한 친척입니다. choice와 match — Zero의 태그된 합타입과 그에 어울리는 패턴 매칭 구조입니다.
자주 묻는 질문
Zero에서 enum이 뭔가요?
enum은 값이 명명된 변종의 고정 집합 중 하나가 되는 타입을 선언합니다. 추가 페이로드 없이 라벨만 있는 셈이에요. 예: enum Status { ready, failed }. Status 타입의 값은 정확히 Status.ready 아니면 Status.failed 둘 중 하나이며, 컴파일러가 이를 강제합니다.
enum과 choice는 어떻게 다른가요?
enum의 변종은 평범한 라벨입니다. 데이터를 담지 않아요. choice는 태그된 합타입이에요. 각 변종이 선언된 페이로드 타입을 가집니다. 예: choice Result { ok: i32, err: String }. 이름만으로 경우를 구분하면 되면 enum을, 각 경우가 추가 정보를 담아야 하면 choice를 쓰세요.
enum 값이 어떤 변종인지 어떻게 확인하나요?
변종과 비교합니다: if status == Status.ready { ... }. 모든 변종에 걸친 망라 분기에는 match를 쓰세요. 변종을 빠뜨리면 컴파일러가 경고를 줍니다. 값이 합타입일 때 if/else if 체인보다 match를 선호해야 하는 주된 이유예요.
Zero에서 enum 변종이 연관 값을 가질 수 있나요?
아니요 — 그게 choice의 역할입니다. enum은 의도적으로 최소한의 합타입이에요. 각 변종은 그냥 라벨일 뿐입니다. 변종 중 하나에 i32나 String을 붙여야 한다면 enum을 벗어난 것이고, choice가 필요한 시점입니다.
Zero에서 enum은 언제 써야 하나요?
값이 작은 명명된 상태 집합 중 정확히 하나여야 하고, 그 상태들이 추가 데이터를 담지 않을 때 enum을 쓰세요. 예시: 요일, 신호등 색, 메타데이터 없는 라이프사이클 상태, 로깅 레벨 같은 것들요. 변종 중 하나에 데이터를 붙이고 싶어진다면 choice로 옮길 시점입니다.