Starbucks Caramel Frappuccino
본문 바로가기
  • 그래 그렇게 조금씩
SwiftUI/SwiftUI(Advanced)

5. Generic 제네릭

by Toughie 2023. 6. 21.

🦁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프로토콜을 채택하지는 않기 때문에 오히려 더 복잡하고 유연성이 제한될 수도 있음.

 

 

제네릭의 장단점을 잘 고려해서, 필요한 경우에 활용한다면 아주 강력한 기능이라고 생각한다 :)