역할: 객체의 인터페이스를 정의하여 외부와의 상호작용 통로 제공.
추상화: 필요한 정보와 동작만 노출하여 내부 구현을 캡슐화.
다형성 지원: 클래스, 구조체, 열거형 모두 프로토콜을 채택 가능하며, 이를 통해 클래스 외의 타입에서도 다형성을 구현.
프로토콜 확장: 프로토콜 기본 구현을 제공하여 채택하는 타입들이 선택적으로 활용 가능.
protocol Drawable {
func draw()
}
struct Circle: Drawable {
func draw() { print("Drawing a Circle") }
}
struct Rectangle: Drawable {
func draw() { print("Drawing a Rectangle") }
}
func render<T: Drawable>(_ item: T) {
item.draw()
}
render(Circle()) // 출력: Drawing a Circle
render(Rectangle()) // 출력: Drawing a Rectangle
protocol Animal {
var name: String { get }
func makeSound()
}
struct Dog: Animal {
var name: String
func makeSound() { print("Bark!") }
}
struct Cat: Animal {
var name: String
func makeSound() { print("Meow!") }
}
func playWithAnimal(_ animal: Animal) {
print("Playing with \(animal.name)")
animal.makeSound()
}
let dog = Dog(name: "Buddy")
playWithAnimal(dog) // 출력: Playing with Buddy, Bark!
Boxed Protocol Type
Boxed Protocol Type는 existential type(실존적 타입)을 통해 정의되며, 이는 다음의 조건을 만족하는 타입을 의미:
"어떤 타입 T가 있으며, 그 타입 T는 특정 프로토콜을 준수한다."
Boxed Protocol의 필요성
Swift 5.7 이전에는 프로토콜 타입 사용 시 컴파일러가 Boxing(타입 정보를 감추는 과정)을 자동으로 처리했습니다. 그러나 이로 인해 성능 이슈와 타입 안정성 문제가 발생할 수 있었습니다.
이를 해결하기 위해 Swift는 any 키워드를 도입하여 프로토콜 타입을 명시적으로 나타내게 했습니다.
any키워드 사용 예시
protocol Vehicle {
func drive()
}
struct Car: Vehicle {
func drive() { print("Driving a car") }
}
struct Bike: Vehicle {
func drive() { print("Riding a bike") }
}
// 기존 스타일 (경고 발생 가능)
func operateVehicle(_ vehicle: Vehicle) {
vehicle.drive()
}
// 권장 스타일
func operateVehicle(_ vehicle: any Vehicle) {
vehicle.drive()
}
let myCar: any Vehicle = Car()
operateVehicle(myCar) // 출력: Driving a car
any 키워드: 명시적으로 existential type을 선언하여 혼동 방지 및 코드 명확성 향상.
유연성 제공: 런타임에 타입을 결정하며, 다양한 타입을 담을 수 있음.
타입 정보 감춤: 내부 구현의 구체적 타입을 숨기고, 외부에는 공통 인터페이스만 노출.
Boxed Protocol Type은 Swift의 타입 안정성과 명확성을 강화하기 위해 도입된 개념입니다.
any 키워드는 프로토콜 타입을 명확히 하며, 개발자가 구체적인 타입과 실존적 타입을 구분하여 사용하도록 유도합니다.
Protocol은 다형성을 제공하고, 제네릭과 함께 활용 시 강력한 추상화 수단으로 작용합니다.