SwiftUI를 접하다 보면,
Opaque Type(불투명 타입)인 some과 만나게 됩니다.
대체 이건 뭐고 왜 필요한 것일까요?
실마리를 찾기 위해,
Opaque Type(불투명 타입)과 SwiftUI에 대해 알아보겠습니다.
1. Opaque Type(불투명 타입) 과 SwiftUI
불투명 타입이 어떤 건지 비유를 통해 알아보겠습니다.
만약 친구에게 "나 과일 하나 가져올게" 라고 말했다고 가정해 보겠습니다.
어떤 과일을 가져올지 정확히 말하지 않았지만,
분명한 것은 과일의 일종을 가져온다는 점입니다.
"뭐가 될지는 모르겠지만,
마트에 들려서,
과일종류를 사올것이다" 이런 거죠.
SwiftUI에서도 마찬가지입니다.
some을 사용하면 다음의 의미를 가지게 됩니다.
"이것은 View의 일종인데,
Text일 수도, Button일 수도,
혹은 여러 View의 조합일 수도 있지.
어떤 View인지는 너는 굳이 알필요가 없어.
그래도 View를 리턴해줄거야."
이런 의미가 됩니다.
import SwiftUI
...
struct ToggleView: View {
@Binding var isOn: Bool
var body: some View {
Toggle("다크 모드 전환", isOn: $isOn)
.padding()
}
}
조금 불친절한 느낌도 들고,
도대체 뭘까요?
왜 이런게 필요한지 이해하기 위해,
some과 Protocol의 관계에 대한 이해가 필요합니다.
2. some과 Protocol과의 관계
Swift에서 사용하는 View는 Protocol(프로토콜)입니다.
Protocol(프로토콜)은 일종의 계약이나 청사진으로,
특정 기능을 구현해야 한다고 정의만 하는 것인데요.
그 자체로는 구체적인 구현이 없습니다.
여러 종류의 뷰들(Text, Button, VStack 등)이 이 프로토콜을 준수합니다.
아래의 코드에서 추상화된 프로토콜인 View타입으로 반환하고 있는데요.
이러면 "어떤 View든 반환할 수 있다"는 의미가 되겠지요.
그런데 여기에는 문제가 있습니다.
func getView() -> View { ... }
만약 View가 Text라면 글자 크기, 색상 등의 특성을 가지고 있을 것이고,
Button이라면 액션과 라벨 등을 가질 것 인데요.
추상화된 View타입으로 반환해 버리면,
이런 구체적인 정보가 사라져 버립니다.
다음과 같은 일이 발생해 버리는 것 이지요.
generalView는 쓸모있어 보이지 않습니다.
let textView: Text = Text("Hello")
let generalView: View = textView // 여기서 타입 정보 소실
textView.font(.title) // 가능
generalView.font(.title) // 불가능! View 프로토콜에는 font 메서드가 없음
어떻게 해야할까요?
이럴 때, some View로 리턴해주면 됩니다.
그러면, 컴파일러는 내부적으로 정확한 타입을 알고 있기 때문에,
최적화가 가능하고, 타입 정보도 보존해 줍니다.
동시에 외부에서는,
그 정확한 타입에 대해서는 모르는 것 인데요.
불투명하게 타입을 리턴해 줌으로써,
오히려 필요한 데이터를 보존하는 것 입니다.
조금 아이러니하지요.
그래서 some을 사용하면,
타입 정보를 보존하면서도,
세부사항을 숨기는 균형을 제공한다고 할 수 있습니다.
댓글