🔥 제네릭이 해결하는 문제

395자
4분

제네릭은 Swift 프로그래밍에서 매우 강력하고 유용한 기능 중 하나입니다. 제네릭을 사용하면 코드의 재사용성과 유연성을 크게 향상시킬 수 있죠. 그럼 제네릭이 어떤 문제를 해결하는지 자세히 살펴볼까요?

먼저, 두 개의 Int 값을 서로 교환하는 swapTwoInts(_:_:) 함수를 살펴봅시다:

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a // a의 값을 temporaryA에 임시 저장
    a = b // b의 값을 a에 할당
    b = temporaryA // temporaryA의 값(원래 a의 값)을 b에 할당
}
swift

이 함수는 inout 매개변수를 사용하여 ab의 값을 교환합니다. inout 매개변수에 대한 자세한 설명은 In-Out Parameters에서 확인할 수 있습니다.

swapTwoInts(_:_:) 함수는 원래 b의 값을 a에 넣고, 원래 a의 값을 b에 넣습니다. 이 함수를 호출하여 두 개의 Int 변수의 값을 교환할 수 있습니다:

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// "someInt is now 107, and anotherInt is now 3"이 출력됩니다.
swift

swapTwoInts(_:_:) 함수는 유용하지만, Int 값에만 사용할 수 있다는 한계가 있습니다. 만약 두 개의 String 값이나 Double 값을 교환하고 싶다면, 아래와 같이 swapTwoStrings(_:_:)swapTwoDoubles(_:_:) 함수를 추가로 작성해야 합니다:

func swapTwoStrings(_ a: inout String, _ b: inout String) {
    let temporaryA = a
    a = b
    b = temporaryA
}
 
func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
    let temporaryA = a
    a = b
    b = temporaryA
}
swift

swapTwoInts(_:_:), swapTwoStrings(_:_:), swapTwoDoubles(_:_:) 함수의 내용이 동일하다는 점을 눈치채셨나요? 유일한 차이점은 받아들이는 값의 타입(Int, String, Double)뿐입니다.

훨씬 더 유용하고 유연한 방법은 '모든' 타입의 두 값을 교환하는 단일 함수를 작성하는 것입니다. 바로 여기서 제네릭 코드가 등장합니다. (이러한 함수의 제네릭 버전은 아래에 정의되어 있습니다.)

func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
    let temporaryA = a // 제네릭 타입 T의 값을 temporaryA에 저장
    a = b // b의 값을 a에 할당
    b = temporaryA // temporaryA의 값을 b에 할당
}
swift

제네릭 함수 swapTwoValues<T>(_:_:)는 타입 매개변수 T를 사용하여 어떤 타입의 값이라도 교환할 수 있습니다. 이제 Int, String, Double 등 모든 타입에 대해 단 하나의 함수로 값 교환이 가능해졌네요.

var genericInt = 3
var genericString = "Hello"
var genericDouble = 3.14
 
swapTwoValues(&genericInt, &anotherInt)
swapTwoValues(&genericString, &"World")
swapTwoValues(&genericDouble, &2.71)
 
print(genericInt) // 107
print(genericString) // "World"
print(genericDouble) // 2.71
swift

이렇게 제네릭을 사용하면 코드 중복을 제거하고, 더 유연하고 재사용 가능한 함수와 타입을 만들 수 있습니다. 제네릭은 Swift 표준 라이브러리에서 광범위하게 사용되며, 배열(Array), 딕셔너리(Dictionary), 세트(Set), 옵셔널(Optional) 등 다양한 범용 콜렉션 타입을 구현하는 데 핵심적인 역할을 합니다.