🦁Generic 제네릭🦁
Swift에서 제네릭(Generic)은 코드의 재사용성, 유연성을 높이기 위한 기능이다.
제네릭을 사용하면 함수, 구조체, 클래스, 열거형 등에서 일반적인 타입 대신 여러 타입을 쓸 수 있다.
(타입을 매개변수화 후 이후에 실제 타입을 결정함)
제네릭을 사용하면 타입만 다른 비슷한 코드를 여러번 쓸 필요가 없다.
struct StringModel {
let info: String?
func removeInfo() -> StringModel {
StringModel(info: nil)
}
}
struct BoolModel {
let info: Bool?
func removeInfo() -> BoolModel {
BoolModel(info: nil)
}
}
이 코드의 info 프로퍼티를 보면 타입만 다르다. 안에 메서드도 똑같다. 사용하는 타입만 다른 것이다.
이걸 제네릭으로 구현하면 아래와 같다.
struct GenericModel<T> {
let info: T?
func removeInfo() -> GenericModel {
GenericModel(info: nil)
}
}
<T>, 여기서 T는 Type의 약자로 보통은 T로 쓴다. <CustomType> <MyType> 등으로 해도 문제는 없다.
이렇게 하면 이제 T자리에 원하는 타입을 초기화 단계에서 결정해서 넣을 수 있게 되는 것이다.
//stringModel의 info는 Optional String타입이기 때문에 String Literal만 할당 가능.
var stringModel = StringModel(info: "Hello, World")
//하지만 제네릭을 활용한 모델에서는 String, Bool등 원하는 타입의 값을 넣을 수 있음.
var genericStringModel = GenericModel(info: "GENERIC")
var genericBoolModel = GenericModel(info: true)
이것을 뷰에서도 사용할 수 있다.
struct GenericView<T: View>: View {
let content: T
let title: String
var body: some View {
VStack {
Text(title)
content
}
}
}
content자리에는 View 프로토콜을 채택한 어느 타입이든 할당될 수 있다. (타입 제약조건을 추가한 것)
여기서 <T: View>가 아니라 이전 예시와 같이 <T>로만 해버리면
Static method 'buildExpression' requires that 'T' conform to 'View'
라는 컴파일 에러가 뜬다. 즉 View 프로토콜을 준수해야한다는 것이다.
GenericView(content: Text("ANYVIEWTYPE"), title: "newView")
초기화는 이렇게 할 수 있다.
Text도 View프로토콜을 준수하기 때문에 가능한 것! 그냥 "ANYVIEWTYPE" 스트링 리터럴만 넣으면 안 된다.
제네릭의 장점
1. 재사용성
여러 다른 타입에 대해 동일한 코드를 재사용할 수 있다. (일반화된 코드 작성 가능)
2. 타입 안정성
사실 Swift의 가장 핵심 특징이라 생각.
타입이 매개변수화되기 때문에 잘못된 타입 사용으로 인한 오류를 미리 방지할 수 있음.
(컴파일 단계에서 타입 안정성 보장 가능)
3. 추상화
직접 구체적인 타입을 가지고 코드를 짜는 대신,
일반적, 추상화된 형태로 코드 작성 가능.
제네릭의 단점
1. 복잡성
한 눈에 바로 타입을 알 기 어렵기 때문에 코드 이해가 어렵고 복잡할 수 있음.
또한 추가적인 문법, 추론 규칙, 여러 개념 및 패턴을 알고 있어야함.
2. 컴파일 시간
제네릭 코드는 타입이 정해진 코드보다 컴파일 시간이 더 오래 걸릴 수 있음.
컴파일러가 모든 타입에 대해 코드를 생성하고 타입 체크를 수행해야하기 때문.
+ 각 타입에 대해 별도의 코드가 생성되기 때문에 파일의 크기가 증가할 수도 있음.
(오버헤드를 고려해야 할 수도 있음)
3. 제약조건의 한계
위 예시에서 <T: View>처럼 제네릭 타입에 제약조건을 사용해서 특정한 타입만을 허용할 수 있음.
하지만 모든 타입이 View프로토콜을 채택하지는 않기 때문에 오히려 더 복잡하고 유연성이 제한될 수도 있음.
제네릭의 장단점을 잘 고려해서, 필요한 경우에 활용한다면 아주 강력한 기능이라고 생각한다 :)
'SwiftUI > SwiftUI(Advanced)' 카테고리의 다른 글
7. PreferenceKey / Custom Navigation Bar (0) | 2023.06.23 |
---|---|
6. @ViewBuilder / 뷰 빌더 (0) | 2023.06.22 |
4. custom Shape / path (0) | 2023.06.20 |
3. MatchedGeometryEffect / custom segmented Control 세그먼트컨트롤 (0) | 2023.06.20 |
2. AnyTransition Custom / 트랜지션 커스텀 (0) | 2023.06.19 |