티스토리 뷰
안녕하세요. Diana 입니다.
요즘 SwiftUI로 개발을 하다보면 에러 문구로 Opaque Type이라는게 자주 보이더라구요.
그리고 주변에서도 종종 귓동냥으로 이런게 있다 하고 들었던 것 같은데 미루고 미루다 이제서야 공부합니다 ㅎㅎ
그럼 바로 시작하겠습니다.
Swift에는 코드의 디테일을 숨기는 방법으로 Opaque Type과 Boxed Protocol Type이라는 두 가지 종류를 제공합니다.
그 중 Opaque Type은 Swift 5.1에 나온 개념으로 구현을 구체화하는 대신 호출에서 내용이 추상화 된다는 흥미로운 특징을 가지고 있죠.
구현을 구체화하고 호출을 추상화한다?
어디선가 비슷한 개념을 본적이 있는 것 같습니다.
네 바로 제네릭인데요.
제네릭은 비슷하긴 하지만 Opaque 타입과는 반대로 구현을 추상화하고 호출을 구체화한다는 특징을 가지고 있습니다.
구체화한다는 말은 제네릭의 경우 구현부에서 파라미터 등 내부에서 쓰일 타입을 T(type) 등의 기호로 표시하곤 하는데 제네릭을 사용한 함수 내부의 타입은 결국 사용할 때 넣어주는 타입에 따라 변경됩니다.
글만으로는 이해하기 어려우니 코드와 함께 자세하게 알아보도록 하겠습니다.
✅ 제네릭(Generic)
우선 우리가 알고 있는 제네릭은 아래와 같이 생겼습니다.
protocol Food {}
func 음식만들기<T: Food>(재료: T) -> T {}
위의 코드에서 T에는 Food 프로토콜을 만족하는 모든 값이 들어올 수 있고 리턴 값 또한 마찬가지로 Food 프로토콜을 만족하는 어떠한 값이든 리턴될 수 있습니다.
여기서 우리는 앞에서 설명한 특징인 추상적인 구현과 구체적인 호출의 특징을 볼 수 있는데 현재 구현부에서는 재료에 어떠한 값이 들어올 지 모르지만 호출부에서 T 값을 지정해주면 내부 T 타입의 값들이 해당 값으로 고정됩니다.
✅ Opaque Type(불투명 타입)
이제 제네릭과 반대되는 특징을 가지는 Opaque Type의 코드를 알아보겠습니다.
struct 스파게티: Food {}
struct 피자: Food {}
func 음식만들기() -> some Food {
let 완성요리 = 스파게티()
return 완성요리
}
위의 코드에서 눈에 띄는 부분이 있다고 하면 바로 "some" 입니다.
타입 앞에 some이 붙게 되면 해당 타입은 Opaque 타입이 되며 해당 코드는 특정 종류의 타입만을 리턴할 수 있게 됩니다.
이게 무슨 소리인지 아래 코드를 봅시다.
struct 스파게티: Food {}
struct 피자: Food {}
func 음식만들기() -> some Food {
if 면요리 { return 스파게티 }
return 피자
}
위의 코드에서 "음식만들기" 함수는 스파게티를 리턴할 수도 있으며 피자를 리턴할 수도 있습니다.
하지만 Opaque 타입은 리턴 타입이 특정 하나로 결정되기를 원하기 때문에 이 경우 컴파일 에러가 발생합니다.
즉 some 을 사용해 Opaque 타입을 구현해줄땐 리턴 타입을 스파게티면 스파게티, 피자면 피자 하나로 통일해주어야 합니다.
그럼 이렇게 제약사항(?)이 생기도록 Opaque 타입을 사용하는 이유는 무엇일까요?
이는 사용의 명확성 때문입니다.
✅ Boxed Protocol Type 이란?
Boxed Protocol Type이란 실존적인(Existential) 타입이라고 불리기도 합니다.
Boxed Protocol을 나타내기 위해서는 우리는 프로토콜 명 앞에 any를 붙이며 해당 값에는 프로토콜을 만족시키는 어떠한 값도 들어갈 수 있습니다.
예시 코드를 보겠습니다.
struct VerticalShapes: Shape {
var shapes: [any Shape]
func draw() -> String {
return shapes.map { $0.draw() }.joined(separator: "\n\n")
}
}
let largeTriangle = Triangle(size: 5)
let largeSquare = Square(size: 5)
let vertical = VerticalShapes(shapes: [largeTriangle, largeSquare])
print(vertical.draw())
위의 코드를 보면 구조체 VerticalShapes는 Shape 프로토콜을 만족시키고 있으며 내부 값으로 Shape 프로퍼티를 만족시키는 값들의 Array를 가지고 있습니다.
이때 shapes에는 우리가 평소에 알고 있는 것처럼 Shape 프로퍼티를 만족시키는 어떠한 값도 들어갈 수 있기 떄문에 Triangle, Square가 들어가더라도 정상적으로 작동합니다.
'Swift' 카테고리의 다른 글
Swift - private(set) 이란? (0) | 2024.09.19 |
---|---|
Swift - CoreData란? (0) | 2024.07.12 |
Swift - Swift의 관점에서 Thread 이해하기(1) (0) | 2024.07.08 |
- Total
- Today
- Yesterday
- reusablelist
- asymptoticnotation
- SwiftUI
- threadprogramming
- swift
- boxedprotocol
- 개발자코테
- 알고리즘
- 빅세타표기법
- swiftpackage
- tipview
- boxedprotocoltype
- opaquetype
- Concurrency
- tipkit
- 팁킷
- private(set)
- Tuist
- ViewBuilder
- opaque
- ios
- 스위프트
- tuist v4
- capsulation
- coredata
- swiftcoredata
- BoxedType
- kakaomapssdk
- Algorithm
- 코어데이터
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |