오늘의 Tip

1. CocoaPods이란?

2. CocoaPods 설치

3. Pod 설치

4. Pod 찾아보기


안녕하세요 야곰입니다.

오늘은 코코아팟에 대한 이야기를 해보려고 합니다.


# CocoaPods이란?


iOS 및 macOS, tvOS 등 애플 플랫폼에서 개발을 할 때, 외부 라이브러리를 관리하기 쉽도록 도와주는 의존성 관리 도구들이 있습니다. CocoaPods는 애플 플랫폼을 위한 의존성 관리도구의 일종입니다. 애플 플랫폼에서 사용할 수 있는 의존성 관리 도구의 대표적인 예로는 [CocoaPods], [Carthage], [Swift Package Manager] 등이 있습니다.


더 자세한 설명은 이미 써두신 분들이 많아 링크를 드립니다.


CocoaPods에 대해 설명하고 있는 문서 링크


# CocoaPods 설치 및 Pod 설치


가장 빠른 것은 아래 영상을 보고 따라하는거예요.






영상을 보기 싫은 분들을 위해 텍스트 설명


# CocoaPods 설치


쉽습니다. 별로 할 게 없어요. 맥을 사용하고 있다면 터미널을 열어서 명령어 한 줄만 입력하면 됩니다.

아무 반응이 없더라도 기다리세요. 설치가 되고 있습니다. 처음에 꽤 오래 걸립니다. 그러니 차분히 기다리세요.


sudo gem install cocoapods


# Pod 설치


CocoaPods를 통해 가져올 수 있는 라이브러리를 Pod이라고 할 수 있습니다. 


먼저 현재 내가 진행하고 있는 프로젝트 폴더에 Podfile 이라는 이름의 파일을 생성합니다. 이 Podfile을 통해 CocoaPods이 라이브러리 의존성을 파악하게 됩니다.


원하는 라이브러리는 cocoapods.org에서 검색해 보는 것이 가장 쉽고 빠릅니다. 검색하여 찾은 라이브러리의 pod spec을 복사하여 Podfile에 붙여넣어줍니다.


파일을 저장한 후 터미널에서 (프로젝트 경로에서)아래 명령어를 입력해줍니다.


pod install


그러면 기존 프로젝트 파일 외에 워크스페이스 파일이 별도로 생성되는데, 이제 그 워크스페이스 파일로 작업을 진행하면 됩니다.



# Pod 설치


그러면 도대체 쓸만한 Pod은 어디서 찾을까요?


일단 CocoaPods를 통해 제공되는 라이브러리는 모두 cocoapods.org에서 찾아볼 수 있는데요, 

UI를 미리 보고 싶다면 cocoacontrols.com도 추천합니다.

각종 UI/UX 라이브러리들이 모여있고, 미리보기, 라이센스 확인도 모두 가능합니다.




Download Source를 선택해 들어가면 대부분 github 페이지로 이동합니다.

github 페이지의 README 파일에 보면 대부분 cocoapods을 통해 설치할 수 있는 pod 정보도 설명이 되어있습니다.




그런데 더 놀라운 곳이 있습니다! 양이 너무 많아 무얼 써보아야 할지 모르지만~ 

[Awesome iOS]에 많은 라이브러리 목록이 있습니다. 

UI만 또 모아놓은 곳도 있구요~ [Awesome iOS UI]


이제 손쉽게 라이브러리를 검색하고 의존성 관리도 손쉽게 해보세요!








by yagom

facebook : https://facebook.com/yagomsoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


저작자 표시 비영리 변경 금지
신고
Posted by yagom


집필도서 출간 안내

안녕하세요 야곰입니다 :)


벌써 책이 나온지는 꽤 되었고 부끄럽지만 제가 쓴 책을 소개합니다.


스위프트 프로그래밍이라는 책이구요, 한빛미디어에서 나왔습니다.




[링크]


스위프트 프로그래밍 언어 문법서이며, 여러가지 팁과 노트가 수록되어 있습니다. 

스위프트를 활용한 프로그래밍 기법이라던지 최근 이야기되고 있는 프로그래밍 패러다임에 대한 이야기들도 있습니다.


많은 참고가 되면 좋겠습니다.


링크


by yagom

facebook : http://fb.yagom.net

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   

저작자 표시 비영리 변경 금지
신고

'Notice' 카테고리의 다른 글

스위프트 프로그래밍  (2) 2017.03.24
iOS 7 핵심노트  (15) 2014.01.20
페이스북 그룹 안내  (6) 2013.07.03
Posted by yagom


iOS 오픈 라이브러리 모음


제가 자주 사용하는 라이브러리들을 모아봤습니다. 

개인 취향이나 세부목적에 쓰는 기능이 아닌 보편적으로 쓸 수 있는 기능들을 위주입니다.
누군가에게는 도움이 되면 좋겠네요 :D

* [] 안에 표시된 이름은 Objective-C로 작성된 유사 라이브러리입니다.


* 유틸리티


Alamofire [AFNetworking]

말이 필요없는 네트워킹 라이브러리죠! 

