본문 바로가기

iOS/Swift

Swift) Protocol 이해하기 (1/6) - Protocol이 도대체 뭔가요?

 



안녕하세요!! 소들입니다 🐮🐮
이번에 이니셜라이저가 끝났으니..!!! 프로토콜에 대해 포스팅을 해보려고 해요 :)
프로토콜만 냅다 다 포스팅 하기보다 중간 중간에
Rxswift나 Design Pattern, Architecture(Ribs / Clean Architecture)도
된다면 섞을 예정입니당!!
다시 블로그 되살리기 운동인 소들이니께 :ㅁ:

이번엔 가볍게 프로토콜이 무엇인지,
스위프트에선 어떻게 사용해야 하는지에 대해 정말 가볍게!! 공부해볼 예정입니다!!
모든 포스팅은 편의 말투로 합니다~!!



1. Protocol이란?


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

위 정의는 말이죠
처음보면 무슨 말인지 1도 모른단 말이죠
따라서 나는 애플의 정의는 일단 가볍게 무시하고
좀 더 쉬운 방법으로 접근해보겠음!
(나중에 이해하고 나서 위 정의를 다시보면, 모두 완벽히 이해할 수 있기에!!)

여러분 저는 완전 신입 시절에 사수분께서
소들씨~ 프로토콜이 뭐라고 생각하세요~~?
라고 했을 때

약속이요!! 🤙🏻

라고 대답했었음!
Protocol의 정의를 찾아보면 뭐 협약, 통신 규약 등이 있지만
좀 더 쉽게 우린 약속이라고 생각을 해보는 것임!!

자, 프로토콜을 이해하기 위해서 우린 밴드라는 것을 생각해볼 것임
내가 음악을 개짱 좋아해서 밴드라는 것을 만들고 싶음!!!
그렇다면, 밴드를 만들기 위해선 어떤 요소들이 필요할까?!!


물론 뭐 베이스도 있을 수 있고, 악기야 추가로 좀 더 많을 수 있겠지만
보통의 밴드라고 함은 위와 같이 기타, 드럼, 피아노, 보컬이 필수적으로 있어야 되잖음??



근데 밴드라는 것은 저 사람들이 모여서 수다만 떨고 끝나는 게 아니라,
어떠한 곡을 연주한다는 것이 목표잖음!?!??!
그렇다면 밴드에 대한 또다른 요구사항 중 하나는 바로, 연주가 될 것임!



그래그래ㅋ 적어도 밴드를 만들기 위해선 위와 같은 약속은 지켜줘야지 ㅋ
하고 우리가 위처럼 어떤 Band라는 것에 대한 가이드를 만들어버렸음ㅎㅎ
이것이 사실 프로토콜의 전부임ㅎㅎ

자, 이젠 위 내용들을 좀 더 프로그래밍적으로 생각해보는 것임!
Band를 구성할 때 필요한 속성 vocal, guitar, piano, drum 프로퍼티로,
play라는 연주에 대한 행위는 메서드로 만들 수 있잖음!?!

따라서, 프로토콜이란 것은,
실제 보컬이 누구고, 기타가 누구고, 어떤 곡을 연주 할 것이고를
실제로 지정(구현)하는 것이 아니라
Band라는 것은,
이런 이런 프로퍼티는 꼭 필요해요!
이러이러한 메서드도 꼭 필요해요!
하고 해당 기능에 필요한 요구 사항을 선언해두는 것 바로 Protocol 이란 것임!!

앞으로 내가 어떤 밴드를 만들 때,
마치 [밴드를 만들 때 필요한 101가지 방법]과도 같은
미리 정의된 Band라는 프로토콜을 통해서(채택해서) 만들 경우,
보컬, 기타, 피아노, 드럼이라는 속성은 필수적으로 필요하며,
연주하다 라는 기능도 필수적이겠구나!!

를 생각해본다면,
여러분은 프로토콜을 모두 이해한 것입니다 ㅋ
이해가 안 가셔도 괜찮음 설명을 개떡같이 해서..ㅎㅎ;;
코드를 보면서 차근차근 이해해 봅시당 :)


1-1. 프로토콜을 정의하는 방법

 

protocol Band {
    var drum: String   { get set }
    var vocal: String  { get set }
    var piano: String  { get set }
    var guitar: String { get set }

    func play()
}



우리가 위에서 Band라는 것으로 만든 프로토콜(약속)은 위처럼 정의할 수 있음!!
프로토콜이란 것은 앞서 누누(간다!)히 말했듯이
프로퍼티를 선언하여 값을 직접 정의하고, 메서드를 직접 구현 하는 것이 아님!!
이 프로토콜을 따르려면 이러 이러한 것들이 필요하다!! 라는 약속을 정의해두는 것임

밴드라는 프로토콜을 따르기 위해선
드럼 보컬 피아노 기타 프로퍼티가 반드시 정의되어 있어야 하고,
play란 메서드가 반드시 정의되어 있어야 해요!!
라는 것을 선언해두는 것이 바로 Band란 프로토콜임!!

