Swift는 강력한 타입 시스템과 프로토콜 지향 프로그래밍을 강조하는 언어입니다. Swift 5.1과 5.7에서는 이를 더욱 강화하기 위해 some과 any 키워드를 도입했습니다. 이 글에서는 Protocol, some Protocol, any Protocol의 차이를 자동차 예제를 통해 쉽게 이해해 보겠습니다.
1. Protocol
우선, 기본적인 프로토콜 선언부터 살펴보겠습니다. 프로토콜은 특정 요구 사항을 정의하여 클래스, 구조체, 열거형이 이를 준수하도록 합니다. 여기서는 자동차에 대한 기본 요구 사항을 정의하는 Car 프로토콜을 만들어 보겠습니다.
protocol Car {
var name: String { get }
func drive()
}
class Sedan: Car {
var name: String = "Sedan"
func drive() {
print("Driving a sedan")
}
}
class SportsCar: Car {
var name: String = "Sports Car"
func drive() {
print("Driving a sports car")
}
}
let myCar: Car = Sedan()
myCar.drive() // "Driving a sedan"
이 예시에서 Car 프로토콜은 모든 자동차가 가져야 할 name 속성과 drive 메서드를 정의합니다. Sedan과 SportsCar 클래스는 이 프로토콜을 준수하며, 각각의 drive 메서드를 구현합니다.
2. some Protocol
some 키워드는 특정한 프로토콜 타입을 준수하는 불투명한 타입을 반환할 때 사용됩니다. 이는 반환 타입을 감추면서도 프로토콜을 준수하는 타입을 반환할 때 유용합니다. Swift 5.1부터 도입된 기능입니다.
protocol Car {
var name: String { get }
func drive()
}
class Sedan: Car {
var name: String = "Sedan"
func drive() {
print("Driving a sedan")
}
}
class SportsCar: Car {
var name: String = "Sports Car"
func drive() {
print("Driving a sports car")
}
}
func getCar() -> some Car {
return Sedan() // 여기를 SportsCar()로 바꿔도 함수 시그니처는 동일하게 유지됩니다.
}
let myCar = getCar()
myCar.drive() // "Driving a sedan"
이 예시에서 getCar 함수는 some Car을 반환합니다.
이는 구체적인 타입을 감추면서도 반환된 객체가 Car 프로토콜을 준수한다는 것을 보장합니다. 프로토콜은 자체적으로 구체적인 타입을 나타내지 않습니다. 프로토콜은 단지 메서드와 속성의 집합을 정의할 뿐, 실제 구현을 제공하지 않습니다. 따라서, 컴파일러는 어떤 구체적인 타입을 반환될지 알 수 없습니다.
또한 프로토콜 내에서 associatedtype이나 Self를 사용해서 정의하게 되었을때도 구체적인 타입이 명확히 알지 못하면 타입 안정성을 보장할 수 없습니다.
some키워드를 사용하면 클라이언트 코드가 구체적인 타입을 알 필요 없이 프로토콜을 통해 상호작용할 수 있습니다.
3. any Protocol
any 키워드는 다양한 타입의 인스턴스를 포함할 수 있는 컬렉션을 만들 때 사용됩니다. 이는 여러 종류의 자동차를 하나의 컬렉션에 담을 때 유용합니다. Swift 5.7부터 도입된 기능입니다.
protocol Car {
var name: String { get }
func drive()
}
class Sedan: Car {
var name: String = "Sedan"
func drive() {
print("Driving a sedan")
}
}
class SportsCar: Car {
var name: String = "Sports Car"
func drive() {
print("Driving a sports car")
}
}
let garage: [any Car] = [Sedan(), SportsCar()]
for car in garage {
car.drive()
}
// "Driving a sedan"
// "Driving a sports car"
이 예시에서 garage 배열은 any Car 타입의 요소들을 포함합니다. 이는 다양한 타입의 자동차 객체를 하나의 배열에 담을 수 있게 해줍니다. 각 자동차 객체는 Car 프로토콜을 준수하므로, drive 메서드를 호출할 수 있습니다.
왜 some과 any 키워드가 탄생했는가?
Swift는 타입 안전성과 추상화를 강조하는 언어입니다. some과 any 키워드는 이런 철학을 구현하기 위해 도입되었습니다.
some Protocol의 필요성:
1. 타입 숨김: 함수나 메소드의 반환 타입을 감추고 싶을 때 유용합니다. 반환 타입이 특정 프로토콜을 준수한다는 것만 공개하고 구체적인 타입을 숨길 수 있습니다.
2. 추상화 유지: 클라이언트 코드가 구체적인 타입을 알 필요가 없을 때 추상화를 유지할 수 있습니다.
any Protocol의 필요성:
1. 다양한 타입 수용: 서로 다른 타입이 같은 프로토콜을 준수한다면, 이를 하나의 컬렉션이나 변수에 담아 다룰 수 있도록 합니다.
2. 유연성 증가: 여러 타입의 인스턴스를 처리하는 데 필요한 유연성을 제공합니다.
some은 반환 타입의 추상화를 제공하여 타입 안전성을 유지하면서도 유연한 설계를 가능하게 하고, any는 실행 시점에 다양한 타입을 다루는 유연성을 제공합니다. 두 키워드는 모두 Swift의 강력한 타입 시스템을 더 잘 활용하고 코드의 추상화 수준을 높이는 데 기여합니다.
결론
Swift에서의 Protocol, some Protocol, any Protocol의 차이를 이해하는 것은 강력하고 유연한 코드를 작성하는 데 필수적입니다. 이 글에서 제공한 자동차 예제와 함께 some과 any 키워드의 사용 이유를 이해하면, 더 나은 Swift 코드를 작성하는 데 큰 도움이 될 것입니다.
'Apple > Apple_Swift' 카테고리의 다른 글
KeyPath란? (0) | 2024.08.08 |
---|---|
상속에 대한 기본 개념과 기능 누락 방지 방법 (0) | 2024.08.07 |
indirect 키워드 (0) | 2024.07.28 |
@resultBuilder (0) | 2024.06.26 |
Swift Package Manager: Package.swift 간단 구조 정리 (0) | 2024.03.26 |