안녕하세요!
프로젝트를 개발하다보면 상황 별로 빌드 결과물을 바꾸고 싶은 경우가 있습니다.
예를들어 출시용 빌드의 경우 특정 설정값을 빌드세팅에 지정해야 하는 경우가 있습니다.
모든 경우를 매번 Xcode의 빌드 세팅에 접근하여 일일히 수정하는 것은 매우 귀찮은 작업이며
설정값이 많아질 경우 협업에 참여하는 모든 개발자가 일관성을 유지하기 힘들어 집니다.
Tuist를 사용하는 경우 별도의 설정없이 tuist generate명령어를 사용하여 프로젝트를 다시 생성하면
이전에 설정했던 빌드세팅이 모두 기본값으로 초기화되기에 해당 문제는 더욱 심각해집니다.
해당 포스팅은 스킴을 통해 빌드세팅을 분기처리하는 방법과
그것을 Tuist를 사용해 명시적인 Swift코드로 남겨
협업에 참여하는 개발자들이 일관된 빌드환경을 유지하는 방법에 대해 소개합니다.
기본적인 지식 정리
우선 빌드 환경을 조성하기 위한 개념들을 정리하겠습니다.
Build setting
빌드 세팅은 특정 타겟을 빌드하기 위한 정버로 키-벨류 형태로 값이 설정되어 있습니다.
Xcconfig
Xcconfig파일은 빌드세팅 값을 수정할 수 있는 파일로 키-벨류 형태로 구성되 있습니다.
예를들어 Swift옵니마이제이션 레벨을 Xcconfig로 수정해보겠습니다.
해당 Xcconfig파일을 기본 Debug Configuration에 지정해 보겠습니다.
SWIFT_OPTIMIZATION_LEVEL = -OSize
자동으로 빌드세팅이 수정된 것을 확인할 수 있습니다.
Xcconfig는 Configuration과 함께 동작합니다.
(Build)Configuration
Configuration은 빌드 세팅을 분기시키는 요소들입니다. 흔히 알려진 Debug, Release가 바로 Configuration입니다.
Configuration은 2가지 타입이 존재합니다. debug, relase입니다.
2가지 타입을 바탕으로 유저는 새로운 Configuration을 추가할 수 있습니다.
Q: 왜 Configuration은 2가지 타입으로부터 파생되야하는 것일까요?
빌드세팅값은 매우 많은 설정을 가지고 있습니다. Xcode는 기본적으로 debug, release라는 두가지 Configuration에 따라 이미 많은 값들을 지정했습니다.
여기서 새로운 Configuration을 생성하면 많은 세팅값들에서 새로운 Config에 대한 값을 일일히 지정해야합니다.
힘든 작업이기에, Xcode는 값이 설정되어 있는 debug, relase를 그대로 복사하여 Configuration을 생성하는 방식을 제시합니다. 복사된 새로운 Configuration에서 변경이 필요한 부분만 수정해주면 됩니다!
스킴
스킴은 특정타겟 혹은 특정 프로젝트에 속한 타겟들의 빌드환경을 최종적으로 구성하는 역할을 합니다.
스킴을 통해서 Configuration을 선택하여 빌드세팅 혹은 info.plist에 적용할 수 있습니다.
Configuration뿐만아니라 빌드과정에서 환경 변수등 여러가지 값들을 최종적으로 확정합니다.
Q: Build Action이 아니라 왜 Run Action에 Configuration을 지정하는 거죠?
Run, Test, Profiile 등의 액션들은 빌드를 진행한 후에 동작들 입니다.
첫번째 이유는 동작들에 따라서 사용할 빌드 환경을 분기하기 위해서입니다.
빌드액션은 단지 해당 액션들을 시행하기전 어떤 타겟들을 빌드할지 정도만 결정합니다.
Q: Cmd + B를 할경우 그럼 어떤 Configuration을 사용하나요 설정된 Config가 없는데요?
이 경우 Run action의 Configuratuin을 따릅니다.
실습: 스킴별로 API Key를 변경하기
스킴을 통해 빌드세팅값(API키)을 변경시키고 그것을 Info.plist로 불러들여 코드에서 출력하는 실습을 해보겠습니다.
(실제로 API키를 info.plist에 저장하는 것은 부적절합니다, 실습으로만 봐주세요! API관리 관련된 글)
같은 코드라도 스킴별로 서로다른 값을 출력하는 것이 목표입니다.
먼저 Xcode를 통해 진행한 후 이것을 Tuist로 옮겨 보겠습니다.
먼저 Debug, Release, Test Configuration을 생성하고 각각의 Config에 서로다른 Xcconfig파일을 할당해보줍니다.
Xcconfig파일의 내용은 아래와 같습니다.
TEST_API_KEY = ..._key
아래와 같이 기존에 존재하지 않는 키값에 대해서는 빌드세팅의 User-Defined영역에서 관리됩니다.
해당 값들을 info.plist로 불러들이겠습니다.
info.plist로 가져오는 이유는 코드레벨에서 해당값에 접근하기 위해서 입니다.
(빌드세팅값에는 직접 접근할 수 없음)
Configuration별로 스킴을 생성하고 일치하는 Configuration을 할당해줍니다.
스킴을 바꿔가면 출력해보면 다음과 같은 결과를 얻을 수 있습니다.
if let api_key = Bundle.main.infoDictionary?["Api_key"] {
print(api_key)
}
Test스킴: Test_key
Debug스킴: Debug_key
Release스킴: Release_key
여기까지 내용을 다음 프로젝트 파일입니다.
이제 해당 내용을 Tuist로 설정해 봅시다!
Tuist로 미그레이션 하기
해당 실습은 Tuist 4.38.2버전을 사용했습니다.
먼저 Configuration을 생성하고 적절한 Xcconfig파일을 할당합니다.
※ 프로젝트의 스킴에서 Configuration을 사용하려면 프로젝트 레벨의 세팅(settings)에서 Configuration을 생성해여합니다.
let project = Project(
name: "Tuisttest",
settings: .settings(configurations: [
.release(
name: "Release",
xcconfig: .relativeToRoot("Xcconfigs/release.xcconfig")
),
.debug(
name: "Debug",
xcconfig: .relativeToRoot("Xcconfigs/debug.xcconfig")
),
.debug(
name: "Test",
xcconfig: .relativeToRoot("Xcconfigs/test.xcconfig")
),
]),
targets: [
.target(
name: "Tuisttest",
destinations: .iOS,
product: .app,
bundleId: "io.tuist.Tuisttest",
infoPlist: .extendingDefault(with: [
"Api_key" : "$(TEST_API_KEY)"
]),
sources: ["Tuisttest/Sources/**"],
resources: ["Tuisttest/Resources/**"],
dependencies: []
),
]
)
info.plist에 해당 값을 가져오는 코드를 추가합니다.
let project = Project(
name: "Tuisttest",
settings: .settings(configurations: [
...
]),
targets: [
.target(
name: "Tuisttest",
destinations: .iOS,
product: .app,
bundleId: "io.tuist.Tuisttest",
infoPlist: .extendingDefault(with: [
"Api_key" : "$(TEST_API_KEY)"
]),
sources: ["Tuisttest/Sources/**"],
resources: ["Tuisttest/Resources/**"],
dependencies: []
),
]
)
다음으로는 스킴을 설정합니다.
스킴의 Run action에 사용하려는 Configuration을 설정합니다.
let project = Project(
name: "Tuisttest",
settings: .settings(configurations: [
...
]),
targets: [
.target(
name: "Tuisttest",
destinations: .iOS,
product: .app,
bundleId: "io.tuist.Tuisttest",
infoPlist: .extendingDefault(with: [
"Api_key" : "$(TEST_API_KEY)"
]),
sources: ["Tuisttest/Sources/**"],
resources: ["Tuisttest/Resources/**"],
dependencies: []
),
],
schemes: [
.scheme(
name: "Tuisttest_Debug",
buildAction: .buildAction(targets: [
.target("Tuisttest")
]),
runAction: .runAction(configuration: "Debug")
),
.scheme(
name: "Tuisttest_Release",
buildAction: .buildAction(targets: [
.target("Tuisttest")
]),
runAction: .runAction(configuration: "Release")
),
.scheme(
name: "Tuisttest_Test",
buildAction: .buildAction(targets: [
.target("Tuisttest")
]),
runAction: .runAction(configuration: "Test")
),
]
)
자 이제 모든 설정은 완료했습니다.
tuist generate를 통해 프로젝트를 생성해봅시다.
Tuist에서 기본적으로 생성하는 스킴과 커스텀 스팀이 모두 잘 생성된 것을 확인할 수 있습니다.
Release스킴을 설정후 실행보겠습니다.
잘 출력되는 것을 확인할 수 있습니다.
실습을 진행한 프로젝트 파일입니다.
긴 글 읽어주셔서 감사합니다. ☺️ ☺️
'Tuist' 카테고리의 다른 글
[Xcode] 프로젝트 모듈화 개념 정리(with Tuist) (1) | 2023.11.13 |
---|