프로퍼티는 let으로 선언하면 안 되나요?
{ get set }이 뭔가요? get만 두면 안되나요?
메서드는 어떤 식으로 선언해 두는 건가요!?

같은 의문은, 바로 다음 포스팅에서 다룰 것이니 넘어가셈!!

지금은 그냥 위처럼
프로토콜은 어떤 기능을 수행할 때 필요한
어떠한 프로퍼티, 메서드에 대해 구현하는 것이 아닌, "선언"만 해두는 것이구나!!만
이해하고 가자 :)


1-2. 프로토콜을 채택하는 방법


자 우리는 Band라는 프로토콜을 선언함으로써,
Band라는 일종의 약속을 만들어둔 것임

그럼 이제 그것을 클래스, 구조체, 열거형이 채택하여 사용할 수 있게끔 만들 수 있는데,
자, 우리가 만약 ABand라는 새로운 밴드를 만들 것임!!

struct ABand {}



위처럼!!
근데, 이 ABand라는 밴드는
밴드를 생성할 때 필요한 요소들을 미리 정의해둔 Band라는 프로토콜(약속)을 따르고 싶어!!
라고 할 경우에,

struct ABand: Band {}



위처럼, 마치 상속을 받을 때처럼,
Band라는 프로토콜을 클래스 이름 옆에 선언해주는 것만으로 해당 프로토콜을 "채택"하게 되는 것임!!

그러면 이제, ABand라는 구조체에서 에러가 뜸



야 너! Band라는 프로토콜 따른다매!!
너어 Band라는 프로토콜을 따르려면
보컬, 기타, 피아노, 드럼 이란 프로퍼티가 정의되어 있어야 하구!!
play란 메서드도 구현되어 있어야 한다구!!
왜 약속 안지켜!!

하고 에러가 뜨는 것임!

 

class ABand: Band {
    var drum:   String = "A"
    var vocal:  String = "B"
    var piano:  String = "C"
    var guitar: String = "D"
    
    func play() {
        print("day6 예뻤어 연주 중!")
    }
}
 

 

 

따라서 위와 같이 Band 프로토콜 안에 선언만 되어 있던 녀석들을
채택한 곳인 ABand라는 구조체 안에서 실제로 구현 해주는 것이 필요함!!
이렇게 하면 이제 에러가 사라짐!

이것이 바로 프로토콜임!!
프로퍼티/메서드에 대한 껍데기만 제공하되, 실제 구현은 채택한 곳에서 하는 것임!!

어느 정도 이해가 갔을 거라 믿구,
그럼 처음에 봤던 애플 정의를 다시 본다면

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

이젠ㅇ ㅣ해 할 수 있기를..!!! :)



2. 필수라기엔.. 베이스는 구하기 힘든데...


위에서 아무렇지 않게 프로토콜 안에 선언되어 있는 프로퍼티 / 메서드는 모드
required 즉, 필수적인 것임
따라서 채택하는 곳에서 구현하지 않을 경우 에러가 남!!

근데,, 베이스 같이 구하기 힘든 멤버도 프로토콜 안에 선언해두고 싶은데,,
이녀석은 밴드마다 있을수도,, 없을 수도 있거든요,,
희귀한 녀석이거등요,,

할 경우에,
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()
}



bass란 프로퍼티 앞에 @objc optional을 붙일 경우(프로토콜에도 당연히 @objc 선언),
이땐 bass라는 프로퍼티에 한해서 required가 아닌 optional로 바뀜!
채택해주는 곳에서 꼭 선언해주지 않아도 에러가 안 남



뭐죠 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 guitar: String { get set }
    @objc optional var bass: String { get set }

    func play()
}



이렇게 클래스 전용일 때 사용하는 AnyObject가 자동으로 채택된다고 보면 됨!!!
Optional인 만큼, 채택하는 곳에서 선언 했을지 안 했을지 여부를 알 수 없기 때문에,

 

 



만약 Band라는 프로토콜 타입을 통해 bass에 접근할 경우,
이때 bass는 String? 즉, Optional(String) 타입으로 접근해야 함!!










.
.
.
이번엔 프로토콜의 정말 기초.. 정말 기초.. 기초 중에 기초에 대해 알아봤.. 습니다..
초반에 프로토콜이 이해하기 꽤 어려워서ㅠㅠ.. 쉽게 이해 시키고 싶었는데ㅜㅜ
요즘 머리가 굳었는지 쉽게 설명이 잘 안되네여..ㅎㅎㅎㅋ...
이번에 맛만보기를 했다면
다음 포스팅에서부턴 프로토콜에 대해 좀 더 깊게 들어가서 공부해보도록 하게씁니당..!!
잘못된 내용 및 오타피드백 댓글로 남겨주세요!!!





Calendar
«   2024/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
최근 댓글
Visits
Today
Yesterday