raywenderlich.com 에서 By Rony Rozen님이 작성하신 CocoaPods Tutorial for Swift: Getting Started 번역 자료입니다. 번역에 문제가 있다면 댓글 달아주시구요. 원문을 보시기를 추천드립니다.

Swift 용 CocoaPods Tutorial을 사용하여 Swift 프로젝트에서 타사 라이브러리 의존성을 설치하고 관리하는 방법을 배우십시오.

By Rony Rozen

[Download Materials]

version : Swift 5, iOS 13, Xcode 11

업데이트 노트 : Rony Rozen이 Xcode 11 및 Swift5 용 튜토리얼을 업데이트했습니다. Joshua Greene은 원본을 작성했습니다.

CocoaPods는 Swift 및 Objective-C Cocoa 프로젝트에 널리 사용되는 의존성 매니저(dependency manager)입니다. CocoaPods 웹 사이트 에 따르면 수천 개의 라이브러리와 수많은 앱 이이 라이브러리를 사용합니다. 그런데 의존성 매니저란 무엇이며 왜 필요한가요?

의존성 매니저를 사용하면 앱에서 사용하는 서드파티 의존성(dependencies)을 쉽게 추가, 제거, 업데이트와 관리를 할 수 ​​있습니다.

예를 들어, 자신의 네트워킹 라이브러리를 만드는 대신 의존성 매니저를 사용하여 Alamofire를 쉽게 가져올 수 있습니다. 정확한 버전 또는 허용 가능한 버전 범위를 지정할 수 있습니다.

즉, Alamofire가 이전 버전과 호환되지 않는 변경 사항으로 업데이트를 하더라도 업데이트 준비가 될 때까지 이전 버전을 계속 사용할 수 있습니다.

이 튜토리얼에서는 Swift와 함께 CocoaPods를 사용하는 방법을 배웁니다. 당신이 할일은:

  • CocoaPods를 설치하십시오.
  • 아이스크림에 대한 생각을 가지고 기능적인 데모 앱을 작업하세요.
  • CocoaPods를 사용하여 네트워킹을 추가하십시오.
  • 시맨틱 버저닝에 대해 학습합니다.
  • 유연한(flexible) 버전을 사용하여 다른 라이브러리를 추가하세요.

참고 : 이 CocoaPods 튜토리얼에는 iOS 및 Swift 개발에 대한 기본 지식이 필요합니다. iOS 또는 Swift를 처음 사용 하는 경우 이 튜토리얼을 수행하기 전에 이 사이트 의 다른 이나 비디오 자습서를 확인하십시오. 또는 iOS Apprentice 라는 책으로 입문 해보세요. 이 튜토리얼에는 코어 그래픽을 사용하는 클래스도 포함되어 있습니다. 핵심 그래픽에 대한 지식은 유익하지만 필수는 아닙니다. 자세한 내용 은 Swift를 사용한 Modern Core Graphics 시리즈를 참조하십시오.

 

시작하기

튜토리얼 맨 위 또는 맨 아래에 있는 Download Materials 버튼을 클릭하여 starter 프로젝트를 다운로드하십시오.

이 튜토리얼 전체에서 Ice Cream Shop, Inc 라는 앱을 사용하게 됩니다. CocoaPods를 사용하여 직접 작성하는 대신 앱에 의존성(dependencies)을 쉽게 추가 할 수 있습니다.

이 튜토리얼을 진행하기 전에 CocoaPods를 설치해야 합니다. 다행히 CocoaPods는 Ruby를 사용합니다. Ruby는 버전 10.7 이후의 모든 버전의 macOS X와 ​​함께 제공됩니다.

터미널을 열고 다음 명령을 입력하십시오.

sudo gem install cocoapods

요청 시 비밀번호를 입력하십시오. 터미널 출력에는 “XX gems installed”로 끝나는 다양한 패치, 설치 및 문서 관련 출력(outputs)이 표시됩니다.

참고 : CocoaPods를 설치하려면 sudo를 사용해야 하지만 일단 설치 되면 이 튜토리얼에서 다시 사용 할 필요가 없습니다.

