질문의 역사:
Swift 5 이전 버전에서는 associated type이 있는 프로토콜에 해당하는 값을 반환할 때 종종 제한에 직면했습니다. return type으로 직접 사용할 수 없었고 type erasure가 필요했습니다. 가독성과 성능을 향상시키기 위해 '불투명 타입'이 도입되었습니다. 이는 some 키워드를 통해 반환되는 값으로, 공용 인터페이스에서 추상화를 설명할 수 있게 합니다.
문제:
실제 반환 타입을 숨기되 프로토콜을 통해 추상을 유지하고자 할 때 발생합니다. 그러나 dynamic dispatch와 type erasure의 비용을 피하고자 할 때 필요합니다. 예를 들어, 컬렉션, 시퀀스, 뷰 컴포넌트를 반환할 때가 있습니다.
해결책:
불투명 타입은 프로토콜에 해당하는 타입을 반환하면서 그 구체적인 구현을 숨길 수 있습니다. 컴파일러는 실제 타입을 알고 있지만 호출하는 쪽은 알지 못합니다.
예시:
protocol Shape { func area() -> Double } struct Circle: Shape { var radius: Double func area() -> Double { Double.pi * radius * radius } } func makeCircle() -> some Shape { return Circle(radius: 3) } let s = makeCircle() print(s.area()) // 작동합니다
주요 특징:
some을 통해 반환됩니다.불투명 타입 (some Protocol)은 반환되는 프로토콜 타입과 무엇이 다릅니까?
불투명 타입은 컴파일 시 구체적인 구현을 가집니다 (외부에서 숨겨져 있지만). Protocol을 반환할 때는 dynamic dispatch가 작동하며, associated type이 있을 경우 type safety가 없습니다.
some Protocol을 사용하여 하나의 함수에서 서로 다른 타입을 반환할 수 있나요?
아니요. 모든 return은 동일한 실제 타입을 반환해야 합니다:
func maker(flag: Bool) -> some Shape { if flag { return Circle(radius: 3) } else { return Square(size: 2) // 오류: 반환 타입이 일치하지 않음 } }
프로토콜 내의 associatedtype은 some Protocol을 통해 사용할 수 있나요?
네. 바로 이것을 위해 (주로) 불투명 타입이 필요합니다:
protocol View { associatedtype Body } func makeView() -> some View { /* ... */ }
함수가 불투명 없이 프로토콜을 반환하여 associated type에 대한 메서드를 사용할 수 없고, 복잡한 type erasure가 필요하며, 코드는 컴파일되지 않거나 비효율적으로 작동합니다.
장점:
단점:
SwiftUI의 ViewBuilder는 some View를 사용하여 세부 정보를 숨기고 타입 안전성을 높이며 컴파일 및 런타임 속도를 향상시킵니다.
장점:
단점: