Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Archives
Today
Total
관리 메뉴

J

[Swift] Protocol 본문

Swift

[Swift] Protocol

yujaehui 2024. 4. 18. 00:35

1. Protocol이란?

Protocol(프로토콜)은 특정 작업이나 기능에 대한 요구 사항의 집합을 정의하는 데 사용.

프로토콜은 클래스, 구조체, 열거형 등에서 구현할 수 있으며, 객체 지향 프로그래밍의 인터페이스와 유사한 역할.


2. Protocol의 주요 특징

  • 구현 강제화
    • 프로토콜을 채택한 타입은 프로토콜에서 정의한 요구 사항을 반드시 구현해야 함.
  • 유연한 설계
    • 클래스, 구조체, 열거형 모두 프로토콜을 채택할 수 있음.
  • 다중 채택 가능
    • 하나의 타입이 여러 프로토콜을 채택할 수 있음.
  • 타입 독립성
    • 프로토콜을 통해 타입 간 의존성을 줄이고, 코드 재사용성을 높일 수 있음.

3. Protocol의 기본 문법

protocol ProtocolName {
    // 요구 사항 정의
}

4. Protocol의 사용 예제

protocol Greetable {
    func greet()
}

struct Person: Greetable {
    func greet() {
        print("Hello!")
    }
}

let person = Person()
person.greet() // "Hello!"

5. 프로토콜의 구성 요소

메서드 요구 사항

프로토콜은 메서드의 선언만 정의하며, 구현은 없음.

protocol Drawable {
    func draw()
}

struct Circle: Drawable {
    func draw() {
        print("Drawing a circle")
    }
}

프로퍼티 요구 사항

프로토콜은 프로퍼티의 이름, 타입, 읽기/쓰기 권한만 정의.

protocol Shape {
    var area: Double { get }
    var perimeter: Double { get set }
}

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

    var area: Double {
        return width * height
    }

    var perimeter: Double {
        get {
            return 2 * (width + height)
        }
        set {
            width = newValue / 4
            height = newValue / 4
        }
    }
}

초기화 요구 사항

프로토콜은 초기화 메서드도 요구할 수 있음.

protocol Initializable {
    init(value: Int)
}

struct MyStruct: Initializable {
    var value: Int

    init(value: Int) {
        self.value = value
    }
}

let myStruct = MyStruct(value: 10)

6. Protocol과 Extension

Swift에서는 프로토콜 확장을 통해 기본 구현을 제공할 수 있음.

이를 사용하면 프로토콜을 채택하는 타입에서 선택적으로 구현을 제공할 수 있음.

protocol Playable {
    func play()
}

extension Playable {
    func play() {
        print("Default playing...")
    }
}

struct Game: Playable {}

let game = Game()
game.play() // "Default playing..."

7. Protocol Composition (프로토콜 조합)

하나의 타입이 여러 프로토콜을 동시에 준수해야 할 때, & 연산자를 사용하여 프로토콜 조합을 정의할 수 있음.

protocol Flyable {
    func fly()
}

protocol Swimmable {
    func swim()
}

struct Duck: Flyable, Swimmable {
    func fly() {
        print("Flying...")
    }

    func swim() {
        print("Swimming...")
    }
}

func performActions(animal: Flyable & Swimmable) {
    animal.fly()
    animal.swim()
}

let duck = Duck()
performActions(animal: duck)

8. Protocol의 활용

타입 간 통합된 인터페이스 제공

프로토콜은 타입 간 공통된 인터페이스를 제공하여 다형성을 구현 가능.

protocol Animal {
    func sound() -> String
}

struct Dog: Animal {
    func sound() -> String {
        return "Woof"
    }
}

struct Cat: Animal {
    func sound() -> String {
        return "Meow"
    }
}

let animals: [Animal] = [Dog(), Cat()]
for animal in animals {
    print(animal.sound())
}

Delegate 패턴

Delegate 패턴에서 프로토콜은 객체 간 통신을 정의하는 데 사용.

protocol TaskDelegate: AnyObject {
    func taskDidComplete()
}

class Task {
    weak var delegate: TaskDelegate?

    func performTask() {
        print("Task performed")
        delegate?.taskDidComplete()
    }
}

class Manager: TaskDelegate {
    func taskDidComplete() {
        print("Task completed successfully!")
    }
}

let task = Task()
let manager = Manager()

task.delegate = manager
task.performTask()
// "Task performed"
// "Task completed successfully!"

9. Protocol과 Associatedtype

프로토콜에서 연관 타입(associatedtype)을 사용하면 제네릭 프로그래밍과 결합하여 더욱 유연한 코드를 작성할 수 있음.

protocol Container {
    associatedtype Item
    mutating func add(_ item: Item)
    var count: Int { get }
}

struct Box<T>: Container {
    typealias Item = T
    private var items: [T] = []

    mutating func add(_ item: T) {
        items.append(item)
    }

    var count: Int {
        return items.count
    }
}

var box = Box<Int>()
box.add(5)
box.add(10)
print(box.count) // 2

10. Protocol의 실질적 사용 예

Codable

Swift의 Codable 프로토콜은 데이터를 인코딩하거나 디코딩하는 데 사용 됨.

struct User: Codable {
    var name: String
    var age: Int
}

let user = User(name: "Alice", age: 25)
if let data = try? JSONEncoder().encode(user) {
    print(String(data: data, encoding: .utf8)!)
}

if let decoded = try? JSONDecoder().decode(User.self, from: data) {
    print(decoded)
}

Equatable

Equatable은 객체 간의 동등성을 비교하기 위한 프로토콜.

struct Point: Equatable {
    var x: Int
    var y: Int
}

let p1 = Point(x: 1, y: 2)
let p2 = Point(x: 1, y: 2)

print(p1 == p2) // true

Protocol과 Class-Only 제한

프로토콜을 클래스에서만 채택하도록 제한하려면 AnyObject를 사용.

protocol ClassOnlyProtocol: AnyObject {
    func doSomething()
}

class MyClass: ClassOnlyProtocol {
    func doSomething() {
        print("Doing something")
    }
}

11. 결론

Swift의 Protocol은 코드 설계의 유연성을 높이고, 타입 독립적이고 재사용 가능한 코드를 작성하는 데 필수적인 도구.

프로토콜을 사용하면 타입 간의 공통 동작을 정의하고, 확장성과 유지보수성을 높일 수 있음.

특히, 제네릭 및 프로토콜 확장을 함께 활용하면 더욱 강력한 코드를 작성 가능.

'Swift' 카테고리의 다른 글

[Swift] self / Self  (0) 2024.04.18
[Swift] associatedtype  (0) 2024.04.18
[Swift] Generic  (0) 2024.04.15
[Swift] GCD vs Swift Concurrency: 스레드 관리와 성능  (0) 2024.04.15
[Swift] Swift Concurrency  (0) 2024.04.15