마지막으로 터미널에서 이 명령을 입력하여 설정을 완료하세요.

pod setup --verbose

이 프로세스는 CocoaPods Master Specs 저장소를 컴퓨터의 ~/.cocoapods/ 에 복제하기 때문에 몇 분이 걸립니다 .

verbose옵션은 프로세스가 실행될 때 진행 상황을 로깅하므로 “멈춘” 화면이 아닌 과정(process)을 볼 수 있습니다.

이제 CocoaPods를 사용하도록 설정되었습니다!

 

아이스크림 전문점

당신의 최고 고객은 Ice Cream Shop, Inc입니다. 그들의 아이스크림은 매우 인기 있어 카운터에서 고객 주문을 처리 할 수 ​​없습니다. 고객이 iPhone에서 바로 아이스크림을 주문할 수 있는 세련된 iOS 앱을 만들도록 구인했습니다.

앱 개발을 시작했으며 잘 진행되고 있습니다. IceCreamShop.xcodeproj 를 연 다음 빌드하고 실행하여 진행 상황을 살펴보세요. 군침 도는 바닐라 아이스크림 콘이 나타납니다.

https://koenig-media.raywenderlich.com/uploads/2015/03/icecreamshop_starter-282x500.png

사용자는 이 화면에서 아이스크림 맛을 선택할 수 있어야 하지만 아직 불가능합니다. 첫 번째 단계는 이 기능의 구현을 마치는 것입니다.

Views/Storyboards & Nibs 그룹 에서 Main.storyboard 를 열어 앱의 레이아웃을 봅니다. 다음은 앱의 핵심 인 Choose Your Flavor(맛을 선택하는) scene 에 대한 간략한 개요입니다 .

https://koenig-media.raywenderlich.com/uploads/2017/04/ChooseYourFlavor-427x500.png

  • PickFlavorViewController이 scene의 view controller입니다. 사용자 상호 작용을 처리하고 다양한 아이스크림 맛을 표시하는 컬렉션 뷰에 대한 데이터를 제공합니다.
  • IceCreamView 백업 모드인 Flavor를 기반으로 아이스크림 콘을 표시하는 커스텀 뷰(custom view)입니다.
  • ScoopCell은 Flavor 모델에서 색상을 가져 오는 ScoopView를 포함하는 커스텀 콜렉션 뷰(custom collection view) 셀입니다.

모든 Ice Cream Shop, Inc. 위치에는 공통적인 특색이 있지만 각 지역마다 고유한 맛을 가지고 있습니다. 이러한 이유로 웹 서비스는 맛(Flavor)에 대한 데이터를 제공해야 합니다.

그러나 여전히 사용자가 아이스크림 맛을 선택할 수 없는 이유는 설명하지 않습니다.

Controllers 그룹 아래에 있는 PickFlavorViewController.swift를 열면 스텁(stubbed) 메서드(구현되지 않은 임시 코드..)가 표시됩니다.

private func loadFlavors() {
  // TO-DO: Implement this
}

아하, flavors가 없네요! 함수를 구현해야 합니다!

