[내일배움캠프 24일차] 제너릭 (Generic) 복습

NH·2025년 4월 3일

내일배움캠프

목록 보기
24/62
post-thumbnail

Swift 제너릭(Generic)

  • Swift의 제너릭(Generic) 은 타입을 유연하게 사용할 수 있도록 하는 기능
  • 같은 로직을 Int, String, Double 등 다양한 타입에서 사용할 수 게 해준다.

제너릭이 필요한 이유

  1. 코드 중복 방지: 같은 로직을 여러 타입에 대해 반복해서 작성하지 않아도 됨
  2. 타입 안전성 보장: 컴파일 시점에 타입을 체크해서 오류를 방지
  3. 유연성 증가: 다양한 타입을 처리할 수 있도록 함

🔵 제너릭 기본 문법

제너릭은 <T> 같은 타입 파라미터를 사용

  • 예제

    func swapValues<T>(_ a: inout T, _ b: inout T) {
       let temp = a
       a = b
       b = temp
    }
    
    var x = 5
    var y = 10
    swapValues(&x, &y)
    print(x, y) // 10, 5
  • <T>: 제너릭 타입을 선언

  • T를 사용해 어떤 타입이든 받을 수 있도록 설계


🔵 제너릭을 활용한 실습 예제 3가지

🔹 [실습 1] 제너릭을 활용한 Stack 구조 구현

목표: Int, String 등 다양한 타입을 저장할 수 있는 스택(Stack) 만들기

struct Stack<T> { // T는 어떤 타입이든 받을 수 있는 제너릭 타입
    private var elements: [T] = [] // 제너릭 타입 배열 추가
    
    mutating func push(_ element: T) {
        elements.append(element) // 배열 요소 추가
    }
    
    mutating func pop() -> T? {
        return elements.popLast() // 마지막 요소 제거 후 반환
    }
    
    func peek() -> T? {
        return elements.last // 마지막 요소 확인
    }
}

var intStack = Stack<Int>() // Int 타입 인스턴스 생성
intStack.push(1) // 1 넣기
intStack.push(2) // 2 넣기
print(intStack.pop()) // 마지막 요소인 2 제거 후 2 출력

var stringStack = Stack<String>() // String 타입 인스턴스 생성
stringStack.push("Hello") // Hello 넣기
stringStack.push("Swift") // Swift 넣기
print(stringStack.pop()) // 마지막 요소 Swift 제거 후 "Swift" 출력

배운점 & 느낀점

  • 제너릭을 사용해 어떤 타입이든 스택을 만들 수 있게 함!
  • T를 활용해 Int, String 등 여러 타입에서 활용 가능

🔹 [실습 2] 두 개의 값을 비교하는 제너릭 함수

목표: 두 개의 값이 같은지 비교하는 제너릭 함수 만들기

func isEqual<T: Equatable>(_ a: T, _ b: T) -> Bool {
    return a == b
}

print(isEqual(10, 10)) // true
print(isEqual("Swift", "swift")) // false

T: Equatable 제약을 걸어 == 비교 연산을 지원하는 타입만 받도록 설정


🔹 [실습 3] 제너릭을 활용한 프로토콜 구현

목표: 제너릭을 활용한 Container 프로토콜 만들기

protocol Container {
    associatedtype Item // 제너릭 타입 지정
    mutating func add(_ item: Item)
    func getAll() -> [Item]
}

struct Box<T>: Container {
    var items: [T] = []
    
    mutating func add(_ item: T) {
        items.append(item)
    }
    
    func getAll() -> [T] {
        return items
    }
}

var intBox = Box<Int>()
intBox.add(10)
intBox.add(20)
print(intBox.getAll()) // [10, 20]

var stringBox = Box<String>()
stringBox.add("Hello")
stringBox.add("Swift")
print(stringBox.getAll()) // ["Hello", "Swift"]

associatedtype 을 사용해 프로토콜이 특정 타입을 다룰 수 있도록 구현!
Box<T>Container 프로토콜을 채택해 유연한 자료구조를 제공


🔵 정리

  • 제너릭 함수 : 여러 타입을 받을 수 있는 함수 생성 (<T>)
  • 제너릭 타입 : 구조체, 클래스, 열거형에서도 제너릭 적용 가능
  • 제너릭 프로토콜 : associatedtype을 활용해 프로토콜도 제너릭화

✍️ 배운점 & 느낀점

  • 제너릭 이해하고 나면 코드 중복도 줄이고, 타입을 유연하게 다룰 수 있을 거야!
  • 제너릭 타입을 사용하면 다양한 타입에 대해 유연하고 재사용 가능한 코드를 작성할 수 있는 것을 배웠다.
  • 또, 제너릭이 모든 타입에 대응하게 하는 것이 아닌, 특정 조건을 부여하여 제약을 걸어줄 수 있다는 것도 배웠다.
  • 특히 프로토콜을 사용하는 방법이 조금 어렵긴 했지만, 제너릭에 프로토콜에 준수하는 타입만 사용하게 제약을 걸어주는 것과 associatedtype을 활용해 프로토콜도 제너릭화 하는것을 보면서 한번 더 프로토콜의 위대함을 느꼈다.
profile
iOS 개발 블로그

0개의 댓글