Swift로 쓰여졌으며 대부분의 네트워킹 기능을 아주 멋드러지게 구현해두었습니다. 

형제로는 Objective-C로 쓰여진 AFNetworking이 있습니다.


https://github.com/Alamofire/Alamofire

https://github.com/AFNetworking/AFNetworking




SwiftyJSON [JSONModel]

스위프트에서 JSON 다루기 정말 귀찮으시죠? 
스위프트에서 JSON을 손쉽게 다룰 수 있도록 기능이 구현되어있는 라이브러리입니다.




ObjectMapper

모델 객체를 JSON과 손쉽게 상호 변환할 수 있는 라이브러리입니다.

Alamofire, Realm 등 다른 라이브러리와도 손쉽게 연계할 수 있습니다.

[전수열님 추천] <- 심지어 전수열님은 이 라이브러리의 Contributor로 활동하고 계시죠 꺅


https://github.com/Hearst-DD/ObjectMapper




Kingfisher [SDWebImage]

웹 서버에 있는 이미지를 손쉽게 가져올 수 있으며, 캐싱 등의 처리를 알아서 관리해주는 라이브러리입니다. 
다양한 옵션으로 캐싱과 이미지 로딩 방법 등을 손쉽게 제어할 수 있습니다.






RealmSwift [RealmCocoa]

Realm 모바일 데이터베이스는 SQLite와 CoreData를 대체할 수 있는 크로스 플랫폼 모바일 데이터베이스로 무료 오픈소스로 제공됩니다. 
iOS 뿐만 아니라 안드로이드, React Native, Xamarin 등 여러 플랫폼에서 사용할 수 있습니다. 
Realm 모바일 데이터베이스를 사용하면 데이터 모델을 따로 만들고 않고도 리액티브 데이터 레이어를 쉽게 구현할 수 있으면서 성능이 최적화된 앱 개발에 도움이 됩니다.