네트워킹 클래스를 사용 하고 작성할 수 있지만 [URLSession](http://www.raywenderlich.com/51127/nsurlsession-tutorial)보다 쉬운 방법이 있습니다. Alamofire를 사용하세요 !

라이브러리를 다운로드하고 소스 파일을 프로젝트로 바로 드래그하고 싶을 수도 있습니다. 그러나 그것은 어려운 방법입니다. CocoaPods는 훨씬 더 우아하고 영리한 솔루션을 제공합니다.

 

첫 번째 의존성(Dependency) 설치

첫 번째 단계는 Xcode 를 닫는 것 입니다. 네, 잘 읽어보세요

이제 프로젝트의 의존성을 정의 할 Podfile 을 만들 차례 입니다.

터미널을 열고 cd 커맨드를 사용 하여 IceCreamShop 프로젝트가 포함 된 디렉토리로 이동하십시오.

cd ~/Path/To/Folder/Containing/IceCreamShop

다음 명령을 입력하십시오.

pod init

프로젝트 Podfile이 생성 됩니다.

마지막으로 Xcode를 사용하여 Podfile을 수정 하려면 다음 명령을 입력하십시오.

open -a Xcode Podfile

참고 : Podfile을 편집 할 때는 TextEdit을 사용하지 마십시오. 표준 인용 부호가보다 그래픽으로 표현되는 활자 인용 부호로 대체되기 때문입니다. 이로 인해 CocoaPod가 혼동되어 오류가 발생할 수 있습니다. 대신 Xcode 또는 다른 프로그래밍 텍스트 편집기를 사용하여 Podfile을 편집하십시오.

기본 Podfile은 다음과 같습니다.

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'IceCreamShop' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for IceCreamShop

end

platform 앞의 #과 공백을 삭제 한 다음 #으로 시작하는 다른 행을 삭제하세요.

Podfile은 다음과 같아야 합니다.

platform :ios, '9.0'

target 'IceCreamShop' do
  use_frameworks!

end

이것은 CocoaPods에게 프로젝트가 iOS 9.0을 대상으로하고 정적 라이브러리(static libraries) 대신 프레임 워크를 사용하게합니다(use_frameworks!). Swift와 CocoaPods는 정적 링크를 지원하지만 포함하는 모든 라이브러리가 정적 링크를 지원하지는 않습니다. 이 프로젝트에서 사용할 것 중 하나는 그렇지 않습니다.

Swift 로만 프로그래밍을 한 경우 약간 이상하게 보일 수 있습니다. Podfile이 실제로 Ruby로 작성 되었기 때문입니다. CocoaPods를 사용하기 위해 Ruby를 알 필요는 없지만 사소한 텍스트 오류로 인해 CocoaPods가 오류를 발생시킬 수 있음을 알아야 합니다.

 

라이브러리에 관한 한마디

라이브러리(library)라는 용어는 실제로 라이브러리 또는 프레임워크를 의미하는 일반 용어로 사용 되는 것을 볼 수 있습니다. 이 튜토리얼은 이 단어들도 자연스럽게 섞어서 우연히 유죄(guilty of casually)입니다.

라이브러리, 프레임워크 와 CocoaPod의 차이점에 대해 궁금 할 것입니다. 용어가 약간 혼란스러워도 괜찮습니다!

CocoaPod, Pod는 CocoaPods를 사용하여 프로젝트에 추가되는 라이브러리 또는 프레임워크의 일반적인 용어입니다.

iOS 8에는 코드, 이미지 및 기타 에셋과 함께 묶을 수있는 동적 프레임워크(dynamic frameworks)가 도입되었습니다. iOS 8 이전에는 CocoaPod를 “fat” 정적 라이브러리(static libraries)로 만들었습니다. “Fat”은 시뮬레이터 용 i386, 장치 용 armv7 등과 같은 몇 가지 코드 명령어 세트를 포함했음을 의미합니다. 그러나 Swift에서는 정적 라이브러리에 이미지 또는 에셋과 같은 리소스를 포함 할 수 없습니다.

 

첫 번째 의존성 설치로 돌아 가기

이제 CocoaPods를 사용하여 첫 번째 의존성을 추가 할 차례입니다. Podfile에 다음 라인을 추가하세요 use_frameworks! :

pod 'Alamofire', '4.9.1'

이것은 CocoaPods에게 프로젝트에 대한 의존성으로 Alamofire 버전 4.9.1을 포함길 원한다는 것을 알려줍니다.

Podfile을 저장하고 닫습니다.

이제 프로젝트의 의존성을 설치하도록 CocoaPods에 지시해야합니다.

IceCreamShop 프로젝트와 Podfile이 들어있는 디렉토리에 있는지 확인한 후 Terminal에 다음 명령을 입력하십시오 .

pod install

다음과 같은 출력이 표시되어야 합니다.

Analyzing dependencies
Adding spec repo `trunk` with CDN `https://cdn.cocoapods.org/`
Downloading dependencies
Installing Alamofire (4.9.1)
Generating Pods project
Integrating client project

[!] Please close any current Xcode sessions and use `IceCreamShop.xcworkspace` for this project from now on.
Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.

Finder를 사용하여 프로젝트 폴더를 열면 CocoaPods가 새로운 IceCreamShop.xcworkspace 파일과 Pods 폴더를 생성하여 프로젝트의 모든 의존성을 저장하는 것을 볼 수 있습니다.

참고 : 지금부터 커맨드라인 경고(warning)에서와 항상 .xcodeproj가 아니라 .xcworkspace 파일로 프로젝트를 열어야합니다. 그렇지 않으면 빌드 오류가 발생합니다.

훌륭해요! CocoaPods를 사용하여 첫 번째 의존성을 추가했습니다!

 

설치된 pod 사용

이제 새로운 의존성인 Alamofire를 사용하게됩니다.

Xcode 프로젝트가 열려 있으면 지금 닫고 IceCreamShop.xcworkspace를 여십시오.

PickFlavorViewController.swift를 열고 기존 import 바로 아래에 다음을 추가하십시오.

import Alamofire

빌드하고 실행하십시오. 아직 변경 사항은 없지만 Alamofire를 지금 사용 할 수 있습니다.

https://koenig-media.raywenderlich.com/uploads/2020/01/Simulator-Screen-Shot-iPhone-11-Pro-Max-2020-01-16-at-20.19.34-231x500.png

다음으로 loadFlavors()를 다음으로 바꾸십시오.

private func loadFlavors() {
    // 1    
    Alamofire.request(
      "https://www.raywenderlich.com/downloads/Flavors.plist",
      method: .get,
      encoding: PropertyListEncoding(format: .xml, options: 0))
        .responsePropertyList { [weak self] response in
        // 2
        guard let self = self else { return }
        
        // 3        
        guard 
          response.result.isSuccess,
          let dictionaryArray = response.result.value as? [[String: String]] 
          else {
            return
        }

        // 4
        self.flavors = self.flavorFactory.flavors(from: dictionaryArray)
        
        // 5
        self.collectionView.reloadData()
        self.selectFirstFlavor()
    }
  }

다음은 이 코드에서 발생하는 상황 별 플레이(play-by-play)입니다.

  1. Alamofire를 사용하여 GET 요청을 작성하고 아이스크림 맛이 포함 된 plist를 다운로드하십시오.

  2. 강한(strong) 참조주기(reference cycle)를 중단하려면 응답 완료 블록(response completion block)에서 약한 self 참조를 사용합니다. 블록이 실행되면 즉시 self에 대한 강력한 참조를 얻으므로 나중에 블록에 속성을 설정할 수 있습니다.

  3. 다음으로 response.result가 성공을 표시하고 response.result.value가 dictionary의 배열인지 확인하십시오.

  4. 이제 self.flavorsFlavorFactory가 생성하는 Flavor 객체의 배열로 설정합니다. 이 클래스는 “colleague(동료)”가 여러분을 위해 작성한 클래스입니다(환영합니다!). 다양한 dictionary를 사용하여 Flavor 인스턴스를 만드는 데 사용합니다.

  5. 마지막으로 컬렉션 뷰를 다시 로드하고 첫 번째 flavor를 선택합니다.

https://koenig-media.raywenderlich.com/uploads/2015/03/choose_flavor-282x500.png

 

맛있는 토핑을 위해

앱은 좋아 보이지만 아직 개선 할 수 있습니다.

flavors 파일을 다운로드하는 데 앱에 1초가 걸린다는 것을 알고 계셨습니까? 인터넷 연결이 빠르면 지연이 눈치 채지 못할 수도 있지만 고객이 항상 운이 좋은 것은 아닙니다.

다음 단계는 앱에 로딩 표시기를 표시하여 고객이 라이브러리를 돌리는 것이 아니라 데이터를로드하고 있음을 이해하도록 도와줍니다.

이 pod를 사용하려면 Podfile에 해당 pod를 추가해야합니다. 명령 행에서 Podfile을 여는 대신 이제 작업 공간의 Pods 대상에서 찾을 수 있습니다. MBProgressHUD는 여기서 잘 작동하는 정말 좋은 지표입니다. 그리고 CocoaPods를 지원합니다; 이런 우연이! :]

