누군가에게 알려주기 보다는 나 스스로 정리 하며 언젠가 다시 사용할 때를 대비하는 글을 작성할것이다.
CocoaPods 이나 Carthage 같은 서드파티툴 처럼 종속성 관리를 위한 기능이다.
단, Apple의 공식 지원이 된다는게 중요하다.
아직도 사용하는 라이브러리 중에서도 SPM 지원 안하는 라이브러리들이 있어서 CocoaPods도 사용하기는 하는데 설치를 하게 되면 .xcodeproj 파일 말고 새로운 .xcworkspace 파일이 생겨서 해당 파일로 작업하지 않으면 라이브러리를 사용할 수 없다던가 하는 이슈가 있어서 정말 싫어한다.
그럼에도 점차 많은 라이브러리들이 SPM을 지원하고 있고 지원할 예정이라 처음부터 SPM으로 하기로 가닥을 잡았다.
// swift-tools-version: 5.8
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "SunBase",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "SunBase",
targets: ["SunBase"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "SunBase",
dependencies: []),
.testTarget(
name: "SunBaseTests",
dependencies: ["SunBase"]),
]
)
처음 생성된 파일을 들어가서 보게 되면 다음과 같은 코드가 작성되어있는것을 볼 수 있다.
하나하나 확인해보자
1. swift-tools-version: 해당 버전은 패키지를 빌드 하는데 필요한 Swift 컴파일러의 최소 버전
이다.
2. import PackageDescription: manifest 파일이 패키지 생성하는데 사용할 API포함하고 있다.
3. name: 라이브러리명을 따라 간다.
4. product: 라이브러리의 패키지를 정의해준다. 해당 패키지로부터 어떠한 타겟을 보여주고 다른 패키지에서 사용 할 수 있도록 해준다.
targets 파라미터는 다수의 타겟 선언이 가능하고 하나의 라이브러리로 여러 타겟 노출도 가능하다.
5. dependencies: 현재 패키지에서 사용하고 있는 다른 Package들을 명시한다.
.package(url:"링크링크", from: "1.0.0")
6. targets: 기본 빌드 단위
- target: 패키지는 target 에 대한 표준 구조를 가진다. Sources 디렉터리에 타겟의 모든 파일이 위치하고, 각 타겟은 타겟 이름과 동일한 이름으로 하위에 위치한다.
- targetTest: Tests 디렉터리 아래 위치하고, 다른 타겟을 테스트 하기에 dependencies 선언해야 한다.
처음 설정된 구조에는 Scources 디렉터리에 하나의 파일만 있었기에 타겟이 하나만 있어도 괜찮았지만 NewSunBase
라는 타겟을 더 추가하기 위해서는 다음과 같이 작성을 해줘야 한다.
targets: [
.target(
name: "SunBase",
dependencies: []),
.target(
name: "NewSunBase",
dependencies: []),
]
products: [
.library(
name: "SunBase",
targets: ["SunBase"]),
.library(
name: "NewSunBase",
targets: ["NewSunBase"]),
],
그리고 Sources 디렉터리 밑에 NewSunBase디렉터리를 만들고 밑에 .swift 파일을 만들어서 구현해야 한다.
이렇게 기능 별로 분리해서 여러 개의 product를 배포했을 경우, 사용자가 패키지 설치할 때 어떤 모듈을 사용할지 선택 할 수 있다.
//RxSwift 의 Package.swift 파일 중 일부
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 },
주의 사항
패키지생성 시에 하단부에 Source Control 에
Create Git repository on my Mac
의 체크박스가 활성화 되어 있는지 확인
위에 적힌것들을 잘 따라서 패키지를 만들었으면 Xcode의 Source Control Navigator 영역
으로 이동한다.
좌측에 있는 영역인데 도저히 모르겠다면 Xcode 아무 곳이나 클릭하고 command + 2
를 누르면 왼쪽에 떠있는 영역이 바뀌는것을 볼 수 있다.
해당 영역에서 상단에 보면 Repositories
라는 곳이 있는데 해당 부분으로 이동한다. (난 여기서 직접 보면서 하는게 편하다)
2로 이동한 영역 아무 곳에서 우클릭
후 New "git" Remote
라고 쓰인 버튼을 누른다. 내부의 "git" 부분은 각자 설정마다 다르므로 New ~~~ Remote
버튼을 누르면 된다.
그러면 무슨 창이 뜨게 되는데 GitHub에 대해서 너무 잘 알아서 이것저것 다 잘 알아서 수정해도 상관없다면 모르겠지만 그런게 아니라면 다 그대로 놔두고 중간에 Repository Name
항목만 바꿔준다.
git 이름이 될 부분이니까 원하는 데로 바꿔서 하단의 Create 를 눌러주면 된다.
잠시 기다리면 배포 끝
git tag
로 패키지의 버전을 관리하기에 패키지의 버전 관리를 하고 싶다면 tag도 생성해줘야 한다.repository URL
을 입력하면 패키지를 사용할 수 있다.당연 틀린 부분 지적은 감사하나 비난은 정중하게 사양하겠다.