CoreData를 감싼 라이브러리가 아니라 완전히 새로운 데이터베이스입니다. 렘이라고 읽습니다. 
렘 모바일 플랫폼(https://realm.io/docs/get-started/overview/#the-realm-mobile-platform)을 사용하면 서버와 손쉬운 데이터베이스 동기화도 가능합니다.




Then

대한민국의 짱짱 iOS 개발자 전수열느님[https://github.com/devxoul]이 만든 라이브러리입니다. 

클로저를 사용하여 인스턴스를 생성한 뒤 원하는 처리를 해줄 수 있습니다. 코드가 분산되지 않고 깔끔해집니다!


https://github.com/devxoul/Then




CoreStore

CoreData를 손쉽고 안전하게 관리할 수 있도록 도와주는 라이브러리입니다. 학습비용이 조금 있습니다만, 코어데이터를 조금 더 쉽게 운용할 수 있습니다.





SugarRecord

CoreData와 Realm 데이터베이스를 손쉽게 사용할 수 있도록 감싸놓은 라이브러리입니다. 

두 데이터베이스 종류에 상관없이 손쉽게 데이터베이스를 운용할 수 있습니다.


https://github.com/carambalabs/SugarRecord




Google Analytics Service

사용자 분석과 로그분석, 크래시 분석에 유용하죠. 구글 분석 툴.


https://developers.google.com/analytics/devguides/collection/ios/v3/sdk-download



Fabric

최근에 구글로 인수된 트위터의 사용자 분석 및 인증 도움 라이브러리입니다. 여러 기능을 포함하고 있습니다. 

저는 주로 사용자분석에 많이 활용하고, 크래시리틱스를 통해 크래스 로그 분석에 사용합니다.


https://get.fabric.io





* UI/UX


SnapKit

오토레이아웃을 코드로 구성할 때 매우 편리하게 작성할 수 있게 도와주는 라이브러리입니다. 즉, 손쉬운 오토레이아웃 코드 작성 라이브러리! 


https://github.com/SnapKit/SnapKit




DZNEmptyDataSet

테이블 뷰나 컬렉션 뷰 등에 데이터가 없을 때 보여줄 수 있는 심플한 화면을 손쉽게 관리할 수 있는 라이브러리입니다.


https://github.com/dzenbot/DZNEmptyDataSet





TextFieldEffects

텍스트필드에 다양한 효과를 줄 수 있는 라이브러리입니다.

 텍스트 필드에 다양한 애니메이션을 손쉽게 넣어줄 수 있습니다.


https://github.com/raulriera/TextFieldEffects





RETableViewManager

테이블뷰를 통해 여러종류의 입력을 받을 때 매우 유용하게 사용할 수 있는 라이브러리입니다. 

내 코드에서 테이블뷰 delegate와 dataSource 메서드를 구현해줄 필요도 없습니다.

커스터마이징도 자유롭게 제공합니다. 

조금의 학습비용이 있지만 제대로 사용할 줄 알면 편하게 테이블뷰를 다룰 수 있습니다.


https://github.com/romaonthego/RETableViewManager




Spring

애니메이션을 손쉽게 구현할 수 있는 라이브러리입니다. 

다양하고 연속적인 애니메이션을 간단한 코드로 사용할 수 있습니다. 

코드 뿐만 아니라 스토리보드에서도 옵션 설정이 가능합니다.


https://github.com/MengTo/Spring




SVProgressHUD

로딩 팝업 등을 손쉽고 예쁘게 보여줄 수 있는 라이브러리입니다. 

다양한 옵션과 모양이 있어 어떤 앱에서도 사용하기 좋습니다.


https://github.com/SVProgressHUD/SVProgressHUD



iRate

사용자에게 언제, 어떻게 앱스토어 리뷰를 제안해야 할지 고민이 많다구요? 

iRate를 사용하면 시기 적절하게 앱스토어 리뷰를 요청할 수 있습니다. 

짜증나지 않는 선에서 알아서 간간히 앱스토어 리뷰를 요청합니다.


https://github.com/nicklockwood/iRate



SCAlertView

손쉽게 알림창(Alert)를 보여줄 수 있는 라이브러리입니다. 커스터마이징이 쉽고 깔끔하게 동작합니다.


https://github.com/vikmeup/SCLAlertView-Swift



MGSwipeTableCell

테이블뷰의 셀을 Swipe(옆으로 밀어 끌기) 했을 때 다양한 애니메이션과 메뉴 옵션을 제공하는 라이브러리입니다. 


https://github.com/MortimerGoro/MGSwipeTableCell



Charts

예쁜 차트를 손쉽게 그리고 관리할 수 있는 라이브러리입니다. 크으~


https://github.com/danielgindi/Charts



PagingMenuController

세그먼트 컨트롤 또는 툴바 등을 사용한 여러 메뉴를 한 화면에 보여주는 경우 스와이프 제스쳐로 페이징이 가능하도록 할 수 있는 라이브러입니다. 

iOS에서 권장하는 UX는 아니지만 종종 필요한 경우 유용합니다.


https://github.com/kitasuke/PagingMenuController




Hero

다양한 인터렉션을 통해 뷰 컨트롤러 간에 전환(transition)을 손쉽게 구현할 수 있는 라이브러리입니다. 
다양한 제스쳐와 전환 애니메이션을 제공합니다. 강추!
[윤병훈님 추천]





* 폰트/디자인


Chameleon

디자인 감각이 없는 사람도 예쁜 색 조합을 맞출 수 있습니다. 

최근 베타로 테마기능을 넣어서 테마만 설정해주면 앱 전반적으로 플랫 색상을 지정해줍니다. 

개인 개발자에게 매우 유용!


https://github.com/ViccAlexander/Chameleon




FontAwesomeKit

다양한 아이콘 폰트를 사용할 수 있는 라이브러리. 

웹에는 Font Awsome이 있다면 iOS에는 FontAwsomeKit이 있습니다!


https://github.com/PrideChung/FontAwesomeKit



FontBlaster

외부 서체(폰트)를 손쉽게 가져와서 활용할 수 있도록 도와주는 라이브러리입니다. 

기본 폰트가 아닌 앱 전용 폰트를 사용한다면 매우 유용하게 사용할 수 있습니다.


https://github.com/ArtSabintsev/FontBlaster



Material

메테리얼 디자인을 위한 라이브러리입니다. 

다양한 메테리얼 애니메이션과 그래픽 요소들이 포함되어 있습니다.


https://github.com/CosmicMind/Material




* 보너스

PinterestSwift

라이브러리는 아니지만 Pinterest와 같은 화면 이동을 구현해놓은 샘플코드입니다. 참고해볼 만한 코드.








유용한 라이브러리를 찾으셨나요?

더 좋은 라이브러리, 추천하고 싶은 라이브러리가 있다면 덧글로 알려주세요~! 한 번 모아볼까요? :D
 



by yagom

facebook : https://facebook.com/yagomsoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


저작자 표시 비영리 변경 금지
신고
Posted by yagom


오늘의 주제

1. 프로토콜 지향 프로그래밍



안녕하세요, 야곰입니다. 


지난 포스팅에서는 스위프트의 프로토콜과 익스텐션에 대해 알아봤습니다.


2017/01/23 - [Swift] - Swift란 어떤 언어인가?

2017/01/25 - [Swift] - Swift 기초문법 - 변수, 상수, 기초 데이터 타입

2017/02/06 - [Swift] - Swift - 함수, 콜렉션 타입

2017/02/28 - [Swift] - Swift - 구조체 클래스

2017/03/07 - [Swift] - Swift - 프로토콜, 익스텐션

이번에는 스위프트와 함께 대두된 프로토콜 지향 프로그래밍 디자인 패턴에 대해 알아보겠습니다 :)



프로토콜 지향 프로그래밍

애플은 2015년 9월, WWDC에서 스위프트 버전 2.0을 발표하면서 스위프트는 프로토콜 지향 언어(Protocol-Oriented Language)라고 발표했습니다. 프로토콜 지향 언어는 도대체 무슨 뜻일까요? 스 위프트의 표준 라이브러리에서 타입과 관련된 것을 살펴보면 대부분이 구조체로 구현되어 있습니다. 객체지향 프로그래밍 패러다임에 기반을 둔 언어는 대부분 클래스의 상속을 사용해 타입에 공통된 기능을 구현합니다. 그런데 스위프트는 클래스로 구현된 타입은 별로없고, 대부분 구조체로 기본 타입이 구현되어 있습니다. 상속도 되지 않는 구조체로 어떻게 그렇게 다양한 공통 기능을 가질 수 있는 걸까요? 해답은 프로토콜과 익스텐션에 있습니다.

프로토콜 초기구현

지난 포스팅에서 프로토콜(Protocol)특정 역할을 수행하기 위한 메서드, 프로퍼티, 기타 요구사항 등의 청사진이라고 말씀드렸습니다. 프로토콜을 채택(Adopted)한 타입은 프로토콜이 요구하는 기능을 구현하여 프로토콜을 준수해야(Conform)합니다. 
익스텐션은 기존 타입의 기능을 확장하며, 프로토콜은 프로토콜을 채택한 타입이 원하는 기능을 강제로 구현한다는 점을 우리는 알고 있습니다. 그런데 특정 프로토콜을 정의하고 여러 타입에서 이 프로토콜을 준수하게 만들어 타입마다 똑같은 메서드, 똑같은 프로퍼티, 똑같은 서브스크립트 등을 구현해야 한다면...? 얼마나 많은 코드를 중복 사용해야 하며 또 유지보수는 얼마나 힘들어질지 생각만 해도 머리가 아플 겁니다. 이때 필요한 게 바로 익스텐션과 프로토콜의 결합입니다. 
프로토콜을 채택한 타입의 정의부에 프로토콜의 요구사항을 구현하지 않더라도 프로토콜의 익스텐션에 미리 프로토콜의 요구사항을 구현해 둘 수 있습니다. 이를 프로토콜 초기구현이라고 합니다. 

protocol Talkable {
    var topic: String { get set }
    func talk(to: Self)
}

struct Person: Talkable {
    var topic: String
    var name: String
    
    func talk(to: Person) {
        print("\(topic)에 대해 \(to.name)에게 이야기합니다")
    }
}

여기 지난 포스팅에서 예제로 보았던 Talkable 프로토콜이 있습니다. 이 프로토콜은 Person이라는 구조체 타입에만 채택이 되었으므로 여러 프로퍼티와 메서드를 구현하더라도 Person에만 구현하면 되므로 큰 문제가 없었습니다. 그런데, Talkable이라는 프로토콜을 Person 뿐만 아니라 다른 타입에서도 채택하고 싶다면? 아마도 그 타입에서도 Talkable 프로토콜이 요구하는 사항을 모두 구현해 주어야 할 것입니다.

protocol Talkable { var topic: String { get set } func talk(to: Self) } struct Person: Talkable { var topic: String var name: String func talk(to: Person) { print("\(topic)에 대해 \(to.name)에게 이야기합니다") } } struct Monkey: Talkable { var topic: String func talk(to: Monkey) { print("우끼끼 꺄꺄 \(topic)") } }


그런데 프로토콜이 요구하는 사항을 미리 모두 한꺼번에 구현해 둘 수 있다면 중복된 코드를 피할 수 있을 것입니다.

protocol Talkable { var topic: String { get set } func talk(to: Self) } // 익스텐션을 사용한 프로토콜 초기 구현 extension Talkable { func talk(to: Self) { print("\(to)! \(topic)") } } struct Person: Talkable { var topic: String var name: String } struct Monkey: Talkable { var topic: String } let yagom = Person(topic: "Swift", name: "yagom") let hana = Person(topic: "Internet", name: "hana") yagom.talk(to: hana) hana.talk(to: yagom)


위의 코드에서는 Person과 Monkey에 Talkable의 요구사항인 talk(to:) 메서드를 구현하지 않았음에도 전혀 오류가 발생하지 않습니다.
이렇게 하나의 프로토콜을 만들어두고, 초기 구현을 해둔다면 여러 타입에서 해당 기능을 사용하고 싶을 때 프로토콜을 채택하기만 하면 됩니다.
만약에 프로토콜 초기 구현과 다른 동작을 해야한다면, 그저 그 타입에 프로토콜의 요구사항을 재정의해주면 됩니다.

struct Monkey: Talkable { var topic: String func talk(to: Monkey) { print("\(to)! 우끼기기기끼기기") } } let sunny = Monkey(topic: "바나나") let jack = Monkey(topic: "나무") sunny.talk(to: jack)


프로토콜 초기 구현을 잘 해둔다면 여러 프로토콜을 그저 채택만 하기만하면 그 타입에 기능이 추가되는 것이죠.

protocol Flyable { func fly() } extension Flyable { func fly() { print("푸드득 푸드득") } } protocol Runable { func run() } extension Runable { func run() { print("후다닥 후다닥") } } protocol Swimable { func swim() } extension Swimable { func swim() { print("어푸 어푸") } } protocol Talkable { func talk() } extension Talkable { func talk() { print("재잘재잘 쪼잘쪼잘") } } struct Bird: Flyable, Talkable { } let bird = Bird() bird.fly() bird.talk() struct Person: Runable, Swimable, Talkable { } let person = Person() person.run() person.talk() person.swim()


위 코드처럼 프로토콜 초기 구현을 잘 해두면 이렇게 프로토콜 채택만으로도 그 기능을 사용할 수 있게 됩니다. 프로토콜 초기 구현이 프로토콜 지향 프로그래밍의 핵심이라고 볼 수 있습니다.

프로토콜 지향 프로그래밍을 추구하는 이유

그렇다면 프로토콜 지향 프로그래밍을 하는 이유는 무엇일까요?

  • 구조체, 클래스, 열거형 등 구조화된 타입 중에 상속은 클래스 타입에서만 가능합니다.
    • 클래스는 참조 타입이므로 참조 추적에 비용이 많이 발생합니다. 비교적 비용이 적은 값 타입을 활용하고 싶어도, 상속을 할 수 없으므로 때마다 기능을 다시 구현해 주어야 했지만, 프로토콜 지향 프로그래밍은 그 한계를 없앴습니다.
  • 기능의 모듈화가 더욱 명확해 집니다.
    • 클래스가 상속을 할 수 있도록 설계되어 있다고 하더라도 다중상속을 지원하는 언어는 많지 않습니다. 다중상속을 지원하지 않는다는 뜻은 하나의 상속체계에서 다른 상속체계에 속해있는 기능을 끌어다 쓸 수 없다는 뜻입니다. 그런데 프로토콜 지향 프로그래밍은 기능을 프로토콜이라는 단위로 묶어 표현하고 초기 구현을 해 둘 수 있으니 상속이라는 한계점을 탈피할 수 있습니다.

어떠신가요? 프로토콜 지향 프로그래밍! 정말 매력적이지 않나요?

익스텐션을 통한 각 프로토콜의 초기구현은 구현코드를 볼 수 없기 때문에 어떻게 구현되었는지 는 확실히 볼 수 없지만 Array의 정의만 보더라도 제네릭, 프로토콜을 다양하게 사용한 것을 볼 수 있습니다. 아마도 각 타입별로 공유하는 초기구현은 익스텐션으로 구현되어 있을 것입니다. 

스위프트의 주요 기능을 하나하나 알아갈수록 스위프트 표준 라이브러리의 코드가 눈에 잘 들어오실거예요. 하나의 기능을 알아갈 때마다 스위프트 표준 라이브러리를 살펴보면서 어떤 기능을 통해 구현 되었는지, 어떻게 연관이 되는지 읽어보고, 해석해보고, 상상해보는 것도 언어를 이해하는 데 도움이 됩니다. 

이번 포스팅에서는 프로토콜 지향 프로그래밍(Protocol Oriented Programming, POP) 대해 알아보았습니다. 
앞으로 또 무슨 주제를 써 나갈까요? 
그 동안 많은 도움이 되었길 빕니다!

고맙습니다 :D




by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/

twitter : http://www.twitter.com/yagomSoft ( @yagomsoft )

p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   

저작자 표시 비영리 변경 금지
신고
Posted by yagom


오늘의 주제

1. 프로토콜
2. 익스텐션




안녕하세요, 야곰입니다. 


지난 포스팅에서는 스위프트의 구조체와 클래스에 대해 알아봤습니다.


2017/01/23 - [Swift] - Swift란 어떤 언어인가?

2017/01/25 - [Swift] - Swift 기초문법 - 변수, 상수, 기초 데이터 타입

2017/02/06 - [Swift] - Swift - 함수, 콜렉션 타입

2017/02/28 - [Swift] - Swift - 구조체 클래스



이번에는 프로토콜과 익스텐션에 대해 알아보겠습니다 :)



