🔥 제네릭 프로그래밍

399자
5분

제네릭을 사용하면 코드를 더욱 유연하고 재사용 가능하게 작성할 수 있습니다. 제네릭을 활용하면 중복 코드를 줄이고, 타입에 구애받지 않는 코드를 작성할 수 있죠. 이제 제네릭을 어떻게 사용하는지 알아보겠습니다.

제네릭 함수 및 타입 정의하기

제네릭 함수나 타입을 만들려면 꺾쇠 괄호(<>) 안에 이름을 작성하면 됩니다. 예를 들어, 다음 코드는 Item 타입의 요소를 지정한 횟수만큼 반복하여 배열을 만드는 제네릭 함수입니다.

func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
    var result: [Item] = []   // Item 타입의 빈 배열 생성
    for _ in 0..<numberOfTimes {
         result.append(item)  // 지정한 요소를 배열에 추가
    }
    return result             // 생성한 배열 반환
}
makeArray(repeating: "knock", numberOfTimes: 4)  // ["knock", "knock", "knock", "knock"]
swift

makeArray 함수는 Item 타입의 요소(item)와 반복 횟수(numberOfTimes)를 받아서 Item 타입의 배열을 반환하죠. 호출 시 "knock" 문자열과 횟수 4를 전달하면 ["knock", "knock", "knock", "knock"] 배열을 얻을 수 있습니다.

함수뿐만 아니라 클래스, 열거형, 구조체도 제네릭 형태로 만들 수 있습니다. 다음은 스위프트 표준 라이브러리의 옵셔널 타입을 구현한 예시입니다.

// 스위프트 표준 라이브러리의 옵셔널 타입 재구현
enum OptionalValue<Wrapped> {
    case none
    case some(Wrapped)
}
var possibleInteger: OptionalValue<Int> = .none  // Int 타입의 OptionalValue 변수 선언 및 초기화
possibleInteger = .some(100)                     // 값 할당
swift

OptionalValue 열거형은 Wrapped라는 제네릭 타입을 사용하여 정의되었습니다. possibleInteger 변수는 Int 타입의 OptionalValue로 선언되었고, .none으로 초기화한 후 .some(100)으로 값을 할당했죠.

제네릭 제약 조건 지정하기

제네릭 타입에 제약 조건을 추가하려면 where 키워드를 사용하면 됩니다. 예를 들어, 타입이 특정 프로토콜을 준수하도록 요구하거나, 두 타입이 같아야 한다는 조건을 지정할 수 있습니다. 다음 코드를 볼까요?

func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool
    where T.Element: Equatable, T.Element == U.Element
{
    for lhsItem in lhs {
        for rhsItem in rhs {
            if lhsItem == rhsItem {  // 두 시퀀스에 공통 요소가 있는지 확인
                return true
            }
        }
    }
   return false
}
anyCommonElements([1, 2, 3], [3])  // true
swift

anyCommonElements 함수는 두 개의 시퀀스(TU)를 받아서 공통 요소가 있는지 여부를 반환합니다. where 절을 사용하여 TU의 요소 타입이 Equatable 프로토콜을 준수해야 하고, 서로 같은 타입이어야 한다는 제약 조건을 지정했습니다.

<T: Equatable>처럼 작성하는 것은 <T> ... where T: Equatable과 같은 의미입니다.

정리하면, 제네릭은 타입에 구애받지 않는 유연하고 재사용 가능한 코드를 작성할 수 있게 해줍니다. 꺾쇠 괄호(<>) 안에 이름을 작성하는 것으로 제네릭 함수나 타입을 손쉽게 정의할 수 있죠. 또한 where 키워드를 사용하면 제네릭 타입에 제약 조건을 추가할 수도 있습니다. 이렇게 제네릭을 활용하면 코드의 중복을 최소화하고 타입 안전성을 크게 향상시킬 수 있어요. 여러분도 제네릭의 강력함을 경험해 보시고, 더욱 효율적이고 유연한 코드를 작성해 보세요!