https://koenig-media.raywenderlich.com/uploads/2015/03/pods_in_workspace-365x320.png

Podfile을 열고 Alamofire 라인 바로 뒤에 다음을 추가하십시오.

pod 'MBProgressHUD', '~> 1.0'

파일을 저장하고 이전과 마찬가지로 터미널에서 pod 설치를 통해 종속성을 설치하십시오.

이번에는 다른 점이 있습니까? 그러나 버전 번호를 ~> 1.0으로 지정했습니다. 왜죠?

CocoaPods는 모든 pod가 Semantic Versioning을 사용하도록 권장합니다. 그것이 무엇인지 이해하기 위해 잠시 시간을 내볼까요.

 

Semantic Versioning

여러 번 다음과 같이 작성된 버전이 표시됩니다 : 1.0.0. 이 세 숫자는 주 버전(major), 부 버전(minor)패치(patch) 버전 번호입니다.

예를 들어 버전 번호 1.0.0의 경우 1은 주 번호이고 첫 번째 0은 부 번호이고 두 번째 0은 패치 번호입니다.

https://koenig-media.raywenderlich.com/uploads/2017/04/sem_versioning.png

주 번호(major)가 증가하면 버전이 이전 버전과 호환되지 않는 변경 사항을 포함하고 있음을 나타냅니다. pod를 다음 주요 버전으로 업그레이드 할 때 빌드 오류를 수정해야하거나 pod가 이전과 다르게 동작 할 수 있습니다.