프로토콜


프로토콜(Protocol)특정 역할을 수행하기 위한 메서드, 프로퍼티, 기타 요구사항 등의 청사진을 정의합니다. 구조체, 클래스, 열거형은 프로토콜을 채택(Adopted)해서 특정 기능을 수행하기 위한 프로토콜의 요구사항을 실제로 구현할 수 있습니다. 어떤 프로토콜의 요구사항을 모두 따르는 타입은 그 ‘프로토콜을 준수한다(Conform)’고 표현합니다. 타입에서 프로토콜의 요구사항을 충족시키려면 프로토콜이 제시하는 청사진의 기능을 모두 구현해야 합니다. 즉, 프로토콜은 기능을 정의하고 제시 할 뿐이지 스스로 기능을 구현하지는 않습니다. 


프로토콜 정의

프로토콜은 구조체, 클래스, 열거형의 모양과 비슷하게 정의할 수 있으며 protocol 키워드를 사용합니다. 


protocol 프로토콜 이름 {
    프로토콜 정의
}
구조체, 클래스, 열거형 등에서 프로토콜을 채택하려면 타입 이름 뒤에 콜론(:)을 붙여준 후 채택할 프로토콜 이름을 쉼표(,)로 구분하여 명시해줍니다. 

struct SomeStruct: AProtocol, AnotherProtocol {
    // 구조체 정의
}

class SomeClass: AProtocol, AnotherProtocol {
    // 클래스 정의
}

enum SomeEnum: AProtocol, AnotherProtocol {
    // 열거형 정의
}

위 코드의 각 타입은 AProtocol과 AnotherProtocol을 채택한 것입니다. 만약, 클래스가 다른 클래스를 상속받는다면 상속받을 클래스 이름 다음에 채택할 프로토콜을 나열해줍니다. 
class SomeClass: SuperClass, AProtocol, AnotherProtocol {
    // 클래스 정의
}

위의 SomeClass는 SuperClass를 상속받았으며 동시에 AProtocol과 AnotherProtocol 프로토콜을 채택한 클래스입니다. 

프로토콜 요구사항

프로토콜은 타입이 특정 기능을 수행하기 위해 필요한 기능을 요구합니다. 프로토콜이 자신을 채택한 타입에 요구하는 사항은 프로퍼티나 메서드와 같은 기능들입니다. 프로토콜은 프로퍼티, 메서드, 서브스크립트, 이니셜라이저 등의 기능을 요구할 수 있습니다.

프로퍼티 요구


프로토콜은 자신을 채택한 타입이 어떤 프로퍼티를 구현해야 하는지 요구할 수 있습니다. 그렇지만 프로토콜은 그 프로퍼티의 종류(연산 프로퍼티인지, 저장 프로퍼티인지 등)는 따로 신경쓰지 않습니다. 프로토콜을 채택한 타입은 프로토콜이 요구하는 프로퍼티의 이름과 타입만 맞도록 구현해주면 됩니다. 다만, 프로퍼티를 읽기 전용으로 할지 혹은 읽고 쓰기가 모두 가능하게 할지는 프로토콜이 정해야 합니다. 

