제가 이해하고 공부 한대로 작성한 내용이다 보니 , 정확한 정보가 아닐수도 있습니다
고쳐야 할 부분이 있다면 , 편하게 애기 해주시면 감사 하겠습니다🙏🏻
Package.swift, Plugin, 그리고 Firebase 설정까지 한 번에 정리하기
대규모 iOS 프로젝트에서는 모듈화와 함께 외부 라이브러리 관리가 필수입니다.
Tuist를 사용하면 Swift Package Manager(SPM)를 기반으로 일관된 방식으로 의존성을 선언하고, 각 모듈에 깔끔하게 주입할 수 있습니다.
이번 글에서는 아래 내용을 정리합니다:
Package.swiftTuist는 외부 SPM 의존성을 Plugin/DependencyPackagePlugin/Package.swift 파일에서 선언합니다.
@preconcurrency import PackageDescription
#if TUIST
@preconcurrency import ProjectDescription
let packageSettings = PackageSettings(
productTypes: [
"FirebaseCore": .staticLibrary,
"FirebaseAuth": .staticLibrary,
"FirebaseFirestore": .staticLibrary,
"FirebaseAnalytics": .staticLibrary,
"FirebaseCrashlytics": .staticLibrary,
"FirebaseRemoteConfig": .staticLibrary
]
)
#endif
let package = Package(
name: "DDDAttendance",
dependencies: [
.package(url: "https://github.com/firebase/firebase-ios-sdk", from: "10.27.0"),
.package(url: "https://github.com/pointfreeco/swift-composable-architecture", exact: "1.18.0"),
.package(url: "https://github.com/pointfreeco/swift-concurrency-extras.git", from: "1.1.0"),
.package(url: "https://github.com/apple/swift-collections.git", branch: "main"),
.package(url: "https://github.com/johnpatrickmorgan/TCACoordinators.git", exact: "0.11.1"),
.package(url: "https://github.com/Roy-wonji/AsyncMoya", from: "1.1.0"),
.package(url: "https://github.com/Roy-wonji/DiContainer.git", from: "1.0.8")
]
)
staticLibrary로?Firebase는 모듈 간 동적 링크 이슈로 인해, 정적 라이브러리(staticLibrary) 설정이 권장됩니다.
Tuist에서는 PackageSettings를 사용하여 아래와 같이 지정할 수 있습니다:
let packageSettings = PackageSettings(
productTypes: [
"FirebaseCore": .staticLibrary,
"FirebaseAuth": .staticLibrary,
"FirebaseFirestore": .staticLibrary,
"FirebaseAnalytics": .staticLibrary,
"FirebaseCrashlytics": .staticLibrary,
"FirebaseRemoteConfig": .staticLibrary
]
)
💡 #if TUIST는 Tuist 환경에서만 활성화되며, Xcode에서는 무시됩니다.
이것도 markdown 으로
패키지를 선언한 뒤에는 각 라이브러리를 enum으로 정리해서
모듈에서 직관적으로 사용할 수 있도록 만드는 것이 좋습니다.
Plugin/DependencyPackagePlugin/ProjectDescriptionHelpers/Extension+TargetDependencySPM.swift:
import ProjectDescription
public extension TargetDependency {
enum SPM {}
}
public extension TargetDependency.SPM {
static let asyncMoya = TargetDependency.external(name: "AsyncMoya", condition: .none)
static let diContainer = TargetDependency.external(name: "DiContainer", condition: .none)
static let composableArchitecture = TargetDependency.external(name: "ComposableArchitecture", condition: .none)
static let tcaCoordinator = TargetDependency.external(name: "TCACoordinators", condition: .none)
static let concurrencyExtras = TargetDependency.external(name: "ConcurrencyExtras", condition: .none)
static let collections = TargetDependency.external(name: "Collections", condition: .none)
}
이제 각 모듈의 Project.swift 파일에서 아래처럼 간단하게 사용할 수 있습니다:
dependencies: [
.SPM.composableArchitecture,
.SPM.diContainer,
.SPM.asyncMoya
]
| 라이브러리 | 설명 |
|---|---|
| ComposableArchitecture | 상태 기반 아키텍처(TCA) |
| ConcurrencyExtras | LockIsolated 등 Swift Concurrency 확장 |
| Collections | Deque, OrderedSet 등 고성능 컬렉션 |
| TCACoordinators | TCA 기반 화면 전환 관리 |
| AsyncMoya | async/await 기반 Moya wrapper |
| DiContainer | 자체 DI 프레임워크 |
Tuist를 활용한 외부 의존성 관리는 다음과 같은 이점을 가집니다:
| 항목 | 내용 |
|---|---|
| 일관된 선언 방식 | Plugin/DependencyPackagePlugin/Package.swift에서 SPM 패키지를 통합 선언하여, 모든 외부 의존성을 한 곳에서 관리할 수 있습니다. |
| Firebase 대응 최적화 | Firebase 관련 모듈은 staticLibrary로 설정해 링크 충돌 방지 및 안정성 확보가 가능합니다. 이는 실무에서도 흔히 마주하는 문제이며, 이를 예방할 수 있는 구조입니다. |
| enum 기반 추상화 | .SPM.composableArchitecture처럼 enum 기반으로 추상화함으로써, 오타 없이 직관적인 사용이 가능하며 유지보수도 용이해집니다. |
| 모듈 간 명확한 의존성 주입 | 각 모듈의 Project.swift에서 .SPM.asyncMoya, .SPM.diContainer 등으로 선언 가능하여, 반복되는 의존성 등록 로직을 줄이고 명확성 향상 |
| 테스트와 모듈 재사용성 향상 | 각 의존성이 명시적으로 구분되어 있어, 테스트 대상 분리 및 모듈화에 최적화되어 있습니다. |
다음 글에서는
“Tuist에서 Plugin 만들고 등록하기” 를 주제로 실전 예제를 소개할 예정입니다.