Swift

[Swift] Opaque Type (some 키워드)

yujaehui 2024. 4. 19. 10:27

1. OpaqueType (some 키워드)

Swift의 Opaque Type은 함수나 속성이 반환하는 구체적인 타입을 숨기고 대신 타입 정보를 추론할 수 있도록 하는 기능.

some 키워드를 사용하여 선언하며, 내부적으로 반환되는 타입이 하나로 고정되지만, 호출자는 타입 정보를 알 필요 없이 사용 가능.

이 기능은 Generic과 비슷해 보이지만, 동작 방식에서 중요한 차이점이 존재.

Opaque Type은 주로 캡슐화와 유연한 반환 타입 설계에 사용.


2. Opaque Type 사용법

func makeOpaqueShape() -> some Shape {
    Circle() // Shape 프로토콜을 준수하는 Circle 반환
}
  • 반환 타입이 some Shape로 정의되었으므로, 함수는 Shape 프로토콜을 준수하는 어떤 구체적인 타입을 반환.
let shape = makeOpaqueShape()
// shape의 구체적인 타입은 Circle이지만, 이를 몰라도 사용 가능
print(shape)
  • 호출자는 반환 타입이 Shape를 따르는 구체적인 타입(Circle)임을 몰라도 사용이 가능.

3. Opaque Type 주요 특징

  1. 구체적인 타입 고정
    • 함수나 속성이 반환하는 구체적인 타입은 하나로 고정.
    • 내부적으로 반환되는 타입은 컴파일러가 추론하지만, 외부에는 노출되지 않음.
  2. 프로토콜 준수
    • Opaque Type은 반환 타입으로 프로토콜을 사용할 수 있음.
      • 이는 반환되는 타입이 특정 프로토콜을 준수하도록 강제.
  3. 타입 안정성
    • 반환되는 타입이 동일해야 하므로 타입 안정성을 보장.
    • 반환 타입이 서로 다른 경우 컴파일 에러가 발생.
    func makeShape(isCircle: Bool) -> some Shape {
        if isCircle {
            return Circle() // OK
        } else {
            return Rectangle() // 컴파일 에러: Circle과 Rectangle은 다른 타입
        }
    }

4. Opaque Type 활용

ViewBuilder에서 사용

SwiftUI에서 ViewBuilder는 some View를 반환하도록 설계되어 있음. 이는 SwiftUI 뷰 계층 구조를 컴파일러가 최적화하도록 도움.

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
            Button("Click Me") { }
        }
    }
}
  • some View는 SwiftUI가 내부적으로 최적화한 구체적인 View 타입을 반환.
  • 호출자는 View라는 공통 프로토콜을 준수하는 점만 알면 됨.

타입 캡슐화

Opaque Type은 복잡한 타입을 감추고 간결하게 설계하는 데 유용.

// 복잡한 타입
func getConfiguredButton() -> ModifiedContent<
    ModifiedContent<
        ModifiedContent<
            Button<Text>,
            _BackgroundStyleModifier<Color>
        >,
        _PaddingLayout
    >,
    _ForegroundStyleModifier<Color>
> {
    Button("Click Me") {
        print("Button clicked")
    }
    .foregroundStyle(.white)
    .padding()
    .background(Color.blue)
}
// 타입 캡슐화
func getConfiguredButton() -> some View {
    Button("Click Me") {
        print("Button clicked")
    }
    .padding()
    .background(Color.blue)
    .foregroundColor(.white)
    .cornerRadius(8)
}

5. Opaque Type vs. Protocol Type

  Opaque Type (some) Protocol Type (Shape)
타입 고정 여부 반환 타입이 내부적으로 고정됨 다양한 타입 반환 가능
타입 안정성 반환 타입이 컴파일 시점에 결정 런타임에 확인
성능 컴파일 타임 최적화 가능 프로토콜 동적 디스패치 사용
사용 가능 기능 구체적인 타입의 모든 기능 사용 가능 프로토콜에서 정의된 기능만 사용 가능

6. Opaque Type vs. Generic

Opaque Type과 제네릭은 반환 타입에 대한 추상화를 제공하지만, 주된 차이점은 반환 타입의 구체성.

  Opaque Type (some) Generic
타입 고정 여부 내부적으로 고정된 구체적 타입 호출할 때마다 다른 타입 가능
사용성 반환 타입을 숨기고 캡슐화 가능 호출자가 반환 타입을 명확히 알고 있어야 함
유연성 반환 타입이 고정적이어야 함 다양한 타입을 반환 가능
// Opaque Type
func makeShape() -> some Shape {
    Circle()
}
// Generic
func makeShape<T: Shape>(_ shape: T) -> T {
    shape
}

7. Opaque Type 주요 활용 사례

  1. SwiftUI View 계층
    • 복잡한 View 계층을 Opaque Type으로 간단하게 추상화.
  2. 타입 숨기기
    • 내부적으로 사용하는 타입을 노출하지 않고 인터페이스를 설계할 수 있음.
  3. 컴파일 타임 최적화
    • 런타임 디스패치를 줄이고 컴파일 시점에 타입을 고정하여 성능을 향상.

8. 결론

Opaque Type은 타입 추상화와 캡슐화를 가능하게 하여 코드 가독성과 유지보수성을 높임.

특히 SwiftUI와 같은 선언형 UI 프레임워크에서 효율적으로 사용되며, 타입 안정성과 성능을 보장하는 데 유용.

'Swift' 카테고리의 다른 글

[Swift] 버전 대응 Wrapper  (0) 2024.05.19
[Swift] Property Wrapper  (0) 2024.04.29
[Swift] map  (0) 2024.04.19
[Swift] init  (0) 2024.04.18
[Swift] weak, unowned  (0) 2024.04.18