프로토콜의 프로퍼티 요구사항은 항상 var 키워드를 사용한 변수 프로퍼티로 정의됩니다. 읽기와 쓰기가 모두 가능한 프로퍼티는 프로퍼티의 정의 뒤에 {get set}이라고 명시하며, 읽기 전용 프로퍼티는 프로퍼티의 정의 뒤에 {get}이라고 명시해줍니다. 

protocol SomeProtocol { var settableProperty: String { get set } var notNeedToBeSettableProperty: String { get } } protocol AnotherProtocol { static var someTypeProperty: Int { get set } static var anotherTypeProperty: Int { get } }


위 코드의 SomeProtocol에 정의된 settableProperty는 읽기와 쓰기 모두를 요구했고, notNeedToBeSettableProperty는 읽기만 가능하다면 어떻게 구현되어도 상관없다는 요구사항입니다. 타입 프로퍼티를 요구하려면 static 키워드를 사용합니다. 클래스의 타입 프로퍼티에는 상속 가능한 타입 프로퍼티인 class 타입 프로퍼티와 상속 불가능한 static 타입 프로퍼티가 있습니다만 이 두 타입 프로퍼티를 따로 구분하지 않고 모두 static 키워드 를 사용하여 타입 프로퍼티를 요구하면 됩니다. AnotherProtocol에 정의된 someProperty 와 anotherProperty는 모두 타입 프로퍼티를 요구합니다.

protocol Talkable {
    var topic: String { get set }
}

struct Person: Talkable {
    var topic: String
}

Talkable 프로토콜은 어떤 주제에 대해 말할 수 있게 하기 위한 프로퍼티인 topic를 요구합니다. 그래서 Talkable 프로토콜을 채택하여 준수하는 Person 클래스는 topic 프로퍼티를 가져야합니다.


메서드 요구


프로토콜은 특정 인스턴스 메서드나 타입 메서드를 요구할 수도 있습니다. 프로토콜이 요구할 메서드는 프로토콜 정의에서 작성합니다. 다만, 메서드의 실제 구현부인 중괄호({}) 부분은 제외하고 메서드의 이름, 매개변수, 반환 타입 등만 작성합니다. 프로토콜의 메서드 요구에서는 매개변수 기본값을 지정할 수 없습니다. 타입 메서드를 요구할 때는 타입 프로퍼티 요구와 마찬가지로 앞에 static 키워드를 명시합니다. static 키워드를 사용 하여 요구한 타입 메서드를 클래스에서 실제 구현할 때에는 static 키워드나 class 키워드 어느 쪽을 사용해도 무방합니다.

protocol Talkable {
    var topic: String { get set }
    func talk(to: Person)
}

struct Person: Talkable {
    var topic: String
    var name: String
    
    func talk(to: Person) {
        print("\(topic)에 대해 \(to.name)에게 이야기합니다")
    }
}

이니셜라이저 요구


프로토콜은 프로퍼티, 메서드 등과 마찬가지로 특정한 이니셜라이저를 요구할 수도 있습니다. 프로토콜에서 이니셜라이저를 요구하려면 메서드 요구와 마찬가지로 이니셜라이저를 정의하지만 구현은 하지 않습니다. 즉, 이니셜라이저의 매개변수를 지정하기만 할 뿐, 중괄호를 포함한 이니셜라이저 구현은 하지 않습니다. 


