패턴 매칭은 Swift의 근본적인 특징으로, 코드를 더 안전하고 깔끔하게 만듭니다. 역사적으로 패턴 매칭은 관련 값을 포함한 열거형을 보다 표현력 있고 안전하게 다루기 위한 수단으로 발전했습니다. 다른 언어들과는 달리, Swift는 if, guard, switch 표현에서 중첩된 값을 직접 풀 수 있게 해줍니다.
문제: 비표준 열거형, 특히 중첩된 연관 값을 가진 경우에는 case 구조에서 쉽게 실수할 수 있거나 주요 switch의 제한을 과소평가할 수 있습니다. 또한 if case, guard case와 전통적인 switch 사용 간의 차이가 종종 명확하지 않습니다.
해결책: 시나리오에 따라 다른 패턴 매칭 접근 방식을 적용하고, 복잡한 중첩 구조에서는 이름을 명시적으로 지정하고 where를 사용하는 것이 좋습니다.
코드 예제:
enum NetworkState { case success(User) case failure(Error, code: Int) case loading(progress: Double) } let state = NetworkState.failure(SomeError(), code: 401) if case let .failure(error, code) = state, code == 401 { print("Unauthorized: \(error)") } guard case .success(let user) = state else { return } print(user) switch state { case .success(let user): print("Welcome, \(user.name)") case .failure(let error, let code) where code == 404: print("Not Found: \(error)") case .failure(_, let code): print("Failure with code: \(code)") case .loading(let progress): print("Progress: \(progress)") }
주요 특징:
switch에서 모든 열거형 case를 누락하면 어떻게 되나요?
컴파일 오류(열거형이 non-optional인 경우) 또는 모든 커버리지가 고려되지 않은 경우 경고/기본 case 요구입니다. Optionals는 .some과 .none만 지정하면 충분합니다.
중첩된 열거형 및 연관 값으로 패턴 매칭을 할 수 있나요?
네. 하지만 구문이 복잡해집니다. 중첩된 값을 위해 여러 레벨을 즉시 풀 수 있습니다:
enum Outer { case inner(Inner) } enum Inner { case item(id: Int) } let e = Outer.inner(.item(id: 5)) if case let .inner(.item(id)) = e { print(id) }
패턴 매칭에서 guard case와 if case의 차이점은 무엇인가요?
guard case는 조건을 확인하고 실패 시 exit 블록(return, throw, break)을 수행합니다. 일반적으로 요구 사항에 사용되며, 일치하지 않으면 나갑니다.
if case는 함수에서 나가지 않고 단일 라인 조건 처리기에 적합한 구조입니다.
개발자가 여러 case를 가진 열거형을 위해 switch를 사용하지만 새로운 case를 커버하지 않습니다. 코드는 컴파일되지만 새로운 시나리오는 처리되지 않으며 애플리케이션이 런타임에 크래시됩니다.
장점:
단점:
개발자가 모든 case를 명시적으로 커버하고, 지역 필터링을 위해 where를 사용하며, 중첩된 let을 통해 중첩된 값을 풀어냅니다.
장점:
단점: