[Swift Apple ] Swift 프로토콜(Protocol) 완벽 이해하기

Swift의 가장 중요한 개념 중 하나인 프로토콜(Protocol) 에 대해 쉽게 설명해드리겠습니다. Swift에서 프로토콜은 유연하고 확장성 있는 코드를 작성하기 위한 핵심 도구예요.



[Swift Apple ] Swift 프로토콜(Protocol) 완벽 이해하기
 [Swift Apple ] Swift 프로토콜(Protocol) 완벽 이해하기




📢 Swift 프로토콜(Protocol) 완벽 이해하기

– 코드 약속, 설계의 기준을 만드는 방법!



✅ 프로토콜(Protocol)이란?

프로토콜은 “이렇게 동작해야 해!” 라는 규칙(약속) 을 정해주는 역할을 합니다. 쉽게 말해, 
프로토콜 = 기능 목록만 적어둔 설계서라고 생각하면 돼요.

  • 프로토콜은 구현(내용) 없이,

    “이 메서드와 속성을 가져야 해!” 라고 형태만 정의합니다.

  • 클래스(Class), 구조체(Struct), 열거형(Enum) 모두 프로토콜을 채택(Adopt) 할 수 있어요.




🏗️ 프로토콜 기본 문법

protocol Greetable {
    func greet()
}

이제 이 프로토콜을 따르는(채택하는) 타입은 반드시 greet() 메서드를 구현해야 해요.

struct Person: Greetable {
    func greet() {
        print("안녕하세요!")
    }
}



🎯 왜 프로토콜을 사용할까요?

  • 공통 기능을 표준화하고 싶을 때

  • ✅ 클래스나 구조체가 서로 다른데도, 같은 규칙으로 사용하고 싶을 때

  • 유연하고 확장성 있는 코드를 만들고 싶을 때

  • ✅ 상속 없이도 “공통된 기능”을 구현할 수 있음

  • ✅ 테스트 코드 작성, 의존성 주입(DI) 등에 필수


Swift는 객체지향(OOP)보다 프로토콜 지향 프로그래밍(POP) 을 강조합니다!

그만큼 프로토콜은 Swift 개발의 핵심이에요.




🧪 프로토콜 예제


예제 1: 기본 프로토콜 채택

protocol Drivable {
    func drive()
}

class Car: Drivable {
    func drive() {
        print("자동차가 달립니다!")
    }
}




예제 2: 속성과 메서드를 포함한 프로토콜

protocol Animal {
    var name: String { get }
    func sound()
}

struct Dog: Animal {
    var name: String = "강아지"

    func sound() {
        print("멍멍!")
    }
}

  • 프로퍼티도 읽기 전용(get), 읽기/쓰기(get set) 구분 가능





⚡ 프로토콜의 주요 기능

기능

설명

다중 프로토콜 채택

여러 개의 프로토콜을 동시에 채택 가능

프로토콜 상속

프로토콜도 다른 프로토콜을 상속 가능

프로토콜 합성

타입 제한 시 여러 프로토콜을 & 로 결합

프로토콜 기본 구현

Extension으로 기본 기능 제공 가능

Associated Type

제네릭처럼 타입 유연성 제공




✅ 다중 프로토콜 채택

protocol Flyable { func fly() }
protocol Swimmable { func swim() }

struct Duck: Flyable, Swimmable {
    func fly() { print("오리가 날아요!") }
    func swim() { print("오리가 헤엄쳐요!") }
}





✅ 프로토콜 + Extension (기본 구현 제공)

protocol Printable {
    func printMessage()
}

extension Printable {
    func printMessage() {
        print("기본 메시지 출력")
    }
}

struct Report: Printable {}
let report = Report()
report.printMessage()  // 기본 메시지 출력

  • 이렇게 하면 선택적 구현도 가능!



프로토콜 + Extension (기본 구현 제공)
프로토콜 + Extension (기본 구현 제공)




💡 프로토콜과 클래스/구조체의 차이점

구분

프로토콜

클래스/구조체

역할

“무엇을 해야 하는지” 규칙 정의

실제 데이터와 기능 구현

다중 채택

✅ 가능

클래스는 단일 상속

상속

프로토콜도 상속 가능

클래스만 상속 가능

활용 목적

유연성, 표준화

데이터 및 로직 처리



✏️ 실습 아이디어

  1. Movable 프로토콜 만들고 자동차, 자전거에 적용하기

  2. Drawable 프로토콜을 채택한 도형(원, 사각형) 그리기 기능 구현

  3. 프로토콜 + Extension으로 기본 동작 제공 후 일부만 커스터마이징

  4. 프로토콜을 활용한 Delegate 패턴 직접 구현해보기



✅ 1. Movable 프로토콜 만들고 자동차, 자전거에 적용하기

protocol Movable {
    func move()
}

struct Car: Movable {
    func move() {
        print("🚗 자동차가 도로를 달립니다.")
    }
}

struct Bicycle: Movable {
    func move() {
        print("🚲 자전거가 페달을 밟으며 움직입니다.")
    }
}

// 사용 예시
let movableList: [Movable] = [Car(), Bicycle()]
movableList.forEach { $0.move() }


Movable 프로토콜 만들고 자동차, 자전거에 적용하기
Movable 프로토콜 만들고 자동차, 자전거에 적용하기





✅ 2. Drawable 프로토콜을 채택한 도형(원, 사각형) 그리기 기능 구현

protocol Drawable {
    func draw()
}

struct Circle: Drawable {
    var radius: Double

    func draw() {
        print("⚪️ 반지름 \(radius)cm 원을 그립니다.")
    }
}

struct Rectangle: Drawable {
    var width: Double
    var height: Double

    func draw() {
        print("▭ 가로 \(width)cm, 세로 \(height)cm 사각형을 그립니다.")
    }
}

// 사용 예시
let shapes: [Drawable] = [Circle(radius: 5), Rectangle(width: 10, height: 4)]
shapes.forEach { $0.draw() }


Drawable 프로토콜을 채택한 도형(원, 사각형) 그리기 기능 구현
Drawable 프로토콜을 채택한 도형(원, 사각형) 그리기 기능 구현





✅ 3. 프로토콜 + Extension으로 기본 동작 제공 후 일부만 커스터마이징

protocol Greeter {
    func greet()
}

extension Greeter {
    func greet() {
        print("안녕하세요! 기본 인사입니다. 👋")
    }
}

struct DefaultPerson: Greeter {}  // 기본 인사 사용

struct CustomPerson: Greeter {
    func greet() {
        print("안녕하세요! 저는 커스텀 인사를 합니다. 😊")
    }
}

// 사용 예시
let a = DefaultPerson()
let b = CustomPerson()

a.greet()  // 기본 인사 출력
b.greet()  // 커스텀 인사 출력
✅ 확장(Extension)으로 기본 기능을 주고, 필요한 타입만 재정의(overriding)할 수 있어요!


프로토콜 + Extension으로 기본 동작 제공 후 일부만 커스터마이징
프로토콜 + Extension으로 기본 동작 제공 후 일부만 커스터마이징




✅ 4. 프로토콜을 활용한 Delegate 패턴 직접 구현해보기

protocol ButtonDelegate: AnyObject {
    func didTapButton()
}

class CustomButton {
    weak var delegate: ButtonDelegate?

    func tap() {
        print("🔘 버튼이 눌렸습니다.")
        delegate?.didTapButton()
    }
}

class ViewController: ButtonDelegate {
    func didTapButton() {
        print("✅ 버튼 클릭 이벤트 처리 완료!")
    }
}

// 사용 예시
let button = CustomButton()
let controller = ViewController()
button.delegate = controller
button.tap()
✅ 프로토콜로 역할을 정의하고, delegate로 역방향 이벤트 전달을 처리하는 대표 예입니다.


프로토콜을 활용한 Delegate 패턴 직접 구현해보기
프로토콜을 활용한 Delegate 패턴 직접 구현해보기




🧠 요약

실습 주제

학습 포인트

Movable 프로토콜 적용

기본 추상화와 다형성

Drawable 도형 구현

데이터 기반 출력 로직

프로토콜 + 기본 구현 확장

선택적 커스터마이징

Delegate 패턴 구현

이벤트 전달 & 약한 참조 관리




🎯 마무리하며


Swift 프로토콜 핵심 요약!

  • 프로토콜은 규칙(약속) 을 정의하는 설계도

  • 클래스, 구조체, enum 모두 프로토콜을 채택 가능

  • 상속보다 유연하게 공통 기능을 제공할 수 있음

  • Extension과 함께 사용하면 더욱 강력

  • Swift의 프로토콜 지향 프로그래밍(POP) 을 실천하는 열쇠!

댓글 쓰기