서버 사이드에서 Java 또는 Kotlin으로 개발을 해오셨다면, interface라는 개념은 너무나 익숙할 겁니다. Swift에도 이와 유사한 개념으로 protocol이 존재합니다. 하지만 단순히 “Swift에서 interface는 protocol이다”라고만 이해하면 놓치는 부분이 많습니다.
Swift의 protocol은 interface + default method + 제네릭 + 확장성이 한데 어우러진, 꽤 강력한 개념입니다. 이번 글에서는 Java/Kotlin 인터페이스와 비교하면서 Swift의 프로토콜을 정리해보겠습니다.
🧩 1. 기본 개념: protocol ≒ interface
Swift의 protocol은 특정 타입이 가져야 할 **속성(Property)**와 **메서드(Method)**의 청사진(Contract)을 정의합니다. 기본적인 역할은 Java/Kotlin의 interface와 거의 동일합니다.
protocol Vehicle {
var speed: Double { get set } // 프로퍼티 요구사항
func move() // 메서드 요구사항
}
struct Car: Vehicle {
var speed: Double = 0.0
func move() {
print("Car is moving at \(speed) km/h")
}
}
👉 Java/Kotlin에서 interface를 implements 하는 것과 거의 같습니다.
2. Java/Kotlin interface vs Swift protocol 요약 비교
| 항목 | Java/Kotlin interface | Swift protocol |
|---|---|---|
| 프로퍼티 정의 | 메서드만 가능 (Kotlin은 val/var 가능) | 저장/계산 프로퍼티 모두 정의 가능 (get/set) |
| 구조체/열거형 적용 | 클래스만 구현 가능 | 클래스, 구조체(struct), 열거형(enum) 모두 채택 가능 |
| 확장(기본 구현) | default method (Java8+) | protocol extension 으로 기본 구현 가능 |
| 다중 채택 | 가능 | 가능 |
| 제네릭 | 제네릭 타입으로 선언 | associatedtype으로 제네릭 추상화 지원 |
| Optional 요구사항 | 없음 (모든 메서드 구현 필요) | @objc optional 지원 (단, class 한정) |
| 런타임 타입 캐스팅 | instanceof 등 | is, as?, as! 사용 |
3. 클래스뿐 아니라 struct, enum도 채택 가능
Java/Kotlin 인터페이스는 클래스만 구현할 수 있지만, Swift에서는 **값 타입(Value Type)**인 구조체(struct), 열거형(enum)도 프로토콜을 채택할 수 있습니다.
enum Direction: Moveable {
case north, south, east, west
func move() {
print("Moving \(self)")
}
}
protocol Moveable {
func move()
}
👉 Swift는 값 타입이 언어의 핵심 개념이라, 이런 패턴이 매우 흔합니다.
4. protocol extension으로 기본 구현 제공
Java 8 이후 interface에 default method를 정의할 수 있듯이, Swift도 protocol extension으로 기본 구현을 제공합니다.
하지만 Swift는 훨씬 강력합니다 — 프로토콜을 채택한 모든 타입에 공통 기능을 추가할 수 있죠.
protocol Logger {
func log(_ message: String)
}
extension Logger {
func log(_ message: String) {
print("[LOG] \(message)")
}
}
struct FileLogger: Logger {}
struct ConsoleLogger: Logger {}
FileLogger().log("Hello") // 기본 구현 사용
👉 Kotlin의 interface default 구현과 비슷하지만, Swift에서는 extension으로 공통 동작을 부여하는 경우가 많습니다.
5. associatedtype으로 제네릭 추상화
Java/Kotlin에서는 인터페이스에 제네릭 타입을 붙여 추상화합니다.
interface Repository<T> {
fun save(entity: T)
}
Swift에서는 associatedtype을 사용합니다.
protocol Repository {
associatedtype Entity
func save(_ entity: Entity)
}
struct UserRepository: Repository {
func save(_ entity: User) {
// 구현
}
}
👉 associatedtype은 Swift의 제네릭 추상화 방식으로, Swift의 Protocol with Associated Types(PAT)는 굉장히 자주 등장하는 개념입니다.
6. @objc optional — 선택적 요구사항
Swift 프로토콜은 모든 요구사항이 기본적으로 필수입니다.
선택적 메서드를 정의하려면 Objective-C 호환 프로토콜(@objc)을 사용해야 합니다.
@objc protocol Delegate {
@objc optional func didFinish()
}
하지만 네이티브 Swift에서는 보통 optional 대신 extension으로 기본 구현을 제공하는 방식이 일반적입니다.
7. 실무 예시
✅ Delegate 패턴
UIKit에서 흔히 쓰는 방식입니다.
protocol TableViewDelegate {
func didSelectRow(at index: Int)
}
✅ Repository / UseCase 추상화
서버 API 인터페이스 정의 시
protocol UserRepository {
func fetchUser(id: String) async throws -> User
}
✅ SwiftUI ViewModel 추상화
protocol ViewModel: ObservableObject {
associatedtype State
var state: State { get }
}
✨ 마무리: Swift는 “상속”보다 “프로토콜 조합”을 선호한다
Swift는 전통적인 클래스 상속보다는, 여러 개의 protocol을 조합해서 기능을 구성하는 방식을 선호합니다.
서버 개발자가 인터페이스를 “클래스 계약” 정도로만 사용했다면, Swift에선 프로토콜이 추상화의 주력 수단이 됩니다.
📌 한 줄 요약
Swift의 protocol = interface + default method + struct/enum 지원 + 제네릭 추상화 + 확장 기능
단순한 인터페이스 개념 이상으로, 언어 전체를 관통하는 핵심 요소입니다.