본문 바로가기
카테고리 없음

15. 프로토콜(Protocol)과 프로토콜 지향 프로그래밍

by swifttt 2025. 4. 3.

 

Swift에서 프로토콜(Protocol)은 특정 기능을 수행하기 위한 속성이나 메서드의 청사진(blueprint)을 정의하는 타입입니다.
클래스, 구조체, 열거형 등 다양한 타입이 프로토콜을 채택하여 해당 요구사항을 구현할 수 있습니다.

Swift는 객체 지향 언어이면서도 프로토콜 지향 프로그래밍(protocol-oriented programming)을 강력하게 지원합니다.
이는 Swift의 핵심적인 설계 철학 중 하나로, 프로토콜을 활용한 유연한 추상화와 확장이 가능합니다.

1. 프로토콜 기본 문법

protocol Greetable {
    var name: String { get }
    func greet()
}

위 예시는 name이라는 읽기 가능한 프로퍼티와, greet()라는 메서드를 요구합니다.
이 프로토콜을 채택한 타입은 해당 요구사항을 반드시 구현해야 합니다.

2. 프로토콜 채택과 구현

struct Person: Greetable {
    var name: String

    func greet() {
        print("안녕하세요, 저는 \(name)입니다.")
    }
}

let user = Person(name: "지민")
user.greet()

Person 구조체는 Greetable 프로토콜을 채택하고, 요구된 속성과 메서드를 구현하였습니다.

3. 클래스에서의 프로토콜 채택

class Dog: Greetable {
    var name: String

    init(name: String) {
        self.name = name
    }

    func greet() {
        print("\(name)가 꼬리를 흔듭니다.")
    }
}

프로토콜은 상속이 아니라 채택(adopt)하는 방식이며, 여러 개의 프로토콜을 동시에 채택할 수도 있습니다.

4. 프로토콜 상속

protocol Named {
    var name: String { get }
}

protocol Describable: Named {
    var description: String { get }
}

DescribableNamed를 상속하므로, 이를 채택한 타입은 두 프로토콜의 모든 요구사항을 충족해야 합니다.

5. 프로토콜 확장 (Protocol Extension)

Swift의 가장 강력한 기능 중 하나는 프로토콜 확장입니다.
이를 통해 프로토콜 자체에 기본 구현을 제공할 수 있습니다.

extension Greetable {
    func greet() {
        print("안녕하세요, \(name)!")
    }
}

해당 프로토콜을 채택한 타입이 직접 greet()를 구현하지 않으면, 위에서 정의한 기본 구현이 사용됩니다.

6. 프로토콜을 활용한 다형성

let people: [Greetable] = [
    Person(name: "은우"),
    Dog(name: "바둑이")
]

for item in people {
    item.greet()
}

PersonDog은 서로 다른 타입이지만, 모두 Greetable을 따르기 때문에 배열에 담아 동일하게 처리할 수 있습니다.

마무리

Swift의 프로토콜은 코드의 재사용성과 유연성을 극대화할 수 있는 중요한 기능입니다.
특히 프로토콜 지향 프로그래밍을 통해 공통 기능을 추상화하고, 구조체나 열거형에서도 객체지향적인 설계를 할 수 있습니다.
extension과 함께 활용하면 클래스 상속보다도 더 강력한 설계가 가능하며, 실무에서도 널리 사용됩니다.