부 번호(minor)가 증가하면 버전에 이전 버전과 호환되는 새로운 기능이 포함되어 있음을 나타냅니다. 업그레이드하기로 결정할 때 새로운 기능이 필요하거나 필요하지 않을 수 있지만 빌드 오류가 발생하거나 기존 동작이 변경되지 않아야합니다.

패치 번호(patch)가 증가하면 새 버전에 버그 수정이 포함되어 있지만 새로운 기능이나 동작(behavior)이 변경되지 않았음을 의미합니다. 일반적으로 항상 최신 버전의 최신 버전의 pod을 갖도록 가능한 빨리 패치 버전을 업그레이드 하려고 합니다.

마지막으로, 위 규칙에 따라 최상위 숫자 (major, minor, patch)를 늘리면 하위 숫자를 0으로 재설정해야합니다.

예를 들면 다음과 같습니다.

현재 버전 번호가 1.2.3 인 pod를 고려하십시오.

이전 버전과 호환되지 않는(not backward-compatible) 기능을 변경하고 새로운 기능은 없지만 기존 버그를 수정하면 버전 2.0.0이 제공됩니다.

 

도전 시간

pod의 현재 버전이 2.4.6이고 버그를 수정하고 구 버전과 호환되는 기능을 추가하도록 변경 한 경우 새 버전 번호는 무엇입니까?

답 : 2.5.0 설명 : 이전 버전과 호환되는 새로운 기능을 포함하여 변경하는 경우 부 번호를 늘리고 패치를 0으로 재설정합니다.

pod의 현재 버전이 3.5.8 이고 이전 버전과 호환되지 않는 기존 기능을 변경 한 경우 새 버전 번호는 무엇입니까?

답 : 4.0.0 설명 : 변경 사항이 기존 동작을 수정하고 이전 버전과 호환되지 않으면 주 번호를 늘리고 부 번호와 패치 번호를 0으로 재설정해야합니다.

pod의 현재 버전이 10.20.30이고 버그만 수정 한 경우 새 버전 번호는 무엇입니까?

답 : 10.20.31 설명 : 버그만 수정하면 패치 번호 만 증가시킵니다.

이 모든 것을 말했지만, 이러한 규칙에는 한 가지 예외가 있습니다.

pod의 버전 번호가 1.0.0보다 작은 경우 베타 버전으로 간주됩니다. 약간의 숫자 증가는 이전 버전과 호환되지 않는 변경 사항을 포함 할 수 있습니다.