protocol Talkable {
    var topic: String { get set }
    func talk(to: Person)
    init(name: String, topic: String)
}

struct Person: Talkable {
    var topic: String
    var name: String
    
    func talk(to: Person) {
        print("\(topic)에 대해 \(to.name)에게 이야기합니다")
    }
    
    init(name: String, topic: String) {
        self.name = name
        self.topic = topic
    }
}

let yagom: Person = Person(name: "야곰", topic: "스위프트")
let hana: Person = Person(name: "하나", topic: "코딩")

yagom.talk(to: hana)
// 스위프트에 대해 하나에게 이야기합니다

프로토콜의 상속


프로토콜은 하나 이상의 프로토콜을 상속받아 기존 프로토콜의 요구사항보다 더 많은 요구사항을 추가할 수 있습니다. 프로토콜 상속 문법은 클래스의 상속 문법과 유사합니다. 

protocol Readable {
    func read()
}
protocol Writeable {
    func write()
}
protocol ReadSpeakable: Readable {
    func speak()
}
protocol ReadWriteSpeakable: Readable, Writeable {
    func speak()
}

class SomeClass: ReadWriteSpeakable {
    func read() {
        print("Read")
    }
    
    func write() {
        print("Write")
    }
    
    func speak() {
        print("Speak")
    }
}
위 코드의 ReadSpeakable 프로토콜은 Readable 프로토콜을 상속받았고 ReadWriteSpeakable 프로토콜은 Readable과 Writeable 프로토콜을 상속받았습니다. 그래서 ReadWriteSpeakable 프로토콜을 채택한 SomeClass는 세 프로토콜이 요구하는 read(), write(), speak() 메서드를 모두 구현해야 합니다. 


익스텐션

익스텐션(Extension)은 스위프트의 강력한 기능 중 하나입니다. 익스텐션은 구조체, 클래스, 열거형, 프로토콜 타입에 새로운 기능을 추가할 수 있는 기능입니다. 기능을 추가하려는 타입의 구현된 소스 코드를 알지 못하거나 볼 수 없다 해도, 타입만 알고 있다면 그 타입의 기능을 확장할 수도 있습니다.

스위프트의 익스텐션이 타입에 추가할 수 있는 기능은 다음과 같습니다. 

  • 연산 타입 프로퍼티 / 연산 인스턴스 프로퍼티 
  • 타입 메서드 / 인스턴스 메서드
  • 이니셜라이저
  • 서브스크립트 
  • 중첩 타입
  • 특정 프로토콜을 준수할 수 있도록 기능 추가 
익스텐션은 타입에 새로운 기능을 추가할 수는 있지만, 기존에 존재하는 기능을 재정의할 수는 없습니다. 클래스 의 상속과 익스텐션을 비교해보겠습니다. 이 둘은 비슷해보이지만 실제 성격은 많이 다릅니다. 

클래스의 상속은 클래스 타입에서만 가능하지만 익스텐션은 구조체, 클래스, 프로토콜 등에 적용이 가능합니다. 또 클래스의 상속은 특정 타입을 물려받아 하나의 새로운 타입을 정의하고 추가 기능을 구현하는 수직 확장이지만, 익스텐션은 기존의 타입에 기능을 추가하는 수평 확장입니다. 또, 상속을 받으면 기존 기능을 재정의할 수 있지만, 익스텐션은 재정의할 수 없다는 것도 큰 차이 중 하나입니다. 상황과 용도에 맞게 상속과 익스텐션을 선택하여 사용하면 됩니다. 

 

상속 

익스텐션 

확장 

수직 확장 

수평 확장 

사용 

클래스 타입에만 사용 

클래스, 구조체, 프로토콜, 제네릭 등 모든 타입 

 재정의

재정의 가능 

재정의 불가 


익스텐션을 사용하는 대신 원래 타입을 정의한 소스에 기능을 추가하는 방법도 있겠지만, 외부 라이브러리나 프레임워크를 가져다 썼다면 원본 소스를 수정하지 못합니다. 이처럼 외부에서 가져온 타입에 내가 원하는 기능을 추가하고자 할 때 익스텐션을 사용합니다. 따로 상속을 받지 않아도 되며, 구조체와 열거형에도 기능을 추가할 수 있으므로 익스텐션은 매우 편리한 기능입니다. 

익스텐션은 모든 타입에 적용할 수 있습니다. 모든 타입이라 함은 구조체, 열거형, 클래스, 프로토콜, 제네릭 타입 등을 뜻합니다. 즉, 익스텐션을 통해 모든 타입에 연산 프로퍼티, 메서드, 이니셜라이저, 서브스크립트, 중첩 데이터 타입 등을 추가할 수 있습니다.

더불어 익스텐션은 프로토콜과 함께 사용하면 굉장히 강력한 기능을 선사합니다. 그 내용은 다음 포스팅인 프로토콜 지향 프로그래밍에서 조금 더 자세히 다루겠습니다. 


익스텐션 문법


