본문 바로가기
iOS/Swift

[Swift] Opaque Types

by Jiseong 2025. 2. 22.

Opaque Types

불투명한 타입으로, 메서드 및 변수, 파라미터등의 타입을 감추는 방법을 의미한다
반환되는 구체 타입은 구현부에서 알 수 있으며, 외부에선 감춰진 타입만을 알 수 있다. 그래서 역제네릭으로 불리기도 한다.

  • some + 프로토콜 (some Testable) 문법으로 사용
  • 컴파일 타임에 어떤 타입이 반환될지 결정함
  • 컴파일러는 구체 타입을 알기 때문에 타입 보존이 가능

제네릭은 반대로 외부에서 구체 타입을 넣어주고, 내부에선 모른다

protocol Testaa { 
    func test<T>(t: T)
} 

class Tess {
    func test<T: String>(t: "TT") {
        print(t)
    }
}

Protocol Type과 비교

Protocol Type의 경우 반환되는 프로토콜 타입을 채택한다면 어떤 객체든 반환할 수 있는 반면

protocol SomeProtocol { }

struct P: SomeProtocol { }

struct C: SomeProtocol { }

class Test {
    func test() -> SomeProtocol {
        if true {
            return P()
        }
        return C()
    }
}

Opaque Types

func test() -> some SomeProtocol {
    return P()
}


Opaque Types는 프로토콜을 채택하는 하나의 구체 타입만을 반환할 수 있다.
이는 분기 등을 통한 여러 구체 타입 반환의 경우 런타임에 타입을 알 수 있으므로, 컴파일 타임에 반환 타입을 결정하는 타입의 특성을 위반하는 것이기 때문이다.
e.g.

func makeValue() -> some Equatable {
    if true {
        return 1
    }
    return 42  // 항상 Int를 반환
}
/// 구체가 Int 하나임. 됨

func test() -> some SomeProtocol {
    if true {
        return P()
    }
    return C()
}
/// 구체가 P, C 두개임. 안됨

위 예제에서 Int를 반환하지만, String 등의 Equatable을 채택하는 객체를 반환할 수 있다면, 함수 호출부에선 Equatable만을 바라보고 있기때문에 개발자가 예측을 할 수 없는 타입이 되버린다.
대표적으로 SwiftUI의 View가 Opaque Types이다.

장점

some을 통해 유연한 코드 작성이 가능하다.
외부에선 반환타입이 추상화된 프로토콜 하나만 알 수 있으므로, 의존을 끊어낼 수 있다.
외부로 드러날 타입이 내부에 종속되니 구현 세부사항의 캡슐화의 장점이 있다.
모듈 간의 의존 관계 개선

  • 모듈B(구현체 모듈)에선 모듈A의 구현을 알 필요가 없으므로, 인터페이스에 의존하게되며 모듈A의 내부 구현에 영향을 받지 않게됨

e.g.

// 모듈 A에서 정의한 프로토콜
public protocol DataProvider {
    func fetchData() -> String
}

// 모듈 A의 내부 구체 타입 
class InternalDataProvider: DataProvider {
    func fetchData() -> String {
        return "Internal Data"
    }
}

// opaque type을 통해 내부 구현을 숨김
public func makeDataProvider() -> some DataProvider {
    // 내부에서는 InternalDataProvider 사용
    return InternalDataProvider()
}


// 모듈 B에서 모듈 A 인터페이스 의존
import ModuleA 

func processData() {
    let provider = makeDataProvider() // 반환 타입은 "some DataProvider" → 구체 타입은 감춰짐
    // 모듈 B는 provider가 어떤 내부 타입인지는 알 필요 없이, DataProvider 프로토콜의 메서드만 사용
    let data = provider.fetchData()
    print("Fetched data:", data)
}

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/opaquetypes/#app-top

'iOS > Swift' 카테고리의 다른 글

Existential Type (any)  (0) 2025.03.02
[Swift] VisionKit OCR  (2) 2024.10.07
[Swift] UITableView, UICollectionView Last IndexPath  (1) 2023.12.05
[iOS] View Drawing Cycle (Layout까지 작성함)  (0) 2022.08.07
[Xcode] 단축키 좀 써주세요...  (0) 2022.08.06

댓글