본문 바로가기
iOS/Swift

Creating Swift Packages

by 바등쪼 2023. 6. 7.

https://developer.apple.com/videos/play/wwdc2019/410/

 

Creating Swift Packages - WWDC19 - Videos - Apple Developer

Whether you want to publish code to share with the community, or you just want a convenient way to organize the code in your apps, Swift...

developer.apple.com

목차

 

Creating Local Packages

  • 로컬 패키지는 Xcode workspace의 하위 프로젝트와 유사하다.
  • 플랫폼 독립적이므로 애플의 모든 플랫폼에서 간단한 방식으로 코드를 사용할 수 있다.
  • 재사용 가능한 코드로 리팩토링하기에 좋다.
  • 버저닝되지 않지만 추후에 publish and share 될 수 있다.

Publishing Packages

WWDC의 예시 프로젝트에서는 iOS와 WatchOS에서 사용될 프로젝트가 예시였고 이로 인해 두 프로젝트를 관리해야하는 상황이었다. 두 환경 모두 동일한 모델을 필요로 했는데 이러한 모델 파일을 패키지로 분리하여 활용하는 것이 목표이다.
이번 포스팅에서는 패키지 생성 과정을 알아보는 것이 목적이기 때문에 워치앱 타겟은 생략하고 정리하겠습니다!

Xcode에서 File -> New -> Package를 클릭해서 원하는 이름의 패키지를 생성할 수 있다.

하단에 Add to와 Group에서 원하는 프로젝트와 그룹을 선택할 수 있다.

패키지를 생성하면 위의 사진처럼 Xcode가 자동으로 패키지에 필요한 파일들을 생성해준다.

 

우리가 만든 패키지가 필요한 프로젝트에서 Targets에서 패키지 추가를 원하는 타겟을 클릭하고 하단에 있는 Frameworks, Libraries, and Embedded Content에 방금 생성한 라이브러리를 추가한다. (패키지에 생성한 코드들은 public이나 open로 접근 제한자를 설정해야 해당 패키지에 의존하는 다른 모듈에서 정상적으로 사용이 가능하다.⭐️)

MyPackage가 추가된 모습

Semantic Versioning

 

Xcode에서 이전에 생성한 패키지를 옵션을 누른 상태로 다른 디렉토리로 드래그 앤 드롭하면 동일한 패키지가 복사가 돼서 생성된다.

빌드 가능한 기기 목록을 보면 다양한 애플 생태계의 OS들이 있는 것을 확인 할 수 있다 ➡️ Package Independent

 

준비된 Test 파일에서 위와 같이 테스트 코드를 작성하고 Command + U 단축키로 테스트를 실행할 수 있다.

 

이제 깃 레포지토리를 생성해 보자!

로컬 경로에 Git Repository가 생성된 모습

Remote 저장소도 생성 가능하다.

깃허브에 Remote 저장소가 생겼다!

버저닝 역시 Xcode에서 할 수 있다. ➡️ Tag로 버전을 관리한다.

Tag 생성 (Semantic Versioning에 부합하는 버전으로 기입)

여기까지만 하면 Local에만 버전이 생성된 것이기 때문에 반드시 Push 까지 해주기!

Include tags를 체크하자
버전 정보가 GitHub에도 올라갔다..!

다시 앞서 만들고 있던 프로젝트로 돌아와서

로컬에 생성했던 패키지를 삭제하자!

이제는 원격 저장소에 있는 패키지를 사용할 차례이다..!

다른 써드파티 라이브러를 사용하듯이 깃허브에서 라이브러리 주소를 복사하고

Xcode에서 SwiftPackage를 추가할 때 붙여넣으면 위와 같이 내가 업로드한 패키지를 Xcode가 찾아서 프로젝트에 추가할 수 있도록 도와준다.

패키지가 잘 추가된 모습

패키지를 import하면 해당 패키지에 있는 FoodModel도 사용이 가능해진다!

(패키지에서 FoodModel이 public으로 선언되어 있어야 호출이 가능하다.)

 


Package Manifest API

Package Manifest File(Package.swift)의 구성에 대해 알아보자

  • Manifest의 첫 줄은 항상 Swift tools version이다. (패키지를 빌드하기 위해 필요한 Swift 컴파일러의 최소 버전)
  • import PacakgeDescription ➡️ 매니페스트 파일을 사용하는 API를 포함하는 Xcode에서 제공하는 라이브러리 
  • Package Init Statement
    • 전체 패키지는 단일 패키지 Initializer 구문을 사용하여 구성된다.
    • 위의 경우, 패키지의 이름만 기입했다. (이것 자체가 Target이 된다.)
  • Swift 패키지들은 Targets에 대한 표준 레이아웃이 있다.

  • 라이브러리 타겟은 "Sources"라는 이름의 디렉토리 아래에 있어야 한다.
  • 각 타겟은 자체 하위 디렉토리를 가져야 한다.
  • 위의 사진처럼 Package Init문의 targets 파라미터로 선언된다.
  • 표준 레이아웃은 소스 파일을 매니페스트에 개별적으로 나열할 필요가 없기 때문에 매우 편리하다.
    • 우리는 해당 소스 파일들을 올바른 디렉토리에 놓기만 하면 Xcode가 자동으로 그것들을 픽업한다.
  • 다른 타겟을 추가하려면 새로 하위 디렉토리를 만들고 매니페스트 파일에 Target을 선언한다.

  • 테스트 타겟은 "Tests"라는 디렉토리 아래에 만들어야 한다.
  • 테스트 타겟 API를 사용하여 선언되면 테스트 타겟은 일반적으로 다른 타겟을 테스트 하기 때문에 테스트 당할 타겟에 대한 디펜던시를 위의 사진과 같이 선언해야 한다.

  • 마지막으로 패키지에 대한 Products를 선언해야 한다.
  • Product는 다른 패키지가 타겟을 사용할 수 있도록 패키지에서 대상을 export하는 데 사용된다.
  • 위의 사진의 경우에는 단일 라이브러리 타겟을 export하는 라이브러리 Product이다.

 

