아리의 iOS 탐구생활

[Xcode] Tuist를 활용하여 프로젝트를 관리해보기 본문

Swift/iOS

[Xcode] Tuist를 활용하여 프로젝트를 관리해보기

Ari Lee 2022. 12. 2. 16:40
반응형

 

이번에 동아리 활동을 시작하게 되면서
프로젝트를 모듈화하여 관리해보자는 의견이 나와 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들로 정의되어 있는 파일
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
  • 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로 생성한 프로젝트 구경가기

 

GitHub - YAPP-Github/21st-iOS-Team-2-iOS

Contribute to YAPP-Github/21st-iOS-Team-2-iOS development by creating an account on GitHub.

github.com

 

 

 

 

 

 

 

 

 

 

Reference

 

Get started | Tuist Documentation

Learn how to install Tuist in your environment and generate your first project.

docs.tuist.io

 

[Swift] Tuist 모듈화 툴

Tuist..! 모듈화를 위한 툴이에요 드디어 해보게 되었는데요... Tuist에대한 정보가 많이 부족하더라구요 정보에 보탬이되고자 정리를 해서 공유해보려고해요! Tuist에러 때문에 쉐도우복싱도 많이

nsios.tistory.com

 

[iOS - swift] 4. 모듈화 개념 - Tuist로 프로젝트 관리 방법

1. 모듈화 개념 - Library vs Framework (static library, dynamic library, static framework, dynamic framework) 2. 모듈화 개념 - Binary File 개념 (Mach-O, CPU Architectures, Universal binary, lipo command) 3. 모듈화 개념 - XCFramework 생성

ios-development.tistory.com

 

Tuist 사용법 - 1. 이론 및 샘플 예제

Tuist? Xcode 프로젝트 관리 툴? Why Tuist? 설치 Manifests Project.swift Workspace.swift Config.swift Target 샘플 프로젝트 모듈 생성 Method 모듈 구조 만들기 결론 Tuist? Xcode 프로젝트를 관리하는 툴입니다. Project.swif

baegteun.tistory.com

반응형
Comments