익스텐션은 extension이라는 키워드를 사용하여 선언합니다. 
extension 확장할 타입 이름 {
    // 타입에 추가될 새로운 기능 구현
}
익스텐션은 기존에 존재하는 타입이 추가적으로 다른 프로토콜을 채택할 수 있도록 확장할 수도 있습니다. 이런 경우에는 클래스나 구조체에서 사용하던 것과 똑같은 방법으로 프로토콜 이름을 나열해줍니다. 
extension 확장할 타입 이름: 프로토콜1, 프로토콜2, 프로토콜3 {
    // 프로토콜 요구사항 구현
}

스위프트 라이브러리를 살펴보면 실제로 익스텐션이 굉장히 많이 사용되고 있음을 알 수 있습니다. Double 타입에는 수많은 프로퍼티와 메서드, 이니셜라이저가 정의되어 있으며 수많은 프로토콜을 채택하고 있을 것이라고 예상되지만, 실제로 Double 타입의 정의를 살펴보면 그 모든것이 다 정의되어 있지는 않습니다. 

그러면 Double 타입이 채택하고 준수해야 하는 수많은 프로토콜은 어디로 갔을까요? 어디에서 채택하고 어디에서 준수하도록 정의되어 있을까요? 당연히 답은 익스텐션입니다. 이처럼 스위프트 표준 라이브러리 타입의 기능은 대부분 익스텐션으로 구현되어 있습니다. Double 외에도 다른 타입들의 정의와 익스텐션을 찾아보면 더 많은 예를 보실 수 있습니다. 꼭 한 번 찾아보세요! 

익스텐션으로 확장할 수 있는 항목 

익스텐션을 통해 추가할 수 있는 기능에는 연산 프로퍼티, 메서드, 이니셜라이저, 서브스크립트, 중첩 데이터 타입 등이 있습니다.

연산 프로퍼티 추가


extension Int {
    var isEven: Bool {
        return self % 2 == 0
    }
    var isOdd: Bool {
        return self % 2 == 1
    }
}

print(1.isEven) // false
print(2.isEven) // true
print(1.isOdd)  // true
print(2.isOdd)  // false

var number: Int = 3
print(number.isEven) // false
print(number.isOdd) // true

number = 2
print(number.isEven) // true
print(number.isOdd) // false

위 코드의 익스텐션은 Int 타입에 두 개의 연산 프로퍼티를 추가한 것입니다. Int 타입의 인스턴스가 홀수인지 짝수인지 판별하여 Bool 타입으로 알려주는 연산 프로퍼티입니다. 익스텐션으로 Int 타입에 추가해준 연산 프로퍼티는 Int 타입의 어떤 인스턴스에도 사용이 가능합니다. 위의 코드처럼 인스턴스 연산 프로퍼티를 추가할 수도 있으며, static 키워드를 사용하여 타입 연산 프로퍼티도 추가할 수 있습니다. 


메서드 추가


익스텐션을 통해 타입에 메서드를 추가할 수 있습니다.

extension Int {
    func multiply(by n: Int) -> Int {
        return self * n
    }
}
print(3.multiply(by: 2))  // 6
print(4.multiply(by: 5))  // 20

var number: Int = 3
print(number.multiply(by: 2))   // 6
print(number.multiply(by: 3))   // 9
위 코드의 익스텐션을 통해 Int 타입에 인스턴스 메서드인 multiply(by:) 메서드를 추가했습니다. 여러 기능을 여러 익스텐션 블록으로 나눠서 구현해도 전혀 문제가 없습니다. 관련된 기능별로 하나의 익스텐션 블록에 묶어주는 것도 좋습니다. 


이니셜라이저 추가


인스턴스를 초기화(이니셜라이즈)할 때 인스턴스 초기화에 필요한 다양한 데이터를 전달받을 수 있도록 여러 종류의 이니셜라이저를 만들 수 있습니다. 타입의 정의부에 이니셜라이저를 추가하지 않더라도 익스텐션을 통해 이니셜라이저를 추가할 수 있습니다. 

하지만 익스텐션으로 클래스 타입에 편의 이니셜라이저는 추가할 수 있지만, 지정 이니셜라이저는 추가할 수 없습니다. 지정 이니셜라이저와 디이니셜라이저는 반드시 클래스 타입의 구현부에 위치해야 합니다.(값 타입은 상관없습니다.) 

extension String { subscript(appendValue: String) -> String { return self + appendValue } subscript(repeatCount: UInt) -> String { var str: String = "" for _ in 0..<repeatCount { str += self } return str } } print("abc"["def"]) // "abcdef" print("abc"[3]) // "abcabcabc"


이번엔 스위프트의 프로토콜과 익스텐션 대해 알아봤습니다. 다음 포스팅에서는 프로토콜 지향 프로그래밍(Protocol Oriented Programming, POP) 대해 알아보겠습니다. 

다음 번에 또 뵈어요~ 고맙습니다 :D




by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/

twitter : http://www.twitter.com/yagomSoft ( @yagomsoft )

p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


저작자 표시 비영리 변경 금지
신고
Posted by yagom


티스토리 툴바