Search
Duplicate
🧸

SwiftUI) Opaque Type과 Some키워드에 관해서

간단소개
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
SwiftUI
Scrap
태그
9 more properties
왜 SwiftUI의 첫번째 구문에 var body: some View 인가 에 대해서 궁금했다.
공부를 하게 되었더니, Opaque타입이라는 게 있었다.
Opaque타입을 이해하면 some을 알수있다나 뭐라나.
아무튼 공부해보자!
opaque타입을 이해하기 위해서는 우선적으로 generic을 이해할 필요가 있다.

generic(지네릭)

지네릭은 함수를 호출할때 type을 type parameter를 통해서 정해주게 된다.
즉 지네릭은 함수를 호출할때, 호출자가 placeHolder의 해당 타입을 추론해서 정해주는 역할을 하게 된다.
여기서의 placeHolder란 <T> 로된것을 의미하며, 매개변수를 받는 것을 의미한다.
지네릭에서 중요한것은, 구현부에서는 타입을 숨기지만, 후출부 즉, 사용할때(선언시)에는 타입을 작성해서 알려준다는 것이다.
구현부 → 타입을 알수없다.
선언부 → 타입을 알수 있다.

Opaque타입

opaque타입은 reverse generic이라고 한다.
우선 opaque타입은 이렇게 사용된다.
함수(메소드)의 리턴타입
stored property 타입
computed property 타입
subscripts
(Swift 5.7 부터) 함수 파라미터 타입

opaque타입은 some키워드와 함께 쓸수있다.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ 구현부 (타입을 알수 있다.) func returnSomeString() -> some Equatable { return "hi" } func returnSomeInt() -> some Equatable { return 12 } ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ 후출부 (타입을 알수 없다.) print(returnSomeString()) // hi print(returnSomeInt()) // 12
Swift
복사
이처럼 opaque타입은
구현부에서는 어떤 타입을 사용하는지 알수 있음
리턴, 즉 후출부에서는 어떤 타입인지 알수 없음. → 일반적인 함수와 동일하게 쓰임
이러한 부분때문에 역제네릭이라는 것이다.

some과 any의 차이

any는 Protocol type이며, some은 Opaque type이다.
Protocol Type : 프로토콜을 준수하는 모든 타입 참조 가능
Opaque Type : 하나의 특정 구체 타입을 참조하지만 함수 호출자는 어떤 타입인지 모른다.
그래서…
some키워드를 쓰지 않고 그냥 프로토콜을 준수하는 아무 타입이나 리턴되는거랑 뭐가 다르냐?????
바로에러뜬다.
any와 some의 차이는 리턴하는 타입의 종류를 하나로 정해야 한다는 것이다.
any는 Equatable프로토콜을 준수하는 어떠한 것도 리턴이 가능하기 때문에 안에서 분기를 나누어, may가 리턴이 되던 yong이 리턴이 되던 괜찮다는것이다.
하지만 some의 경우에는 명확한 하나의 타입만을 리턴할수 있도록 하고 있다.
따라서 any는 Protocol Type을 의미하며, some은 Opaque Type을 의미한다.
다시말해서
Opaque Type은 항상 하나의 구체적인 유형을 나타낸다. 이는 어떤 유형인지 알 수는 없다.
프로토콜 타입은 프로토콜을 준수하는 여러 유형을 참조하는 것이 가능하다.

왜 SwiftUI에서는 some과 Opaque types 를 사용하는가????

var body: some View { VStack(alignment: .leading) { Text("My hovercraft is full of eels") .font(.headline) Text("Mijn luchtkussenboot zit vol paling") .font(.subheadline) } }
Plain Text
복사
위와 같은 코드가 있을 때 some View로 선언된 view의 타입은 사실 VStack<TupleView<(Text, Text)>> 과 같은 형태이다.
이때 만약 뷰를 다르게 구성하고 더 많은 서브 뷰가 생긴다면 이것의 타입은 점점 더 복잡해 지게 된다.
body의 타입을 구체적으로 입력할 수는 있지만 만약 그렇게 된다면 view의 구성이 변경될 때마다 이 타입을 계속 업데이트 해야 된다.
→ 만일 지네릭이라면, 계속해서 View를 부를때 VStack<TupleView<(Text,Text)>>를 해주고, 이게 늘어나면 늘어날수록 계속 써야하는게 엄청나게 많아진다는 이야기임.
이를 Opaque타입을 이용하면 간단하게 해결이 된다.
some 키워드를 사용하여 View를 선언하고 컴파일 타임에 구체적인 타입을 결정하도록 하는 것이 훨씬 더 쉽습니다. → 앞에서 계속해서 View를 쓸때마다 VStack<TupleView<(Text,Text)>>이렇게 안써도 되고 코드내부에서는 계속 구체적인 타입을 지정해서 쓰지만, 그냥 밖에서 쓸때는 신경쓰지않아도 된다는 이야기임
즉!
View의 내부를 더욱 유연하게 조작하고 확장할 수 있게 된다.

번외 - 나만의 생각

opaque타입이 아니라 제네릭이었다면 preview에서 contentView()로 사용불가능할지도? 타입을 알려줘야하니까, 굉장히 귀찮았을것 같다.
참고자료