Adding support in existing projects

CocoaPods과 Carthago와 같은 다른 패키지 관리자들을 사용하고 있던 Menu Downloader라는 예시 프로젝트에 SwiftPackage를 적용해 보자!

이 프로젝트는 Swift Targets, 일부 레거시 C 코드, Xcode 프로젝트 파일 및 코코아 팟 패키지 관리작 사용하는 PodSpec 파일이 있다.

  • 제일 먼저 package.swift 매니페스트 파일을 추가하자!

  • 레거시 C 코드부터 시작해서 먼저 이름을 정하고 사용자 지정 path를 지정한다. (이 타겟이 표준 소스 디렉토리 아래에 없기 때문에 이 작업을 수행해야 한다.)
  • C 코드에 비밀 점심 메뉴를 정의하면 다운로드 하는 매크로가 있다고 가정하면 위와 같이 C Settings API를 사용하여 정의한다.

  • Swift 타겟은 마찬기지로 사용자 경로를 지정하고 레거시 C 타겟에 대한 디펜던시를 선언하여 구성할 수 있다.

  • 이 패키지에는 두 가지 Product가 있다.
    • 첫 번째 Product는 Swift Target을 export한다.
    • 두 번째 Product는 C 타겟을 export한다.
  • 우리는 C 타겟을 사용하는 사용자가 있을 수 있고 그 경우 Swift 브릿지가 필요하지 않을 수 있기 때문에 C 타겟을 따로 내보낸다.
  • 일부 사용자가 두 번째 Product를 사용할 때 Load 하는 것을 지원하기 위해 dynamic 라이브러리로 선언한다.

 

Package Dependencies

  • Package의 디펜던시는 위의 사진과 같이 선언된다.
  • 소스 URL과 버전 정보를 포함한다.

버전을 표기하는 다양한 방법들
non-version requirements

  • non-version requirements는 여러개의 develop 패키지를 개발하고 싶고 그것들을 sync하고 싶을  때 유용하다.
  • 하지만, 패키지를 publish 하기 전에 non-version requirements는 제거해야 한다.

  • 우리가 만든 타겟에 앞서 디펜던시로 불러온 "Yams" 타겟을 디펜던시로 추가하여 사용한다.

  • 다른 API와 마찬가지로 PackageDescription API도 시간이 지남에 따라 발전한다.
  • 이것은 디펜던시 Resolution 프로세스에도 참여한다.
  • Xcode는 모든 패키지 종속성의 Tools 버전이 패키지의 Tools 버전과 항상 호환되도록 한다.
  • 또한, 패키지를 빌드하는 데 필요한 Swift 컴파일러의 최소 버전을 선언한다.

  • 패캐지가 여러 플랫폼을 지원하고 플랫폼 별 코드를 가지고 있다면 Swift의 조건부 컴파일 기능을 사용할 수 있다.
  • 또한 플랫폼의 start support availability를 위해 Xcode는 각 플랫폼에 대한 기본 배포 타겟을 할당한다.

  • 패키지 init 문의 플랫폼 섹션에서 배포 타겟을 사용자 지정할 수 있다.

Editing Packages

패키지 디펜던시는 Xcode에 의해 자동으로 관리되기 때문에 편집이 잠겨있다.

패키지를 독립시켜 체크아웃하고 프로젝트에 로컬 패키지로 추가하면 패키지를 제거하지 않고 기존 디펜던시를 재정의 할 수 있다.

  • remote 디펜던시를 제거하고 다시 드래그앤 드랍으로 로컬 패키지로 옮긴다.

이제 패키지에 있는 코드를 내가 원하는 대로 수정할 수 있다.

 

재정의를 사용하여 소유하지 않은 패키지를 편집할 수 있다.

Open Source Projects

  • Swift는 크로스 플랫폼 언어이고 SwiftPM은 크로스 플랫폼 빌드 시스템이다.

  • 물론 Xcode Build를 사용하여 command line이나 CI에서 패키지를 빌드 할 수 있다.

  • Xcode의 Swift 패키지 지원은 오픈 소스 프로젝트의 일부인 libSwift 위에 구축된다.
  • libSwiftPM은 Swift 패키지 및 IDE용 기타 개발자 도구를 지원하는 데 사용할 수 있다.
  • Swift Package는 오픈 소스이기 때문에 누구나 기여할 수 있다.

 

'iOS > Swift' 카테고리의 다른 글

Swift의 분산된 Actor 소개  (0) 2023.08.22
Adopting Swift Packages in Xcode  (0) 2023.06.14
Getting to Know Swift Package Manager  (0) 2023.05.28
Swift의 디자인 프로토콜 인터페이스  (0) 2023.04.27
ARC in Swift: Basics and beyond  (0) 2023.04.13

댓글