🤖 이 글은 Claude Code(AI)가 작성합니다. | 시리즈 목차 | 이전: 8편
C나 Java의 enum을 알고 있다면 “상수에 이름을 붙이는 것” 정도로 생각할 수 있습니다. Swift의 enum은 그것보다 훨씬 강력합니다. 각 케이스가 서로 다른 타입의 데이터를 품을 수 있고, 메서드와 연산 프로퍼티도 가질 수 있습니다. 상태 머신, 에러 타입, 네트워크 응답 모델링에 이르기까지 Swift 코드 곳곳에서 쓰입니다.
기본 enum
enum Direction {
case north
case south
case east
case west
}
let heading = Direction.north
// 타입이 이미 알려진 경우 타입명 생략 가능
var current: Direction = .east
current = .west
switch와 함께 쓸 때 enum의 힘이 드러납니다. 모든 케이스를 처리하지 않으면 컴파일 오류가 납니다. 나중에 케이스를 추가하면 컴파일러가 처리하지 않은 곳을 모두 알려줍니다.
switch heading {
case .north: print("북쪽")
case .south: print("남쪽")
case .east: print("동쪽")
case .west: print("서쪽")
// default 불필요 — 모든 케이스 처리됨
}
rawValue — 기본값 연결
각 케이스에 정수나 문자열 기본값(rawValue)을 붙일 수 있습니다.
enum Planet: Int {
case mercury = 1
case venus
case earth // 자동으로 3
case mars // 자동으로 4
}
print(Planet.earth.rawValue) // 3
print(Planet(rawValue: 2)) // Optional(.venus)
print(Planet(rawValue: 99)) // nil
rawValue로 생성하면 존재하지 않는 값이 들어올 수 있으므로 옵셔널을 반환합니다.
enum HTTPMethod: String {
case get = "GET"
case post = "POST"
case put = "PUT"
case delete = "DELETE"
}
let method = HTTPMethod.get
print(method.rawValue) // GET
연관값(Associated Values) — 데이터를 품는 enum
Swift enum의 핵심 기능입니다. 각 케이스마다 서로 다른 타입의 데이터를 담을 수 있습니다.
enum NetworkResult {
case success(data: Data, statusCode: Int)
case failure(error: String)
case loading(progress: Double)
}
let result = NetworkResult.success(data: Data(), statusCode: 200)
switch result {
case .success(let data, let code):
print("성공: \(code), \(data.count) bytes")
case .failure(let error):
print("실패: \(error)")
case .loading(let progress):
print("로딩 중: \(Int(progress * 100))%")
}
연관값 덕분에 네트워크 응답의 세 가지 상태를 하나의 타입으로 표현할 수 있습니다. 이것을 별도의 클래스 세 개로 만들거나, 딕셔너리로 처리하는 것보다 훨씬 명확합니다.
연관값의 일부만 필요할 때는 _로 무시합니다.
if case .success(_, let code) = result {
print("상태 코드: \(code)")
}
메서드와 연산 프로퍼티
enum도 메서드와 연산 프로퍼티를 가질 수 있습니다.
enum Suit {
case spades, hearts, diamonds, clubs
var isRed: Bool {
self == .hearts || self == .diamonds
}
func symbol() -> String {
switch self {
case .spades: return "♠️"
case .hearts: return "❤️"
case .diamonds: return "♦️"
case .clubs: return "♣️"
}
}
}
let card = Suit.hearts
print(card.isRed) // true
print(card.symbol()) // ❤️
CaseIterable — 모든 케이스 순회
CaseIterable을 채택하면 allCases 프로퍼티로 모든 케이스를 배열로 얻습니다.
enum Season: CaseIterable {
case spring, summer, autumn, winter
}
for season in Season.allCases {
print(season)
}
// spring, summer, autumn, winter
print(Season.allCases.count) // 4
실전 패턴 1: 상태 머신
UI나 네트워크 로직의 상태를 enum으로 표현하면 처리되지 않은 상태가 없음을 컴파일러가 보장해줍니다.
enum LoadingState {
case idle
case loading
case loaded(items: [String])
case error(message: String)
}
var state: LoadingState = .idle
// 상태에 따라 UI 업데이트
func updateUI(for state: LoadingState) {
switch state {
case .idle:
showPlaceholder()
case .loading:
showSpinner()
case .loaded(let items):
showList(items)
case .error(let message):
showError(message)
}
}
실전 패턴 2: 에러 타입
Error 프로토콜을 채택한 enum은 Swift의 에러 처리 시스템과 바로 연결됩니다. 에러 처리는 11편에서 자세히 다루지만, 에러 타입 자체는 enum으로 만드는 것이 관례입니다.
enum FileError: Error {
case notFound(path: String)
case permissionDenied
case corrupted(reason: String)
}
func readFile(at path: String) throws -> String {
guard path.hasPrefix("/") else {
throw FileError.notFound(path: path)
}
return "파일 내용"
}
indirect — 재귀 열거형
enum의 연관값에 같은 enum 타입이 들어갈 때는 indirect를 씁니다. 트리나 연결 리스트 같은 재귀적 자료구조를 표현할 때 씁니다.
indirect enum Tree {
case leaf(Int)
case node(Tree, Tree)
}
let tree = Tree.node(
.node(.leaf(1), .leaf(2)),
.leaf(3)
)
다른 언어와 비교
| C / Java | Kotlin | Swift | |
|---|---|---|---|
| 케이스에 데이터 첨부 | 불가 | sealed class로 가능 |
연관값으로 직접 가능 |
| 메서드 포함 | Java enum 가능 | 가능 | 가능 |
| switch 망라성 | 강제 아님 | 강제 아님 | 강제 |
| rawValue | 정수 자동 할당 | 가능 | 정수/문자열 선택 |
| 전체 케이스 순회 | values() | values() | CaseIterable |
핵심 요약
- Swift의 enum은 각 케이스마다 서로 다른 타입의 데이터(연관값)를 담을 수 있다.
- switch로 enum을 처리할 때 모든 케이스를 처리하지 않으면 컴파일 오류가 난다.
- rawValue로 정수나 문자열 기본값을 붙일 수 있고, rawValue로 역변환하면 옵셔널을 반환한다.
- enum에 메서드와 연산 프로퍼티를 추가할 수 있다.
- 상태 머신과 에러 타입을 enum으로 모델링하면 컴파일러가 빠진 케이스를 잡아준다.
다음 편은 10편 — 프로토콜과 제네릭: Swift의 다형성입니다. 1부의 마지막 편입니다. 프로토콜이 단순한 인터페이스를 넘어 어떻게 동작하는지, 제네릭과 결합하면 무엇이 가능해지는지를 다룹니다.
🤖 Generated with Claude Code