cleanUrl: /programming/swift-generics

Generic이 뭔지는 대충 알고 있었지만, “꺽쇄 있는 그거”로 대충 뭉개고 이해하고 있었는데, 이번에 Swift 5.1의 여러 기능들이 Generic과 연관이 많다고 해서 제대로 짚고 넘어가보려 합니다. 그리고 Generic의 효용을 알기 위해서 먼저 Swift의 타입시스템을 잠시 들여다 보겠습니다.

Swift의 타입시스템

Swift는 아주 강력한 타입시스템을 가진 언어입니다. 즉, 아래와 같은 JavaScript코드는 Swift에서는 빌드되지 않습니다.

// 다른 두 개의 타입 값으로 연산을 하는 JavaScript
function sum(a, b) {
    return a + b
}
sum(1,2) // returns 3
sum("1", 2) // returns "12"
1 == "1" // returns true
1 === "1" // returns false
// 그런 꼴은 눈 뜨고는 못 보는 Swift
func sum(a: Int, b: Int) {
    return a + b
}
sum(1,2) // returns 3
sum("1", 2) // Build Error!!
1 == "1"  // Build Error!! (Not even False)

이런 강력한 타입시스템은, 훨씬 더 안전하고 버그가 없는 프로그램을 만드는데 크게 기여합니다. 예를 들어 “1” + 1 = “11” 일 수도 있지만, “1” + 1 = 2 일 수도 있죠. 프로그램을 돌려보기 전 까지는 이 언어가 어떤 식으로 동작 할 지 예측 할 수 없습니다.

즉, JavaScript가 “이런들 어떠하리 저런들 어떠하리” 하면서 태연하게 두 값을 더해 버린다면, Swift는 “이 몸이 죽고죽어 일백번을 고쳐죽어도 숫자랑 문자열은 못 더한다!!” 라고 주장하는 언어입니다.

타입시스템의 안 좋은 점

그런데 이런 “안전함”에 따라오는 TradeOff가 있습니다. 예컨대, 두 정수를 더하는 함수를 만들어 봅시다.

func sum(a: Int, b: Int) -> Int {
    return a + b
}
sum(1,2) // 3

아, 잘 더해집니다. 하지만 위 함수에는 큰 단점이 있습니다. 바로 Float형태의 값들은 다루지 못한다는 점입니다.

sum(1.0, 2.0) // Couldn't convert Double 1.0 into Int

sum 함수는 당연히 정수형 값이 들어올 거라고 기대하고 있었는데 Float값이 들어오니, 당연히 불만을 가질 수 밖에 없지요.

따라서 우리는 어쩔 수 없이 Float 버전의 sum 함수를 만들어야만 합니다.

func sum(a: Float, b: Float) -> Float {
    return a + b
}
sum(1.0, 2.0) // 3.0

그리고 예상 했겠지만, Double 버전도 만들어야 합니다.

func sum(a: Double, b: Double) -> Double {
    return a + b
}

에… 또.. CGFloat 버전도 만들까요?

func sum(a: CGFloat, b: CGFloat) -> CGFloat {
    return a + b
}