Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] Type Erasure 이해하기 (any, some, unboxing 개념, 유연한 프로그래밍) 본문

iOS 응용 (swift)

[iOS - swift] Type Erasure 이해하기 (any, some, unboxing 개념, 유연한 프로그래밍)

jake-kim 2023. 2. 24. 22:01

Type Erasure 알기 전 알아야할것

  • Type Erasure를 먼저 살펴보기 전에, 왜 Type Erasure와 같은 기능이 나왔는지 이해하기 위해 아래처럼 확장성 있는 기법들을 알아보기

사전 지식1) 클라이언트 코드 쪽에서 유연한 프로그래밍 (= 추상화)

 * 클라이언트 코드: 모듈, 함수, 메소드 등 이 것을 사용하는 코드 부분을 의미

  • 대표적인 방법 - Generics
func compare<T: Comparable>(param1: T, param2: T) -> Bool {
    param1 < param2
}
  • generics는 리턴 타입에는 적용이 어려운 단점
func someRet<T: Comparable>() -> T {
    10 // Cannot convert return expression of type 'Int' to return type 'T'
}
  • enum 타입을 이용하여 리턴 타입을 여러개 두는 방법
enum SomeRetType {
    case int(Int)
    case string(String)
}

func someRet() -> SomeRetType {
    if true {
    	return .int(0)
    } else {
    	return .string("string")
    }
}
  • protocol을 사용하는 방법 (프로토콜 지향 방법)
protocol MyAnyView {}

struct MyView1: MyAnyView {}
struct MyView2: MyAnyView {}

func someView() -> MyAnyView {
    if true {
        return MyView1()
    } else {
        return MyView2()
    }
}

사전 지식2) any와 some 키워드 이해하기 (opaque type)

  • some과 any는 반대의 개념
    • some은 타입을 제한
    • any는 타입을 추상화 (= Type Erasure)

https://developer.apple.com/videos/play/wwdc2022/110352/

/// Collection 타입으로 제한
some Collection

/// Collection 타입으로 추상화
any Collection
  • some, any 타입 사용
// Error: Protocol 'Collection' can only be used as a generic constraint because it has Self or associated type requirements
func someList1() -> Collection {
    return [1, 2, 3]
}

func someList2() -> some Collection {
    return [1, 2, 3]
}

func someList3() -> any Collection {
    return [1, 2, 3]
}
  • any와 some의 차이점은?
    • some은 배열의 Element 타입이 모두 동일해야하지만, any는 달라도 무방
protocol SomeType {}

struct Struct1: SomeType {}
struct Struct2: SomeType {}

func someList4() -> [some SomeType] {
    return [Struct1(), Struct2()] // Error: Type of expression is ambiguous without more context
}

func someList5() -> [any SomeType] {
    return [Struct1(), Struct2()]
}
  • 애플에서 제안하는 some, any 타입 사용
    • some을 우선적으로 사용하고 any가 필요한 경우만 그때 any를 사용할 것
    • 이유 > 프로그래밍에서는 개발자가 예측 가능한 프로그래밍을 해야, 유지보수가 용이한데 추상화를 크게 할 수록 예측 가능성이 떨어지므로

Type Erasure 란?

  • Type Erasure란 구체적인 특정 타입을 추상적인 타입으로 바꾸는 것
    • 타입을 지운다는 의미 = 추상화 한다는 의미
    • 타입을 지우는 이유는 사용하는 쪽에서 유연한 프로그래밍을 위함
    • (위에서 알아본 any가 바로 type erasure의 한 종류)
  • 애플에서는 비유적으로 type erased를 표현
    • any는 타입을 없애기 위해 상자를 씌운다는 의미 (= 추상화)
    • 상자를 씌운다는 의미는 또한 상자를 언제든 unboxing 하여 사용할 수 있다는 의미

ex) SwiftUI에서 AnyView 타입으로 변경하기 위한 eraseToAnyView를 따로 extension으로 추가하고, Image와 같은 곳에서 View로 변환하여 사용할 수 있도록 구현

  • Image에서 eraseToAnyView를 사용하여 Image의 타입을 지우고 AnyView를 반환하여 사용하는 쪽에서 View로 사용할 수 있도록 제공
extension View {  
    var eraseToAnyView: AnyView { AnyView(self) }
}

public extension Image {
    static var splashImage: (_ imageName: String) -> AnyView = { imageName in
        Image(imageName)
            .resizable()
            .aspectRatio(contentMode: .fit)
            .eraseToAnyView
    }
}

정리

  • type erase는 타입을 추상화 시키는 것이고, 핵심은 다시 타입을 되돌려서 사용이 가능 (unboxing)
  • any 키워드는 type erase의 대표적인 방법이고, some 키워드는 타입을 제한하는 방법 중 하나임을 이해
  • 예측 가능한 프로그래밍을 위해서 되도록 any보다는 some 키워드를 사용할 것

* 참고

https://developer.apple.com/videos/play/wwdc2022/110352/

https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html

 

Comments