김경록의 앱 개발 여정

[Swift] existential type과 any키워드(Boxed Protocol Type) 본문

TIL

[Swift] existential type과 any키워드(Boxed Protocol Type)

Kim Roks 2025. 1. 9. 18:37

현업 친구의 코드 리뷰

큰 고민없이 작성했던 any 키워드에 대해 꼭 필요하다고 생각하냐고 물어봐서

이상한건가 하고 삭제 처리했는데 이렇게 찾아보기로 했다.

existential type의 정의

프로토콜을 따르는 타입의 값들을 나타내는 용도

그니까 결국 프로토콜이 type으로 사용될때 그 타입을 부르는 명칭이 바로 existentials type이다.

existential type의 문제점

일반적으로 항상 사용하던게 맞다. 하지만 이게 문제가 있는데

가독성의 문제

가독성 차원에서의 문제가 있을 수 있다.

protocol Animal {
    func makeSound()
}

struct Dog: Animal {
    func makeSound() {
        print("Woof")
    }
}

struct Cat: Animal {
    func makeSound() {
        print("Meow")
    }
}
// Existential type을 사용하지만, 'any' 키워드가 없어서 명시적이지 않음

let animals: [Animal] = [Dog(), Cat()]

for animal in animals {
    animal.makeSound()
}

이런 형태가 과거 5.6 버전 이전의 Existential type의 문제였는데

코드가 복잡해졌을때 저 Animal이 Concreate Type 인지 Existential Type인지 모르기때문이다.
우리 모두는 마지막에 쓰인 Animal타입이 Existential 타입인지 Concerate 타입인지 직접 확인하기전까진 모른다.

성능적인 이슈

어쩃든 Existential Type 을 사용했다는것은 컴파일 될 때 어떤 Type을 사용할 지 잘 모른다는것이다.

(프로토콜은 추상타입이며 어떤 Concreate Type을 가져다 쓸지 모른다는것)

고로 Static Dispatch 가 아닌 Dynamic DisPatch 를 사용하게 되며,

비용적인 측면에서 Generic을 통한 다형성을 이용하는것보다는 훨씬 비쌀 수 밖에 없다.

자세한 내용은 여기에 서술하지 않겠다
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/opaquetypes

이 페이지에서 Boxed Protocol Types 에 관한 내용을 읽어보면 좋다.

결론

비용이 비싸면 쓰면 안된다? 그건 아니라고 생각한다. 다만 알고 있다면 조금 더 생각 할 여지가 있다는것
내가 위에서 말했던 "아무 생각없이 프로토콜을 타입으로 사용하는것"은 비용적인 대가가 있는 행위라는것을 알고 있는것과 모르는것은 다르다는것이다.

작성자로 하여금 조금 더 생각 할 턴을 주고(?) 가독성적으로도 더 나은 Existential Type의 사용을 위해 고안된게

5.6이후 버전의 내용이다

// Existential Type을 사용할때 any 키워드를 붙일 수 있게됨 -> 가독성 up
let animals: [any Animal] = [Dog(), Cat()]

이런식으로 Existential Type을 사용할 땐 any 키워드를 포함시킬 수 있게되었다고 한다.

글 작성일 기준으로 아직 버전이 5.10 인것으로 알고있는데 현재는 붙여도 되고 안붙여도 상관이 없지만

내 리뷰어가 얘기해준 6.0 버전 이후론 권장 사항이 아니라 필수 사항이 된다고 한다(안붙이면 에러띄움)

아무래도 친구는 코드 컨벤션의 통일을 위해 물어봤던 것 같다.

참고한 내용