[Swift] Swift 5.6 의 Existential any

이제부터 existential type 앞에 any 를 붙여쓰자

naljin
8 min readMar 25, 2022

개-하!!! 다들 Swift 5.6 Release 된거 알구 현생 살고 계시는쥐!?!!

저는 물론 몰랐다가 오늘 알았기 때문에,, ◠‿◠ 스윽 보다가 알아두면 좋을 것 같은 내용인 “SE-0335 — Introduces existential any" 를 들고 돌아왔습니다

아 뭔지 앎 ㅅㄱ! 하시는 분들은 뒤로 가기를 누르는 것으로하고,,,,,,,,!!!

아직 남아 계신 분들은,, 혹시 existential type 이 뭔지 아시나요??

바로 protocol 이 type 으로 사용될 때, 해당 type을 “existential type” 라고 합니다

무슨 말인지 코드를 보면 바로 이해갈텐데요,

protocol P {}
protocol Q {}
struct S: P, Q {}

let p1: P = S() // 해당 맥락에서 'P' 는 existential type

위에서 protocol Pp1 의 type 으로 사용되었으므로, 이 맥락에서 P 는 existential type 입니다.

어떤 concrete type 이든 상관 없이 해당 protocol 을 conform 하면 모두 existential type 에 할당될 수 있져 ㅇㅇ (+ 추상화 쌉 파서블!)

뭔 말인지는 예시로 설명을 이어가볼게요!

protocol P {}
struct S: P {}
class C: P {}

var p1: P = S() // ㅇㅋ
p1 = C() // ㅇㅋ

SC 라는 두개의 concrete type 모두 protocol P 를 conform 하고 있기 때문에 p1 변수에 들어갈 수 있슴다

🤷🏻‍♀️ : 아 rgrg~~ 나 이렇게 평소에 잘 써왔는데 existential type 이라는 용어가 걍 생소했을 뿐임~ protocol 이 type 으로 사용되는 맥락에서는 existential type 이라고 한다고?? ㅇㅋㅇㅋ!

근데 여러분,,, 아래 코드를 한번 볼게요. 뭐가 concrete type 이고 뭐가 existential type 인지 구분 가능한가여??

var foo: Foo
var bar: Bar

하나 더 보겠습니다. Vehicle 이 concrete type 인지 existential type 인지 구분이 가나요??

func travel(using vehicle: Vehicle) { }

마지막으로 하나 더! ConcreteP 라는 Generic 이 P 라는 protocol conform 이 필요한건지, class inherit 가 필요한건지 구분이 가시나요?

func generic<ConcreteP: P>(p: ConcreteP) { }

여기까지 혼란스러우셨다면,,?! 삐빅 정상입니다.

concrete type 이든 existential type 이든 선언되는 방식이 동일해서 지금 뭐가 뭔지 알 수 없는 상황이죠 ㅇㅇ!

🤷🏻‍♀️ : 아니 내 잘못임??? Swift 가 애초에 구분 안가게 만들어놨구만 어쩌라고~~~~

맞아요. 우리 잘못은 아니지만,,,! 어쨌든 이런 특성은 개발자들의 혼란을 야기해왔고 종종 코드를 다시 작성해야 하는 경우까지도 발생했다고 합니다.

또한 existential type 은 concrete type 보다 더 많은 비용이 듭니다. existential type 안에는 (protocol conform만 한다면) 값의 type 이 동적으로 변경될 수 있기 때문이죠! 이는 dynamic memory 가 필요함을 의미하고, heap 할당과 reference counting 까지 더해져 existential type 을 사용하는 코드에서는 pointer indirection 와 dynamic method dispatch 가 발생합니다.

이렇게 existential type 을 사용할 때는 concrete type보다 더 많은 비용이 요구됨에도 불구하고, 지금까지 개발자에게 이 퍼포먼스 비용을 나타내는 명확한 구분은 없었습니다.

🤷🏻‍♀️ : 흠 그래서 어쩌자고??

 : 이제 existential types 에 명시적으로 any 를 붙여서 명확히 구분시킬거임!!!!!!!!!!!!!!!!!!!!!!!

좋아여 등장 배경만 알았으면 머,, 오늘 내용은 다 끝났다고 생각하구요,,? ㅋㅎ

이제 Swift 5.6 부터 existential type 앞에 any 키워드가 붙을 수 있어요!

protocol P {}
protocol Q {}
struct S: P, Q {}
let p: any P = S()
let pq: any P & Q = S()
protocol Vehicle {}
func travel(using vehicle: any Vehicle) { }

앞에 내용이 길었던거치고 실제 코드는,, 뭐 별거 없죠?

추가로 메타타입 관련 변경 사항은 아래와 같습니다

  • existential metatype (protocol을 inherit 하고 있는 타입의 메타 타입) : P.Type -> any P.Type
  • protocol metatype : P.Protocol -> (any P).Type
  • protocol metatype value : P.self -> (any P).self

전 / 후 코드를 비교해보져

protocol P {}
struct S: P {}
// 전
let existentialMetatype: P.Type = S.self
let protcolMetatype: P.Protocol = P.self
// 후
let existentialMetatype: any P.Type = S.self
let protcolMetatype: (any P).Type = (any P).self

ㅇㅋㅇㅋ??

Swift 5.6 에서는 any 키워드를 이용해서 명시적으로 existential type 을 선언할 수 있다~ 정도지만, 추후 버전에서는 any 를 명시 하지 않으면 warning이 뜨고, Swift 6 부터는 error 를 띄울 계획이라고 합니다

그러니까 나중에 error 떠서 고치는 부분을 한 곳이라도 줄이려면 지금부터 any 키워드를 사용해서 existential type 을 선언하는 습관을 들여야겠네요 ㅎ ㅠ

오늘은 여기까지 알아보는걸로!! 그럼 20000!!!

출처

--

--

No responses yet