학습
Swift 제네릭(Generics) 사용법
Swift 제네릭(Generics) 사용법 — 중급
제네릭(Generics) 사용법
1. 도입 (왜 배워야 하는가)
프로그래밍에서 제네릭(Generics)은 코드의 재사용성과 유연성을 극대화시켜줍니다. 많은 경우, 특정 데이터 타입에 종속되지 않고 다양한 타입을 처리할 수 있는 코드를 작성할 수 있기 때문에 실무에서 매우 유용합니다. 예를 들어, 제네릭을 사용하면 배열, 리스트, 딕셔너리와 같은 자료구조를 만들 때 각기 다른 타입의 데이터를 저장할 수 있습니다.
제네릭을 모르면, 각 데이터 타입에 대해 별도의 코드를 작성해야 하므로 코드가 중복되고 유지보수가 어려워질 수 있습니다. 또한, 타입에 따라 다르게 동작하는 함수를 여러 개 만들어야 하므로 코드의 가독성이 떨어지고, 버그가 발생할 확률이 높아집니다.
2. 핵심 개념 설명
제네릭은 특정 타입에 의존하지 않고 다양한 타입을 처리할 수 있는 기능입니다. 이를 통해 함수, 구조체, 클래스 등을 정의할 때 타입을 매개변수로 받아 사용할 수 있습니다.
실생활 비유
제네릭을 요리 도구에 비유할 수 있습니다. 예를 들어, 모든 종류의 음식을 만들 수 있는 다목적 요리 도구가 있습니다. 이 도구는 특정 음식에만 사용되는 것이 아니라, 다양한 조리법에 맞춰 활용할 수 있습니다. 제네릭도 마찬가지로, 특정 타입에 국한되지 않고 여러 타입에 적용할 수 있는 코드 구조를 제공합니다.
관련 용어 정리
| 용어 | 설명 |
|---|---|
| 제네릭 타입 | 다양한 데이터 타입을 받아들일 수 있는 타입 |
| 타입 매개변수 | 제네릭에서 사용되는 타입을 나타내는 변수 |
3. 기본 코드 예제
아래는 제네릭 함수를 사용하는 가장 기본적인 예제입니다. 두 개의 값을 비교하여 큰 값을 반환하는 함수입니다.
func max<T: Comparable>(a: T, b: T) -> T {
return a > b ? a : b
}
// 사용 예
let maxInt = max(a: 10, b: 20) // 20
let maxDouble = max(a: 3.5, b: 2.8) // 3.5
let maxString = max(a: "apple", b: "banana") // "banana"
실행 결과
maxInt: 20maxDouble: 3.5maxString: "banana"func max<T: Comparable>(a: T, b: T) -> T: 제네릭 함수 정의.T는Comparable프로토콜을 준수하는 타입을 의미.return a > b ? a : b: 두 값을 비교하여 큰 값을 반환.- 각 사용 예에서 서로 다른 타입의 값들에 대해
max함수를 호출하고 결과를 저장. - 타입 제약을 잊음
- 제네릭 타입을 명확히 하지 않음
- 제네릭을 사용하면 코드의 재사용성과 유연성을 높일 수 있다.
- 다양한 타입을 처리할 수 있는 함수 및 자료구조를 만들 수 있다.
- 타입 제약을 통해 안전한 코드를 작성할 수 있다.
코드 한 줄씩 동작 설명
4. 실전 활용 예제
예제 1: 쇼핑몰에서 장바구니를 구현할 때
struct CartItem<T> {
var item: T
var quantity: Int
}
var item1 = CartItem(item: "사과", quantity: 3)
var item2 = CartItem(item: 1001, quantity: 2) // 상품 ID
이 예제에서는 장바구니에 들어갈 수 있는 다양한 타입의 아이템(예: 과일 이름 또는 상품 ID)을 처리할 수 있습니다.
예제 2: 데이터 처리 함수
func printElements<T>(elements: [T]) {
for element in elements {
print(element)
}
}
printElements(elements: [1, 2, 3]) // 정수 배열
printElements(elements: ["A", "B", "C"]) // 문자열 배열
이 함수는 어떤 타입의 배열이든 출력할 수 있습니다.
5. 흔한 실수와 주의사항
- 잘못된 코드:
func add<T>(a: T, b: T) -> T { return a + b } // T는 + 연산을 지원하지 않음
- 올바른 코드:
func add<T: Numeric>(a: T, b: T) -> T { return a + b }
- 잘못된 코드:
func swap(a: Any, b: Any) { ... } // 타입 안전성이 없음
- 올바른 코드:
func swap<T>(a: inout T, b: inout T) { ... }
6. 정리
다음에 학습하면 좋은 주제는 Associated Types와 Protocol-Oriented Programming입니다. 제네릭과 함께 사용하면 더욱 강력한 타입 시스템을 구축할 수 있습니다.