TIL: 프로토콜(Protocols)의 개념

Royce·2025년 3월 24일

Swift 문법

목록 보기
46/63

프로토콜(Protocols)

  • 프로토콜(Protocol)은 영어로 규약(Agreement) / 협약(Convention) 을 의미한다
  • 프로토콜은 특정 능력이나 기능을 정의하는 일종의 자격증 이라고 볼 수 있다
  • 프로토콜을 통해 구조체, 클래스, 열거형 등이 특정 기능을 반드시 구현하도록 강제할 수 있다
  • 프로토콜은 클래스 상속의 단점을 보완하는 중요한 개념 이다

프로토콜의 정의 및 구현

정의

protocol Instrument {  // 요구사항을 정의하는 프로토콜 (자격증의 필수 능력)
    func play()  // 악기를 연주하는 기능 (구현은 하지 않음)
}
  • Instrument 프로토콜은 play() 라는 메서드를 요구한다
  • 구체적인 구현은 프로토콜을 채택한 타입에서 수행하게 된다

프로토콜의 채택 및 구현

// 구조체에서 프로토콜 채택
struct Drum: Instrument {  
    func play() {
        print("드럼을 연주합니다.")
    }
}

// 클래스에서 프로토콜 채택
class Violin: Instrument {    
    func play() {
        print("바이올린을 연주합니다.")
    }
}
  • DrumViolinInstrument 프로토콜을 채택하여 play() 기능을 구현한다
  • 프로토콜을 채택하면, 정의된 요구사항을 반드시 구현해야 한다

클래스 상속의 단점과 문제점 예시

class Animal {
    var isFemale = true
    
    func reproduce() {
        if isFemale {
            print("동물이 새끼를 낳습니다.")
        }
    }
    
    func walk() {
        print("동물이 걷습니다.")
    }
}

class Dog: Animal {
    func bark() {
        print("개가 짖습니다.")
    }
}

class Fish: Animal {
    func swim() {
        print("물고기가 헤엄칩니다.")
    }
}

class Robot: Animal {
    override func walk() {
        print("로봇이 기계적으로 걷습니다.")
    }
}
  • Fishwalk() 메서드를 상속받지만, 물고기는 걷지 않으므로 문제가 발생한다
  • Robot 은 동물이 아님에도 Animal 클래스를 상속받아야 하므로 설계가 비효율적이다
  • 불필요한 메서드와 속성을 강제로 상속받게 되는 문제 가 발생한다

문제점 해결을 위한 프로토콜 사용

protocol Movable {
    func move()  
}
  • Movable 프로토콜은 이동 능력을 정의한다
  • 클래스, 구조체, 열거형 등에서 구현할 수 있다

클래스에서 프로토콜 채택

class Dog1: Animal, Movable {  
    func move() {
        print("개가 뛰어다닙니다.")
    }
}

class Fish1: Animal, Movable {  
    func move() {
        print("물고기가 헤엄칩니다.")
    }
}
  • Dog1Fish1 클래스는 Movable 프로토콜을 채택하여 move() 기능을 구현한다
  • 기존의 Animal 클래스를 상속받으면서도 새로운 기능을 추가한다

구조체에서 프로토콜 채택

struct Car: Movable {  
    func move() {
        print("자동차가 도로를 달립니다.")
    }
}
  • Car 는 구조체로 정의되었지만, Movable 프로토콜을 채택하여 move() 기능을 구현할 수 있다
  • 기존의 클래스 상속 방식에서는 불가능했던 방식이다

프로토콜을 사용하는 함수 정의

struct MovementDemo {
    func demonstrateMovement(movingObject: Movable) {
        movingObject.move()
    }
}
  • demonstrateMovement() 함수는 Movable 프로토콜을 채택한 타입만 받을 수 있다
  • 이 방식으로 특정 기능이 필요한 객체들만을 다룰 수 있게 된다

사용 예제

let myDog = Dog1()
let myFish = Fish1()
let myCar = Car()

myDog.reproduce()    // 출력: 동물이 새끼를 낳습니다.
myDog.move()         // 출력: 개가 뛰어다닙니다.

myFish.reproduce()    // 출력: 동물이 새끼를 낳습니다.
myFish.move()         // 출력: 물고기가 헤엄칩니다.

myCar.move()          // 출력: 자동차가 도로를 달립니다.

let demo = MovementDemo()
demo.demonstrateMovement(movingObject: myDog)   // 출력: 개가 뛰어다닙니다.
demo.demonstrateMovement(movingObject: myFish)  // 출력: 물고기가 헤엄칩니다.
demo.demonstrateMovement(movingObject: myCar)   // 출력: 자동차가 도로를 달립니다.

프로토콜 사용의 장점

  • 다중 상속의 효과 제공 (Swift는 클래스의 다중 상속을 지원하지 않음)
  • 불필요한 속성과 메서드의 상속 문제 해결
  • 클래스(참조 타입) 뿐 아니라, 구조체(값 타입), 열거형도 프로토콜을 채택할 수 있음
  • 타입 안전성을 강화하여 특정 기능이 필요한 타입만을 사용할 수 있게 함

요약

  • 프로토콜은 클래스 상속의 문제를 해결하기 위해 사용되는 기능이다
  • 프로토콜은 클래스뿐 아니라 구조체, 열거형에도 적용할 수 있다
  • 프로토콜은 특정 기능을 강제하여 타입 안전성을 보장한다
  • 클래스 상속으로 인해 발생할 수 있는 비합리적인 상속 문제를 방지할 수 있다
profile
iOS 개발자 지망생

0개의 댓글