WooKoo Blog

물과 같이

개발/개발

[SwiftUI] - Opaque Type

WooKoo 2020. 9. 21. 20:48

Opaque Type 이라고 들어보셨나요?

SwiftUI 를 접하게 되면서 저도 알게되었는데 궁금해서 한번 정리해보았습니다.

틀린 부분 있으면 댓글 부탁드립니다!


Opaque Type

오파큐 타입??? 오패큐 타입? 이게 뭐지??? 

네이버 사전

한국 말로는 불투명한 타입이다.

 

불투명 결과 타입(Opaque Result Types) 또는 불투명 반환 타입(Opaque Return Type)이라고한다.

 

나 : "그래서 불투명한 타입이 뭔데?"

 

SwiftUI의 body 프로퍼티를 보면

var body: some View { ... }

여기서 some이 불투명 타입 키워드라고한다.

(프로퍼티, 첨자, 함수 등 반환타입에 한정적으로 사용됌)

 

타입 정보 은닉

body에 some을 빼게되면 두곳에서 오류가 발생한다.

1. 연관 타입을 가진 프로토콜을 사용할 때 타입을 유추 할 수 없는 오류

2. 이로 인해 뷰 프로토콜의 조건을 만족하지 않아서 발생하는 오류

 

 

View 프로토콜을 보면 Body타입에 대한 정보가 필요하죠??

 

Text 타입으로 반환하면 오류가 사라지게됩니다.

 

UIKit은 뷰의 설정을 바꾸거나 자식 뷰를 추가한다고 타입이 바뀌진 않지만

 

SwiftUI의 구현 방식에서는 뷰를 추가할 때 마다 새로운 타입이 만들어진다.

 

이것이 불투명 타입을 사용하게 된 이유다.

 

some View와 같은 불투명 타입은 앞에서 본 실제 타입을 반환하는 대신에 타입 정보를 숨기고

 

프로토콜에대한 정보만 남긴채 API를 사용하게 도와준다.

 

우리는 뷰 프로토콜을 충족하는 어떤 타입이라는 사실만 알고 사용하면 된다.

 

제네릭을 반대로 사용하는 것과 같은 개념이기에 리버스 제네릭이라고도 한다.

 

 

타입 추상화

제네릭은 코드를 호출하는 측에서 호출되는 측의 타입을 결정한다.

func genericFunction<T: Animal>(_ animal: T) { ... }
genericFunction(Dog()) //T == Dog , 함수를 호출하는 코드가 타입을 결정
genericFunction(Cat()) //T == Cat

불투명 타입은 반대로 호출된 코드가 호출한 코드의 타입을 결정

//호출된 쪽에서 타입을 결정
func opaqueTypeFunction() -> some Animal { Dog() }

//호출한 측은 추상화된 타입을 전달받음
let animal: some Animal = opaqueTypeFunction()

 

정적 타입 시스템

제네릭의 매개변수가 그렇듯 불투명 타입 역시 정적 타입에서만 불투명성이 유지되며 런타임에서는 실제타입을 다루는 것처럼 취급하고 사용할 수 있습니다.

protocol Animal{}

struct Dog: Animal {var color = "brown"}
let dog: some Animal = Dog()

dog.color //컴파일 오류
(dog as! Dog).color //"brown"

타입의 정체성

기존 프로토콜 반환 타입으로 사용할 땐 유연하지만 함수를 호출할 때마다 서로 다른 타입이 반환될 수 있어 타입에 대한 정보를 잃는다.

하지만 불투명 타입을 이용하면 타입의 정체성을 보존할 수 있음

 

결론

1. 불투명타입은 자세한 타입과 구현에 대한 정보를 유저에 숨기고 특정 프로토콜을 따르는 API 라는 것만 전달하고 싶을 때 사용

2. 프로토콜은 타입을 반환하면서도 타입에 대한 정체성을 보장해 API 내부에서 강력한 타입 검사 기능을 활용 할 수 있음

3. some 키워드는 프로퍼티와 첨자, 함수에 반환 타입에만 적용 가능하고, some 다음에 올 수 있는 타입은 프로토콜, 클래스, Any, AnyObject로 한정된다.