iOS

Swift Package 의존성 추가, 생성, 배포 방법

Phililip
728x90

안녕하세요.

 

이번에는 Swift Package Manager를 사용해서 dependency 추가하는 방법과, Swift Package를 직접 만들고 배포하는 방법에 대해 알아볼게요.

 


 

# 1. Swift Package Manager로 패키지 설치

Swift Package Manager는 애플에서 제공하는 dependency manager입니다. (줄여서 SPM이라고도 부릅니다.)

 

SPM으로 패키지를 어떻게 설치하고 관리하는지 알아볼게요.

 

 

## 1.1 dependency 추가

Xcode > 프로젝트 Target > Package Dependencies로 이동합니다.

 

 

 

 

+ 버튼을 클릭하면 패키지를 추가할 수 있는 화면이 나옵니다. 추가할 패키지의 repo URL을 입력하고 Add Package 버튼을 눌러주세요.

 

 

 

 

추가한 패키지들의 정보는 swiftpm 폴더 안에 있는 Package.resolved 파일에서 확인이 가능합니다.

 

{
  "object": {
    "pins": [
      {
        "package": "Time",
        "repositoryURL": "https://github.com/davedelong/time.git",
        "state": {
          "branch": null,
          "revision": "be6cbbbb97aa4570e3b51bd56f98ca3cf62aa3cb",
          "version": "0.9.2"
        }
      }
    ]
  },
  "version": 1
}

 

 

 

## 1.2 패키지 저장 위치

패키지는 Xcode 프로젝트 내부가 아닌 DerivedData에 추가됩니다.

 

간혹 DerivedData를 지우는 경우가 있는데요, 이런 경우에는 패키지도 함께 제거되기 때문에 패키지를 다시 불러와야 합니다.

 

 

 

## 1.3 패키지 관리

Xcode에서는 패키지 관리를 위해 총 3가지 동작을 지원합니다.

 

 

Reset Package Caches

  - DerivedData에 있는 피키지 캐시를 삭제하고 패키지를 다시 불러옵니다.

 

Resolve Package Versions

  - Package.resolved 파일에 명시되어 있는 패키지 정보를 토대로 패키지를 강제로 다시 불러오니다.

 

Update to Latest Package Versions

  - 최신 버전으로 패키지를 업데이트시킵니다.

 

 

 

# 2.Swift Package 만들어보기

이번에는 Swift Package를 직접 만들어볼게요ㅎㅎ

 

 

## 2.1 Swift Package 프로젝트 생성

Xcode > File > New > Package를 선택하면 Swift Package 프로젝트가 만들어집니다.

 

 

 

## 2.2 프로젝트 구조

 

 

 

 

## 2.3 Package.swift

Package.swift 파일은 패키지 이름, 외부 의존성 등 패키지에 대한 정보를 가지고 있습니다.

 

import PackageDescription

let package = Package(
    name: "MyPackage",
    products: [
        .library(
            name: "MyPackage",
            targets: ["MyPackage"]),
    ],
    dependencies: [
        // .package(url: /* package url */, from: "1.0.0"),
    ],
    targets: [
        .target(
            name: "MyPackage",
            dependencies: []),
        .testTarget(
            name: "MyPackageTests",
            dependencies: ["MyPackage"]),
    ]
)

 

 

## 2.4 Package.swift > dependencies

dependencies에 아래처럼 의존성을 추가하면 SPM이 알아서 외부 모듈을 패키지에 추가해줍니다.

 

dependencies: [
    // Dependencies declare other packages that this package depends on.
    .package(url: "https://github.com/apple/swift-algorithms.git", from: "1.0.0"),
],

 

 

 

## 2.5 Package.swift > targets

패키지 안에서도 기능별로 별도의 모듈을 분리할 수 있습니다.

 

Sources 안에 별도 모듈을 위한 폴더와 코드가 있어야 합니다.

 

 

 

예를 들어서, 아래처럼 Target1 이란 타겟을 추가할 경우, Sources/Target1 폴더를 따로 생성해줘야 하는 것이죠.

 

또한, target 마다 별도의 dependencies를 추가해줄 수 있습니다.

 

targets: [
    .target(
        name: "MyPackage",
        dependencies: [
            .product(name: "Algorithms", package: "swift-algorithms")
        ]),
    .target(
        name: "Target1",
        dependencies: []),
    .target(
        name: "Target2",
        dependencies: ["MyPackage"]),       // 타겟에 의존성 추가
]

 

 

 

 

 

