TMI : 디프만 프로젝트에서 배포 환경을
DEV,PRD에 따른 서버 URL 및 테스트 환경을 나눠야 하는 기회가 생겨서 Tuist를 통해 배포 환경을 설정할 수 있는 좋은 기회를 얻게 되었다!! :)
DEV,STAG,PROD 등의 배포 환경을 분리할때 Configuration을 활용하여 세팅 합니다.Configuration은 Debug, Release입니다.Configuration을 통해 특정 배포 환경에 따른 서버 End Point, Base URL, API KEY, Environment Variable을 다르게 설정 할 수 있습니다.저희는 서버
Base URL이DEV,PRD로 구분되어 있기에DEV,PRD배포 환경으로 나눴습니다.
ConfigurationName+Templates.swift를 추가하여 배포 환경에 따른 네이밍을 설정하는 코드를 추가하였습니다..ConfigurationName은 ProjectDescription에서 제공되기에 enum에서 설정해놓은 값Computed Property를 활용하여 설정하였습니다.public enum BuildTarget: String {
case dev = "DEV"
case prd = "PRD"
public var configurationName: ConfigurationName {
return ConfigurationName.configuration(self.rawValue)
}
}
Configuration 역시 ProjectDescription 내부에서 제공되기에 extension을 활용하여 내부에 타입 메서드로 구현된 build 메서드를 사용하여 각 배포 환경에 따라 Configuration을 생성하도록 구현 하였습니다.extension Configuration {
public static func build(_ type: BuildTarget, name: String = "") -> Self {
let buildName = type.rawValue
switch type {
case .dev:
return .debug(
name: BuildTarget.dev.configurationName,
xcconfig: .relativeToXCConfig(type: .dev)
)
case .prd:
return .release(
name: BuildTarget.prd.configurationName,
xcconfig: .relativeToXCConfig(type: .prd)
)
}
}
}
xcconfig File을 추가해야 하며 각 Configuration 설정을 할때 동시에 xcconfig파일의 경로를 알려줘야 합니다.Path를 extenion을 활용하여 내부에 타입 메서드를 별도로 구현하여 relativeToXCConfig 메서드를 구현하였습니다.extension Path {
public static func relativeToXCConfig(type: BuildTarget) -> Self {
return .relativeToRoot("./14th-team5-iOS/XCConfig/\(type.rawValue.lowercased()).xcconfig")
}
}
Tuist에서 third party Library의 의존성을 가져오고 있는 경우에는 Dependencies.swift 파일에서도 Configuration을 추가해야 합니다.Debug, Release를 Configuration으로 제공되고 있기때문에 실제 저희가 Setting한 Configuration을 매칭 시키지 않을 경우 mismatching configurations 오류가 발생 할 수 있습니다.let dependencies = Dependencies(
swiftPackageManager: SwiftPackageManagerDependencies([
.alamofire,
.reactorKit,
.rxSwift,
.snapkit,
.then,
.firebase
],baseSettings: .settings(
configurations: [
.build(.dev),
.build(.prd)
]
)
),
platforms: [.iOS]
)
Scheme는 Build 될때 어떤 Configuration을 사용할지와 Build Target을 할지를 정의 합니다 때문에 Scheme을 만들어서 배포 환경에 따라 run Action, ConfigurationName등을 설정 해줘야 합니다.Scheme 같은 경우 배포 환경 DEV, PRD 값에 맞게 추가를 해줘야 하기 때문에 배포 환경이 2개가 되면 Scheme도 2개를 추가해줘야 합니다.Scheme를 extension을 활용하여 내부에 타입 메서드를 별도로 구현하여 Scheme를 배포 환경에 따라 BuildAction, runAction, archiveAction, profileAction, analyzeAction 등을 세팅하고 생성하는 형식으로 구현 하였습니다.extension Scheme {
public static func makeScheme(_ type: BuildTarget, name: String) -> Self {
let buildName = type.rawValue
switch type {
case .dev:
return Scheme(
name: "\(name)-\(buildName.uppercased())",
buildAction: BuildAction(targets: ["\(name)"]),
runAction: .runAction(configuration: type.configurationName),
archiveAction: .archiveAction(configuration: type.configurationName),
profileAction: .profileAction(configuration: type.configurationName),
analyzeAction: .analyzeAction(configuration: type.configurationName)
)
case .prd:
return Scheme(
name: "\(name)-\(buildName.uppercased())",
buildAction: BuildAction(targets: ["\(name)"]),
runAction: .runAction(configuration: type.configurationName),
archiveAction: .archiveAction(configuration: type.configurationName),
profileAction: .profileAction(configuration: type.configurationName),
analyzeAction: .analyzeAction(configuration: type.configurationName)
)
}
}
}
Scheme, Configuration 등을 Project에 추가하면 Tuist Setting은 끝입니다.extension Project {
public static func makeApp(name: String, target: [Target]) -> Project {
return Project(
name: name,
settings: .settings(
configurations: [
.build(.dev, name: name),
.build(.prd, name: name)
]
),
targets: target,
schemes: [
.makeScheme(.dev, name: name),
.makeScheme(.prd, name: name)
],
additionalFiles: [
"../XCConfig/shared.xcconfig"
]
)
}
}
dev.xcconfig, prd.xcconfig, shared.xcconfig 파일을 하나씩 만들어 줍니다.relativeToXCConfig Method 경로에 맞게 설정을 해야하니 참고 해주시기 바랍니다. -> 만약 다르게 설정하고 싶으면 relativeToXCConfig 수정 하시면 됩니다.OTHER_SWIFT_FLAGS[config=DEV][sdk=*] = $(inherited) -DDEV
OTHER_SWIFT_FLAGS[config=PRD][sdk=*] = $(inherited) -DPRD
#include "../XCConfig/shared.xcconfig"
#include을 사용한 이유는 shared.xcconfig의 코드를 모두 적용하기 위해서 #include "../XCConfig/shared.xcconfig" 추가 하였습니다. 만약 저 코드를 추가하지 않으면 모든 prd.xcconfig, dev.xcconfig에 추가하기 때문에 가독성 측면상 좋지 않겠죠??