오늘은 한번 정리하고 싶었던 주제인 프로토콜 지향 프로그래밍에 대해서 정리하는 시간을 가져보자 🙂
프로토콜지향 프로그래밍(Protocol-Oriented-Programming, POP)란 Swift 언어에서 중요한 패러다임 중 하나로, 객체 지향 프로그래밍과 함께 사용할 수 있지만 보다 유연하고 모듈화된 코드를 작성할 수 있게 해준다.
프로토콜 지향 프로그래밍에서는 코드 재사용성을 극대화하고, 다형성을 달성하기 위해 프로토콜을 활용한다고 이해하면 된다!
먼저 기본인 프로토콜에 대해서 알아보자
프로토콜은 특정 작업이나 속성에 대한 인터페이스를 정의해두는 꼭 지켜야 하는 규칙이라고 이해하면 된다. 클래스, 구조체, 열거형 등 프로토콜을 채택하면 해당 프로토콜에서 정의한 메서드나 속성을 반드시 구현해야 한다.
Swift에서는 다중 상속이 불가능하지만 여러 프로토콜을 채택할 수 있어 유사한 기능을 제공한다!
protocol Drivable {
var speed: Double { get set }
func drive()
}
다음은 프로토콜 지향 프로그래밍의 특징을 살펴보자
- 구현 가능 프로토콜(Protocol with Default Implementation) : Swift 에서는 프로토콜에 기본 구현을 제공할 수 있다. 이로 인해 프로토콜을 채택한 모든 타입에서 공통된 동작을 쉽게 재사용할 수 있다.
protocol Drivable {
var speed: Double { get set }
func drive()
}
extension Drivable {
func drive() {
print("Driving at \\(speed) km/h")
}
}
- 프로토콜 확장(Protocol Extensions) : 프로토콜을 확장해 기본 구현을 추가하거나 새로운 메서드와 속성을 추가할 수 있다. 이렇게 구현하면 프로토콜을 채택한 모든 타입에서 해당 구현을 사용할 수 있다.
extension Drivable {
func increaseSpeed(by amount: Double) {
speed += amount
print("Increased speed to \\(speed) km/h")
}
}
- 프로토콜 합성(Protocol Composition) : 여러 프로토콜을 결합하여 새로운 프로토콜을 만들거나, 함수의 매개변수나 반환 타입으로 사용할 수 있다.
protocol Flyable {
var altitude: Double { get set }
func fly()
}
typealias FlyableDrivable = Drivable & Flyable
func testFlyableDrivable(vehicle: FlyableDrivable) {
vehicle.drive()
vehicle.fly()
}
프로토콜 지향 프로그래밍 VS 객체 지향 프로그래밍
- 클래스 계층 구조 대신 프로토콜 사용 : 객체 지향 프로그래밍에서는 클래스를 계층적으로 상속받아 기능을 확장하는 방식으로 코드를 구성한다. 반면에 프로토콜 지향 프로그래밍은 클래스를 상속 받는 대신 여러 프로토콜을 채택하여 필요에 따라 기능을 조합하는 방식이다.
- 구조체와 함께 사용 : POP에서는 클래스를 사용하는 대신, 구조체와 프로토콜을 함께 사용하는 경우가 많다 구조체는 값 타입으로 복사 시 독립적인 복사본이 생성되며, 이는 멀티스레드 환경에서 안전한 코드를 작성하는데 유리하다.
프로토콜 지향 프로그래밍의 장점
- 유연성 : 프로토콜을 사용하면 서로 다른 타입에 동일한 인터페이스를 강제할 수 있다. 이로 인해 코드의 유연성과 재사용성이 높아진다.
- 구현 강제 : 프로토콜을 채택한 타입은 해당 프로토콜에서 요구하는 모든 속성과 메서드를 구현해야 하므로 코드의 일관성을 유지할 수 있다.
- 다형성 : 프로토콜을 사용하면 여러 타입을 동일한 방식으로 처리할 수 있다. 예를 들어 여러 타입이 Drivable 프로토콜을 채택하면 해당 타입의 객체들을 같은 방식으로 조작할 수 있다.
protocol Drivable {
var speed: Double { get set }
func drive()
}
extension Drivable {
func drive() {
print("Driving at \\(speed) km/h")
}
}
struct Car: Drivable {
var speed: Double
var fuelLevel: Double
func refuel() {
print("Refueling the car.")
}
}
struct Bicycle: Drivable {
var speed: Double
}
let myCar = Car(speed: 120, fuelLevel: 0.8)
let myBicycle = Bicycle(speed: 15)
myCar.drive() // Driving at 120 km/h
myBicycle.drive() // Driving at 15 km/h
예제를 살펴보면 Car 와 Bicycle 모두 Drivable 프로토콜을 채택해 drive 메서드를 사용하고 있다. Car와 Bicycle은 서로 다른 타입이지만 동일한 프로토콜을 채택함으로써 동일한 인터페이스를 제공 받는다 🙂
프로토콜 지향 프로그래밍은 유연하고 재사용 가능한 코드를 작성하는데 매우 유용하다 OOP의 단점을 보완하고 특히 Swift의 구조체와 같은 값 타입과 함께 사용하면 더 큰 장점을 발휘한다. 이 프로토콜 지향 프로그래밍을 잘 파악해서 모듈화된 유지보수가 쉬운 코드를 작성하도록 노력하자!!
오늘은 여기까지!!
'◽️ Programming > iOS' 카테고리의 다른 글
HealthKit에 대해서 알아보고 데이터 가져오기 :) (2) | 2024.09.04 |
---|---|
Clean Architecture에 대해서 알아보자 :) (0) | 2024.09.02 |
GCD와 DispatchQueue는 같은 걸까? (0) | 2024.08.22 |
iOS TestFlight에 대해서 알아보자 (1) | 2024.06.19 |
MVVM 디자인 패턴 알아보기 🧑🏻💻 (0) | 2024.05.10 |