Search
Duplicate

Protocol (프로토콜)

생성일
2023/10/10 09:11
태그
Grammar

Protocol (프로토콜)

 프로토콜이란?

프로토콜이란, 어떤 기능에 적합한 특정 메서드, 프로퍼티 및 기타 요구 사항의 청사진(Blueprint)을 의미한다.
프로토콜은 클래스, 구조체, 열거형에 의해 채택되며, 프로토콜에 정의된 요구사항의 실제 구현을 제공한다.
프로토콜의 요구사항을 모두 충족하는 모든 유형(클래스/구조체/열거형)은 해당 프로토콜에 부합하다고 한다.

 프로토콜은 약속 이다!

밴드로 예를 들자면,
기타, 드럼, 피아노, 보컬 이 필요하다.
그리고 이 밴드에 대한 또다른 요구사항 중 하나는 바로, 연주 가 될 것이다.
이렇게 Band 라는 것에 대한 가이드를 만들었다. 이것이 프로토콜 개념의 전부이다.
이제 프로그래밍적으로 생각해보자면,
Band를 구성할 때 필요한 속성 vocal, guitar, piano, drum은 프로퍼티 로, play라는 연주에 대한 행위는 메서드 로 만들 수 있다.
따라서, 프로토콜이란 것은, 실제 보컬이 누구고, 기타가 누구고, 어떤 곡을 연주할 것이고를 실제로 지정(구현)하는 것이 아니라
Band 라는 것은, ‘이러한 프로퍼티는 꼭 필요하다. 이러한 메서드도 꼭 필요하다.’ 하고 해당 기능에 필요한 요구사항을 선언을 해두는 것이 바로 프로토콜 이다.
그리고 앞으로 내가 어떤 밴드를 만들 때, 미리 정의된 Band 라는 프로토콜을 통해서(채택해서) 만들 경우, 보컬, 기타, 피아노, 드럼 이라는 속성은 필수적으로 필요하며, 연주하다 라는 기능도 필수적이구나 라고 생각할 수 있다.

 프로토콜을 정의하는 방법

protocol Band { var drum: String { get set } var vocal: String { get set } var piano: String { get set } var guitar: String { get set } func play() }
Swift
복사
프로토콜이란 것은

프로퍼티를 선언하여 값을 직접 정의하고, 메서드를 직접 구현하는 것이 아니고, ’이 포르토콜을 따르려면 여러 이러한 것들이 필요하다’ 라는 약속을 정의해 두는 것이다.

 프로토콜을 채택하는 방법

Band 라는 프로토콜을 선언함으로써, Band 라는 일종의 약속을 만들었다. 이제 그것을 클래스, 구조체, 열거형이 채택하여 사용할 수 있게끔 만들 수가 있는데,
만약 ABand라는 새로운 밴드를 만들고 싶다면,
struct ABand {}
Swift
복사
이렇게 ABand 라는 밴드는 밴드를 생성할 때 필요한 요소들을 미리 정의해둔 Band 라는 프로토콜(약속)을 따르고 싶다 라고 할 경우에,
struct ABand: Band {}
Swift
복사
이렇게, 마치 상속을 받을 때처럼, Band 라는 프로토콜을 클래스 이름 옆에 선언해주는 것만으로 해당 프로토콜을 “채택” 하게 되는 것이다.
struct ABand: Band { // Error, Type 'ABand' does not confirm to protocol 'Band' }
Swift
복사
에러가 나는데, Band 라는 프로토콜을 따르기로 했으면서,
보컬, 기타, 피아노, 드럼 이란 프로퍼티가 정의되어 있어야 하고, play 란 메서드도 구현되어 있어야 하는데 왜 약속을 안지켜? 라는 에러이다.
class ABand: Band { var drum: String = "A" var vocal: String = "B" var piano: String = "C" var guitar: String = "D" func play() { print("Lany DNA 듣는 중!") } }
Swift
복사
따라서 위와 같이 Band 프로토콜 안에 선언만 되어 있던 것을
채택한 곳인 ABand 라는 구조체 안에서 실제로 구현 해주는 것이 필요하다.
프로토콜
→ 프로퍼티 / 메서드에 대한 껍데기만 제공하되, 실제 구현은 채택한 곳에서 하는 것이다.

 무조건 필수로 구현??

밴드에서는 베이스가 있을 수도 있고, 없을 수도 있다.
이럴 경우에는 optional 로 선언할 수도 있다.
@objc protocol Band { var drum: String { get set } var vocal: String { get set } var piano: String { get set } var guitar: String { get set } @objc optional var bass: String { get set } func play() }
Swift
복사
bass란 프로퍼티 앞에 @objc optional 을 붙일 경우(프로토콜에도 당연히 @objc 선언),
이때는 bass 라는 프로퍼티에 한해서 required가 아닌 optional 로 바뀐다.
채택해주는 곳에서 꼭 선언해주지 않아도 에러가 나지 않는다.
struct ABand: Band { // Non-class type 'ABand' cannot conform to class protocol 'Band' var drum: String = "A" var vocal: String = "B" var piano: String = "C" var guitar: String = "D" func play() { print("Lany DNA 듣는 중!") } }
Swift
복사
bass 선언은 자유라면서 왜 에러가 날까?
이 에러는 bass란 프로퍼티를 선언하지 않아서 나는 에러가 아니라, Band 라는 포르토콜을 채택하는 것이 ‘구조체’ 이기 때문에 나는 에러이다.
@objc 라는 문법을 붙이는 순간, Objective-C 에서도 사용될 수 있단 것인데, Objective-C 에서 프로토콜은 오로지 ‘클래스 전용’에서만 채택할 수 있다. 따라서 호환성을 위해 @objc 가 붙는 순간 자동으로,
@objc protocol Band: AnyObject { var drum: String { get set } var vocal: String { get set } var piano: String { get set } var guital: String { get set } @objc optional var bass: String { get set } func play() }
Swift
복사
이렇게 클래스 전용일 때 사용하는 AnyObject가 자동으로 채댁된다고 보면 된다.
Optional인 만큼, 채택하는 곳에서 선언 했을지, 안했을지 여부를 알 수가 없기 떄문에
만약 Band 라는 프로토콜 타입을 통해 bass에 접근할 경우, 이때 bass는 String?, 즉, Optional(String) 타입으로 접근해야 한다.

 Reference