## 2.6 Package.swift > products

target을 추가했다고 해서 사용자가 쓸 수 있는 것은 아닙니다.

 

target을 product의 library 타입으로 정의를 해줘야지 배포 후 사용자가 쓸 수 있게 됩니다.

 

products: [
    .library(
        name: "MyPackage",
        targets: ["MyPackage"]),
    .library(
        name: "Library1",
        targets: ["Target1"]),
],

 

 

 

기능 별로 분리해서 여러 개의 product를 배포했을 경우, 사용자가 패키지를 설치할 때 어떤 모듈을 사용할지 선택할 수 있습니다.

(아래는 RxSwift의 Package.swift 파일과 사용자 화면 예시입니다ㅎㅎ)

 

...
let package = Package(
  name: "RxSwift",
  platforms: [.iOS(.v9), .macOS(.v10_10), .watchOS(.v3), .tvOS(.v9)],
  products: ([
    [
      .library(name: "RxSwift", targets: ["RxSwift"]),
      .library(name: "RxCocoa", targets: ["RxCocoa"]),
      .library(name: "RxRelay", targets: ["RxRelay"]),
      .library(name: "RxBlocking", targets: ["RxBlocking"]),
      .library(name: "RxTest", targets: ["RxTest"]),
      .library(name: "RxSwift-Dynamic", type: .dynamic, targets: ["RxSwift"]),
      .library(name: "RxCocoa-Dynamic", type: .dynamic, targets: ["RxCocoa"]),
      .library(name: "RxRelay-Dynamic", type: .dynamic, targets: ["RxRelay"]),
      .library(name: "RxBlocking-Dynamic", type: .dynamic, targets: ["RxBlocking"]),
      .library(name: "RxTest-Dynamic", type: .dynamic, targets: ["RxTest"]),
    ],
    Product.allTests()
  ] as [[Product]]).flatMap { $0 },
  ...
)

 

 

 

 

# 3. Swift Package 배포하기

패키지를 만들었으면 배포를 해야겠죠??

 

public package와 private package 배포하는 방법에 대해 알아볼게요.

 

 

## 3.1 Public Package 배포

swift package 프로젝트 생성할 때 Create Git repository on my Mac을 체크하고 생성해주세요ㅎㅎ

 

 

 

 

Github로 가서 배포할 repository를 만들어줍니다. 이때 README, gitignore, license는 선택하지 않도록 주의해주세요!!

 

 

 

 

swift package 프로젝트에서 개발을 하고 Package.swift 파일 작성 후에 커밋해주세요.

 

그다음에 아래 명령어를 사용해서 방금 생성한 repository로 푸시해주시면 됩니다.

 

 

 

 

Package Dependencies로 돌아가서 방금 생성하고 푸시한 repository URL을 입력하면 패키지를 사용할 수 있습니다.

 👍 👍 👍

 

 

 

## 3.2 Private Package 배포

Github에서 repository를 private으로 만들어주는 것을 제외하고는 public package 배포 프로세스와 똑같아요.

 

 

다만, private이기 때문에 패키지를 사용하려면 Xcode에 Github 계정을 등록해줘야 합니다.

(private repo에 접근이 가능한 계정인지 알기 위해서이죠)

 

 

Xcode > Preferences > Accounts로 가서 Github 계정과 AccessToken을 등록해줍니다.

 

등록 후 결과화면

 

 

 

배포 끝!!

 

 

 

 

## 3.3 버전 관리

SPM은 git tag로 패키지의 버전을 관리해요.

 

그래서 swift package의 버전을 관리하고 싶다면, 작업 후에 tag도 생성해주세요.

 

 

 

## 참고

- https://tiagolopes.blog/2022/01/09/spm-basics/

- https://tiagolopes.blog/2022/01/16/the-structure-of-a-swift-package/

- https://tiagolopes.blog/2022/01/23/publishing-swift-packages/

- https://github.com/ReactiveX/RxSwift

 

 

 


 

이번 글은 여기서 마무리.

 

 

 

 

 

반응형

'iOS' 카테고리의 다른 글

[오픈소스] Bagbutik  (0) 2022.03.28
mailto scheme과 기본 메일 앱 설정  (0) 2022.03.23
TabulaData framework  (0) 2022.03.09
[오픈소스] CustomDump 소개  (0) 2022.02.24
SceneDelegate를 제거하는 방법  (0) 2022.02.05