일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- struct
- IOS
- UIKit
- type
- Unicode
- interpace
- Method
- Git
- 디자인패턴
- enum
- url
- 이니셜라이저
- delegate
- 스위프트
- property
- tuist
- Terminal
- Foundation
- String
- init
- optional
- extension
- Protocol
- Swift
- 코딩테스트
- instance
- initializer
- initalizer
- Xcode
- Class
- Today
- Total
아리의 iOS 탐구생활
[Xcode] Tuist를 활용하여 프로젝트를 관리해보기 본문
이번에 동아리 활동을 시작하게 되면서
프로젝트를 모듈화하여 관리해보자는 의견이 나와 Tuist를 사용해보게 되었다.
어떤 녀석인지 한번 알아보자!!!
Tuist는 Xcode 프로젝트와의 생성, 유지 관리 및 상호 작용을 용이하게 하는 것을 목표로 하는 커맨드 라인 인터페이스(CLI, 명령줄 도구, 터미널을 통해 사용자와 컴퓨터가 상호 작용하는 방식)이다.
바이너리로 배포되므로 종속성을 관리하기 위해 다른 도구에 의존하지 않고도 쉽게 설치하고 사용할 수 있다.
모듈화의 이점
- 모듈화로 나누어져 있으면 빌드 시 변경된 부분만 빌드하면 되기 때문에 빌드 속도가 향상된다는 장점이 있다.
- 모듈간 결합도는 낮추고 응집도를 높이는 형태
- .pbxproj에 UUID의 conflict을 줄일 수 있다는 장점도 가지고 있다.
Tuist를 사용하기 전에 알아야 할 개념
- Target
- project나 Workspace의 파일들을 빌드하여 생성되는 End Product를 의미
- Project
- 모든 파일, 리소스를 빌드하는데 필요한 정보의 저장소(repository)
- 프로젝트는 빌드하는 방법을 명시하는 end product인 target을 하나 이상 포함한다.
- Project가 가지고 있는 정보
- 소스파일에 대한 참조
- Structure navigator에서 소스파일을 그룹화
- Debug, release와 같은 build configuration을 설정 가능
- .xcodeproj라는 디렉토리에 터미널을 통해서 들어가면 아래와 같은 정보가 존재한다.
- Project.pbxproj
- 각 파일들의 참조값들을 UUID들로 정의되어 있는 파일
- Project.pbxproj
cd {projectName}.xcodeproj
open .
ls -a
. project.pbxproj xcuserdata
.. project.xcworkspace
- Workspace
- Xcode의 Project 및 기타 리소스를 그룹화하여 함께 작업할 수 있는 Xcode document
- 다수의 Project를 사용하고 싶은 경우, workspace 하위로 관리
- 각 Project의 파일을 구성하는 것 외에도 workspace에 포함된 Project들과 Target간의 관계를 제공
예시로 pod install시에 workspace가 생기는데 내부를 들어가보면 Pods Project가 생긴 것을 확인할 수 있다.
Project가 2개 이상되었기 때문에 이들의 관계를 하나로 묶어서 관리할 Workspace가 필요하여 pod install하면 자동으로 workspace가 생성된다.
왜 Tuist를 사용하는 걸까?
- Git을 사용하면서 Xcode 프로젝트 설정(.xcodeproj) 파일의 충돌은 협업을 불편하게 한다. 이를 개선해줄 수 있는 도구이다.
- XcodeGen과 다르게 Swift로 프로젝트 설정이 가능하다는 장점이 있다.
- XcodeGen은 yaml 혹은 json으로 프로젝트 설정 파일을 만들어야 된다.
모듈화를 적용했을시 기대되는 효과
- 코드 안정성
- 모듈간 결합도가 낮아지고 응집도가 높아지는 만큼 안정성이 높아지길 기대
- 문제 발생시 분석이 수월해질 것으로 예상
- 개발 생산성
- 모듈별 의존성이 낮아지면 고려해야하는 범위가 낮아져 개발 속도가 향상된다.
- 코드 리뷰시 관련 모듈만 검토가 가능해 리뷰어에게 편의가 높아질 것
- 빌드 속도
- 자주 변경되지 않는 모듈의 빌드가 발생하지 않아 빌드 속도에도 작은 영향을 줄 것.
- 사용 목적에 맞는 코드 배치
- 용도와 목적에 맞는 코드 배치로 이해하기 쉬운 프로젝트 구성
Tuist를 사용하여 모듈화하기
Tuist 설치
curl -Ls https://install.tuist.io | bash
Tuist로 iOS 프로젝트 생성하기
터미널로 프로젝트를 생성할 폴더로 진입하여 아래 명령어를 입력한다.
tuist init --platform ios // UIKit
tuist init --platform ios --template swiftui // SwiftUI
위 사진처럼 4개의 파일이 생성된다.
Project.swift를 수정하는 명령어 Tuist Edit을 실행한다.
명령어를 실행하면 Manifests 프로젝트가 오픈된다.
tuist edit
Project.swift 파일을 입맛대로 편집한다.
이 파일은 Tuist에서 .xcodeproj, 프로젝트를 어떻게 만들지 정의하는 파일이다.
Project.swift
Project는 아래와 같은 이니셜라이저를 가지고 있다.
public init(
name: String,
organizationName: String? = nil,
options: ProjectDescription.Project.Options = .options(),
packages: [ProjectDescription.Package] = [],
settings: ProjectDescription.Settings? = nil,
targets: [ProjectDescription.Target] = [],
schemes: [ProjectDescription.Scheme] = [],
fileHeaderTemplate: ProjectDescription.FileHeaderTemplate? = nil,
additionalFiles: [ProjectDescription.FileElement] = [],
resourceSynthesizers: [ProjectDescription.ResourceSynthesizer] = .default
)
- name
- 프로젝트 이름
- organizationName
- organization의 이름
- options
- Tuist가 xcodeproj 파일을 만들 때의 옵션을 설정해줄 수 있다.
- packages
- SPM의 package를 의미한다.
- settings
- 프로젝트 파일에 있는 build settings의 정보들을 설정해준다.
- Dictionary로 값을 줄 수 있다.
- targets
- 프로젝트의 타겟을 의미한다.
- schemes
- 프로젝트의 scheme를 의미한다.
- fileHeaderTemplate
- 내장 Xcode 템플릿에 Custom으로 파일 헤더를 만들 수 있다.
예를 들어서 fileHeaderTemplate: " ___COPYRIGHT___"
이렇게 만들고 프로젝트를 생성한 다음 swift파일을 만들면
// Copyright © 2022 tuist.io. All rights reserved.
import Foundation
만약 ""으로 해놓으면
//
import Foundation
으로 생성된다. nil이면 기본 값으로
//
// File.swift
// Fitfty
//
// Created by Ari on 2022/12/02.
// Copyright © 2022 baegteun. All rights reserved.
//
이렇게 생성이 된다.
- additionalFiles
- Tuist에서 프로젝트를 만들 때 Xcode에 자동으로 연결해주지 않는 파일을 넣으면 프로젝트에 연결시켜준다.
- 예를 들어 README.md 같은 파일은 프로젝트를 만들 때 Xcode에는 자동으로 보여지지 않는데, 여기에 추가해준다면 Xcode에서도 볼 수 있다.
- 아니면 통신할 서버가 GraphQL이여서 Apollo-iOS를 쓴다면 .graphql 파일을 추가할 수도 있다.
- resourceSynthesizers
- Tuist는 프로젝트를 생성할 때 Resources/ 안에 파일 확장자에 따라 enum을 제공해준다.
- 예시로 Assets에 색이랑 이미지를 넣었다면 아래처럼 enum을 자동으로 생성해준다.
public enum CoreAsset {
public enum Colors {
public static let girgGray = CoreColors(name: "GIRG_Gray")
public static let grigBackground = CoreColors(name: "GRIG_Background")
public static let grigBlack = CoreColors(name: "GRIG_Black")
public static let grigCompetePrimary = CoreColors(name: "GRIG_CompetePrimary")
public static let grigCompeteSecondary = CoreColors(name: "GRIG_CompeteSecondary")
public static let grigOnboardMain = CoreColors(name: "GRIG_OnboardMain")
public static let grigPrimary = CoreColors(name: "GRIG_Primary")
public static let grigPrimaryTextColor = CoreColors(name: "GRIG_PrimaryTextColor")
public static let grigSecondaryTextColor = CoreColors(name: "GRIG_SecondaryTextColor")
public static let grigWhite = CoreColors(name: "GRIG_White")
}
public enum Images {
public static let grigCompeteIcon = CoreImages(name: "GRIG_CompeteIcon")
public static let grigGithubIcon = CoreImages(name: "GRIG_GithubIcon")
public static let grigLogo = CoreImages(name: "GRIG_Logo")
public static let grigOnboard1 = CoreImages(name: "GRIG_Onboard1")
public static let grigOnboard2 = CoreImages(name: "GRIG_Onboard2")
public static let grigOnboard3 = CoreImages(name: "GRIG_Onboard3")
public static let grigOnboard4 = CoreImages(name: "GRIG_Onboard4")
public static let grigSword = CoreImages(name: "GRIG_Sword")
}
}
따라서 resourceSynthesizers란 위에서 제공해주지 않는 확장자들이 Resources/ 에 들어가있을때 어떻게 자동 생성해줄지에 대해 .stencil파일로 정의해주면 프로젝트를 생성할 때 .stencil내용에 따라 생성해준다.
예시로 프로젝트에 Lottie를 사용한다면 Resources/ 에 .json파일이 들어갔을 때 어떻게 자동 생성 시킬지에 대해 만들 수 있다.
.default는 strings, plists, fonts, assets을 자동으로 생성해준다.
Workspace.swift
WorkSpace.swift는 Tuist에서 .xcworkspace 워크스페이스를 어떻게 만들지 정의하는 파일이다.
Workspace는 아래와 같은 이니셜라이저를 가진다.
public init(
name: String,
projects: [ProjectDescription.Path],
schemes: [ProjectDescription.Scheme] = [],
fileHeaderTemplate: ProjectDescription.FileHeaderTemplate? = nil,
additionalFiles: [ProjectDescription.FileElement] = [],
generationOptions: ProjectDescription.Workspace.GenerationOptions = .options()
)
- name
- 워크스페이스의 이름
- projects
- Workspace에 등록할 프로젝트들의 경로를 넣어주면 된다.
- struct인 Path를 받지만 그냥 문자열을 넣어도 무방하다.
- 기본 경로는 프로젝트의 루트 디렉토리를 기준으로 한다.
- schemes, fileHeaderTemplate, additionalFiles
- Project.swift와 동일
- generationOptions
- Tuist가 xcworkspace 파일을 만들 때의 옵션을 설정해줄 수 있다.
Config.swift
프로젝트 전역으로 쓰이는 설정을 해줄 수 있다.
예를 들어 Swift의 버전이나 Xcode의 버전 같은게 있다.
Config.swift는 {프로젝트 루트 디렉토리}/Tuist/Config.swift 에 있을 때만 적용된다.
Target
Project.swift에서 언급했던 Target.
Target은 사용할 모듈을 정의하는 struct이다.
Target은 아래와 같은 이니셜라이저를 가진다.
public init(
name: String,
platform: ProjectDescription.Platform,
product: ProjectDescription.Product,
productName: String? = nil,
bundleId: String,
deploymentTarget: ProjectDescription.DeploymentTarget? = nil,
infoPlist: ProjectDescription.InfoPlist? = .default,
sources: ProjectDescription.SourceFilesList? = nil,
resources: ProjectDescription.ResourceFileElements? = nil,
copyFiles: [ProjectDescription.CopyFilesAction]? = nil,
headers: ProjectDescription.Headers? = nil,
entitlements: ProjectDescription.Path? = nil,
scripts: [ProjectDescription.TargetScript] = [],
dependencies: [ProjectDescription.TargetDependency] = [],
settings: ProjectDescription.Settings? = nil,
coreDataModels: [ProjectDescription.CoreDataModel] = [],
environment: [String : String] = [:],
launchArguments: [ProjectDescription.LaunchArgument] = [],
additionalFiles: [ProjectDescription.FileElement] = []
)
- name
- 타겟의 이름
- platform
- iOS, macOS, tvOS, watchOS 같은 플랫폼을 의미한다.
- product
- app, appClips, staticFramework, framework, unitTest 등을 의미한다.
- productName
- 만들어진 product의 이름
- The build product name
- bundled
- 프로젝트 파일을 열었을 때 보이는 Bundle Identifier
- deploymentTarget
- 배포 타겟을 설정할 수 있다.
- infoPlist
- info.plist를 정의한다.
- sources
- 소스코드의 경로를 입력해주면 된다.
- 안에 문자열로 경로를 입력해도 된다.
- resources
- 앞서서 resourceSynthesizers에서 Tuist가 Resources/ 의 리소스들을 자동으로 코드화한다고 했는데, 그때 이 리소스들이 어디에 있는지에 대한 경로를 의미한다.
- 안에 문자열로 경로를 입력해도 된다.
- copyFiles
- 타겟에 대한 Build Phase 파일 복사 작업
- headers
- 타겟에 대한 headers
- entitlements
- 타겟에 대한 entitlements의 경로를 입력해주면 된다.
- scripts
- 타겟에 대한 build Phase 스크립트 작업
- dependencies
- 타겟의 의존성에 대한 것을 의미한다.
- 라이브러리나 다른 모듈을 의존성으로 넣을 때 사용한다.
- settings
- 타겟의 세팅을 정의한다.
- coreDataModels
- CoreData의 모델들의 경로랑 버전을 정의한다.
- environment
- scheme에서 Edit Scheme… 버튼을 누르면 나오는 창에서 Environment Variables를 설정할 수 있는데 이때 environment를 설정하면 자동으로 생성한다.
- launchArguments
- scheme에서 Edit Scheme… 버튼을 누르면 나오는 창에서 Arguments Passed On Launch를 설정할 수 있는데 이때 launchArguments 설정하면 자동으로 생성한다.
- additionalFiles
- 프로젝트를 생성할 때 자동으로 생겨나지 않는 파일을 등록해놓으면 Xcode에서 볼 수 있다.
편집을 모두 마치고 아래 명령어를 입력해주면 프로젝트가 생성된다.
tuist generate
.xcodeproj, .xcworkspace 파일이 생성된다.
💻 Tuist로 생성한 프로젝트 구경가기
Reference
'Swift > iOS' 카테고리의 다른 글
[Figma/Tip] 디자인 가이드 확인할 때 유용한 꿀팁 모음 (0) | 2023.04.14 |
---|---|
[iOS] Github에서 API KEY를 숨기기 위한 여러가지 방법들 (1) | 2023.01.31 |
[RxSwift/Alamofire] Alamofire를 Mocking해서 네트워크와 무관한 테스트 하기 (3) | 2022.08.14 |
[UIKit/iOS] Storyboard Reference (0) | 2022.04.08 |
[UiKit/iOS] 셀이 didSelect 되었을 때 화면 전환하기 (0) | 2022.02.06 |