protocol에서 associatedtype은 뭘까 ?
MVVM 패턴을 적용할 때, viewModel을 이렇게 in,output 구조체로 나누고 transform 메소드를 통해 변환해주는 형태로 만들어서 사용하는데, 1 VC 1 VM을 만들어서 사용하다보니 VC의 개수만큼 VM 파일이 생기고, 그럴때마다 이 형태를 반복해서 만들어줘야했다.
반복해서 사용해주는건 어쩔 수 없지만, 이 형태(in,output pattern)를 따르고 있다는 것을 프로토콜로 만들어놓고 채택해준다면, viewModel의 상단만 보더라도 어떤 형태로 viewModel을 구성했는지 알 수 있을 것 같아서 프로토콜을 만들고자 했다.
// 중복되는 viewModel의 형태
final class SthViewModel {
struct Input { }
struct Output { }
func transform(input: Input) -> Output
}
그래서 protocol의 형태를 이렇게 만들면 사용할 수 있을 줄 알았다.
protocol ViewModelType {
struct Input { }
struct Output { }
func transform(input: Input) -> Output
}
생각해보면, 프로토콜은 공통 기능을 선언만 해두는 곳이다. 이렇게 만들면 결과적으로 특정된 구조체(타입) 자체를 정의해둔 형태이니까 문법을 따르지 않은 잘못된 형태이다 ^^..;;
그럼 프로토콜 내부에는 타입을 선언할 수 없는 걸까 ?
그건 아니다 !! 중요한건 구체적 타입을 정의, 선언하지 않는 것.
제네릭 타입으로 선언해두고, 이 프로토콜을 채택한 곳에서 구체적인 구현부를 정의해주면 되는데, 여기서 나오는 키워드는 associatedtype 이다.
protocol ViewModelType {
associatedtype Input
associatedtype Output
func transform(input: Input) -> Output
}
associatedtype은 이름 자체로도 알 수 있듯이 연관 타입이다.
말 그대로 선언해둔 곳에서는 바로 알 수 없고, 프로토콜을 채택한 인스턴스에서 구체적인 타입을 정의하는 형태라는 것.
연관 타입 옆에 넣은 것은 Input, Output이라고 네이밍한 제네릭 타입이다.
제네릭을 사용하겠다는 것은 어떤 타입이 들어올지 선언할 때는 알 수 없고, 정의하는 곳에서 결정하겠다는 것이다. 정의하는 시점인 컴파일 시점에 타입이 결정되어 구체적인 타입으로 사용할 수 있다.
이렇게 사용하면 타입 유연성이 생기고, 여러 기본 타입부터 직접 만든 구조체, 클래스 등이 들어와도 상관이 없어서 타입 유연성과 더불어 코드 재사용성이 높아진다.
그리고 제네릭 타입으로 선언된 것이기 때문에 제네릭의 특성을 따르며, 제네릭 타입은 런타임 시점이 아닌 컴파일 시점에 타입 정보가 결정되기 때문에 타입 안정성과 성능 최적화 부분에서 장점을 가진다 !
참고한 자료
프로토콜 - https://bbiguduk.gitbook.io/swift/language-guide-1/protocols
프로토콜 (Protocols) | Swift
준수하는 타입이 구현해야 하는 요구사항을 정의합니다. 프로토콜 (protocol) 은 메서드, 프로퍼티, 그리고 특정 작업이나 기능의 부분이 적합한 다른 요구사항의 청사진을 정의합니다. 프로토콜
bbiguduk.gitbook.io
제네릭 - https://bbiguduk.gitbook.io/swift/language-guide-1/generics
제너릭 (Generics) | Swift
여러 타입에 대한 동작을 작성하고 해당 타입의 요구사항을 지정합니다. 제너릭 코드 (Generic code) 는 정의한 요구사항에 따라 모든 타입에서 동작할 수 있는 유연하고 재사용 가능한 함수와 타입
bbiguduk.gitbook.io
불투명타입 - https://bbiguduk.gitbook.io/swift/language-guide-1/opaque-types
불투명한 타입 (Opaque Types) | Swift
값의 타입에 대한 자세한 정보를 숨깁니다. Swift 는 값의 타입에 대한 자세한 내용을 숨기기위한 두가지 방법을 제공합니다: 불투명한 타입 (opaque type) 과 박스형 프로토콜 타입 (boxed protocol type).
bbiguduk.gitbook.io