다시 MBProgressHUB로 돌아 가기 : ~> 1.0 을 사용하면 1.0 이상 2.0 이하의 최신 버전을 설치해야합니다.

이렇게하면 이 pod를 설치할 때 최신 버그 수정 및 기능을 사용할 수 있지만 실수로 이전 버전과 호환되지 않는 변경 사항은 가져 오지 않습니다.

사용할 수있는 다른 연산자도 몇 가지 있습니다. 전체 목록은 Podfile Syntax Reference를 보세오.

CocoaPod를 사용하는 방법을 배웠으므로 이제 앱을 완성해야합니다.

 

진행률 표시

당신이 기억한다면, 앱에 플레이버가 로딩 될 때 사용자에게 보여주기위한 진행 표시기를 만들고있는 것입니다.

이 기능을 마치려면 PickFlavorViewController.swift 로 돌아가서 다른 import 후에 다음을 추가하십시오.

import MBProgressHUD

다음으로 loadFlavors() 뒤에 다음 헬퍼 메소드를 추가하십시오:

private func showLoadingHUD() {
  let hud = MBProgressHUD.showAdded(to: contentView, animated: true)
  hud.label.text = "Loading..."
}

private func hideLoadingHUD() {
  MBProgressHUD.hide(for: contentView, animated: true)
}

이제 loadFlavors()에서 다음 두 줄을 추가하십시오 (표시된대로):

private func loadFlavors() {
    showLoadingHUD() // <-- Add this line
    
    Alamofire.request(
      "https://www.raywenderlich.com/downloads/Flavors.plist",
      method: .get,
      encoding: PropertyListEncoding(format: .xml, options: 0))
        .responsePropertyList { [weak self] response in
        guard let self = self else { return }
        
        self.hideLoadingHUD() // <-- Add this line
      // ...

메소드 이름에서 알 수 있듯이 showLoadingHUD()는 GET 요청이 다운로드되는 동안 MBProgressHUD의 인스턴스를 표시합니다. hideLoadingHUD()는 요청이 완료되면 HUD를 숨깁니다. showLoadingHUD()가 클로저 외부에 있으므로 self 접두사(prefix)가 필요하지 않습니다.

빌드하고 실행하십시오. 플레이버가 로딩되는 동안 로딩 표시기가 나타납니다. 인터넷 연결이 너무 빠르면 hideLoadingHUD() 직전에 sleep(_:) 문을 추가하여 MBProgressHUD라는 장점을 경험할 수 있습니다. :]

https://koenig-media.raywenderlich.com/uploads/2017/04/HUD_Loading-281x500.png

Great work! 고객은 이제 좋아하는 아이스크림 맛을 선택할 수 있으며 맛 다운로드 중에 로딩 표시기가 나타납니다.

 

여기서 어디로 가야합니까?

이 페이지의 상단 또는 하단에 있는 Download Materials 버튼을 사용하여 완성된 프로젝트를 다운로드 할 수 있습니다.

축하합니다! 이제 의존성 작성 및 수정, 시맨틱 버저닝에 대한 이해를 포함하여 CocoaPod 사용의 기본 사항을 알게되었습니다. 이제 자신의 프로젝트에서 사용할 준비가 되었습니다!

CocoaPods로 더 많은 것을 할 수 있습니다. 공식 CocoaPods 웹 사이트에서 기존 pod를 검색 할 수 있습니다. 또한 CocoaPods 가이드를 참조하여이 우수한 도구에 대한 자세한 내용을 알아보십시오. 그러나 일단 사용을 시작하면 경고(warn)없이 어떻게 관리했는지 궁금 할 것입니다! :]

내가 작성한만큼 CocoaPods 튜토리얼을 읽는 것이 즐거웠기를 바랍니다. 가장 좋아하는 CocoaPod은 무엇입니까? 일상적인 프로젝트에 가장 의존하는 것은 무엇입니까? 아래의 comments에서 자유롭게 공유하거나 질문하세요!

[Download Materials]