🔥 클래스 전용 프로토콜

561자
8분

Swift 프로그래밍 언어에서 프로토콜은 특정 기능을 수행하기 위해 필요한 메서드, 속성 등을 정의하는 청사진과 같은 역할을 합니다. 프로토콜은 클래스, 구조체, 열거형 등 다양한 타입에서 채택하여 사용할 수 있습니다. 그러나 경우에 따라서는 프로토콜을 특정 타입, 즉 클래스에서만 채택하고 싶을 때가 있습니다. 이럴 때 사용할 수 있는 것이 바로 클래스 전용 프로토콜(Class-Only Protocols)입니다.

클래스 전용 프로토콜 정의하기

클래스 전용 프로토콜을 정의하려면 프로토콜의 상속 목록에 AnyObject 프로토콜을 추가해야 합니다. AnyObject 프로토콜은 클래스 타입만 채택할 수 있는 특별한 프로토콜입니다. 다음은 클래스 전용 프로토콜을 정의하는 구문입니다.

protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
    // 클래스 전용 프로토콜 정의
}
swift

위 코드에서 SomeClassOnlyProtocolAnyObject 프로토콜과 SomeInheritedProtocol을 상속받고 있습니다. 이렇게 정의된 프로토콜은 클래스 타입에서만 채택할 수 있게 됩니다.

클래스 전용 프로토콜 채택하기

클래스에서 클래스 전용 프로토콜을 채택하는 방법은 일반적인 프로토콜 채택과 동일합니다. 클래스 이름 뒤에 콜론(:)을 붙이고 채택할 프로토콜 이름을 작성하면 됩니다. 다음은 클래스에서 클래스 전용 프로토콜을 채택하는 예시입니다.

class SomeClass: SomeClassOnlyProtocol {
    // 클래스 정의
}
swift

위 코드에서 SomeClassSomeClassOnlyProtocol을 채택하고 있습니다. 클래스 전용 프로토콜을 채택한 클래스는 해당 프로토콜에서 요구하는 메서드, 속성 등을 구현해야 합니다.

하지만 구조체나 열거형에서 클래스 전용 프로토콜을 채택하려고 하면 컴파일 오류가 발생합니다. 아래는 구조체에서 클래스 전용 프로토콜을 채택하려고 할 때 발생하는 오류의 예시입니다.

struct SomeStruct: SomeClassOnlyProtocol {
    // 컴파일 오류 발생!
}
swift

오류 메시지를 보면 "SomeStruct does not conform to protocol SomeClassOnlyProtocol"이라고 나옵니다. 이는 구조체에서 클래스 전용 프로토콜을 채택할 수 없다는 것을 나타냅니다.

클래스 전용 프로토콜의 활용

클래스 전용 프로토콜은 여러 가지 상황에서 유용하게 활용될 수 있습니다. 대표적인 활용 예시로는 다음과 같은 경우가 있습니다.

  1. 참조 타입 전용 기능 정의
    클래스는 참조 타입(Reference Type)으로, 힙(Heap) 메모리에 저장되고 참조를 통해 접근됩니다. 참조와 관련된 기능을 정의할 때 클래스 전용 프로토콜을 사용할 수 있습니다. 예를 들어, Identifiable 프로토콜을 클래스 전용으로 정의하여 객체 식별자를 관리하는 기능을 클래스에서만 제공할 수 있습니다.
  2. 상속 관련 기능 정의
    클래스는 상속을 지원하는 유일한 타입입니다. 상속과 관련된 기능을 정의할 때 클래스 전용 프로토콜을 사용할 수 있습니다. 예를 들어, Inheritable 프로토콜을 클래스 전용으로 정의하여 상속 가능한 클래스에서만 채택하도록 제한할 수 있습니다.
  3. 클래스 간 공통 인터페이스 정의
    여러 클래스에서 공통으로 사용되는 기능을 정의할 때 클래스 전용 프로토콜을 활용할 수 있습니다. 이를 통해 클래스 간의 인터페이스를 통일하고, 코드의 재사용성과 유지보수성을 높일 수 있습니다.

다음은 클래스 전용 프로토콜을 활용한 예시 코드입니다.

protocol Identifiable: AnyObject {
    var id: String { get }
}
 
class Person: Identifiable {
    let id: String
 
    init(id: String) {
        self.id = id
    }
}
 
class Student: Person {
    var studentID: String
 
    init(id: String, studentID: String) {
        self.studentID = studentID
        super.init(id: id)
    }
}
 
let person = Person(id: "1")
let student = Student(id: "2", studentID: "S001")
 
print(person.id) // "1"
print(student.id) // "2"
print(student.studentID) // "S001"
swift

위 코드에서 Identifiable 프로토콜은 클래스 전용으로 정의되었으며, id 속성을 요구합니다. Person 클래스와 Student 클래스는 모두 Identifiable 프로토콜을 채택하여 id 속성을 구현하고 있습니다.

Student 클래스는 Person 클래스를 상속받아 studentID 속성을 추가로 가지고 있습니다. 이처럼 클래스 전용 프로토콜을 활용하면 클래스 간의 계층 구조를 명확히 하고, 공통된 기능을 추상화할 수 있습니다.

정리하자면, 클래스 전용 프로토콜은 프로토콜의 채택을 클래스로 제한하는 기능을 제공합니다. 프로토콜 상속 목록에 AnyObject 프로토콜을 추가하여 클래스 전용 프로토콜을 정의할 수 있습니다. 클래스 전용 프로토콜을 활용하면 참조 타입 전용 기능 정의, 상속 관련 기능 정의, 클래스 간 공통 인터페이스 정의 등의 상황에서 코드의 명확성과 안정성을 높일 수 있습니다.

클래스 전용 프로토콜은 프로토콜의 채택 범위를 제한하여 의도를 명확히 전달할 수 있는 강력한 도구입니다. 프로토콜을 설계할 때 클래스 전용으로 제한해야 하는지 고려하고, 적절히 활용한다면 코드의 가독성과 유지보수성을 향상시킬 수 있을 것입니다.