부스트캠프 - Tuist 알아보기

김세영·2022년 11월 18일
4

boostcamp

목록 보기
2/3
post-thumbnail

부스트캠프 팀원들과 그룹프로젝트를 설계하면서, 다음과 같은 고민이 생겼습니다.

Xcode에서 파일 및 폴더를 삭제하거나, 위치를 변경하면 .pbxproj에서 충돌이 나지 않을까요?

그래서 처음 결정된 의견은 "폴더의 수정은 기록해놓고, merge한 후 반영하죠!" 였습니다.

하지만 매번 그런 방식을 사용하면 굉장히 번거롭고, 뭔가 방법이 있을 테니 멘토님께 여쭤보자고 이야기가 나왔습니다.

멘토님은 회사에서도 이 문제때문에 고민이 있었고, XcodeGen과 Tuist를 추천해 주셨습니다. 팀원 분들과 회의 끝에 Tuist를 사용하기로 하였습니다.

Tuist

Tuist - GitHub

Tuist는 Xcode 프로젝트를 생성하고 관리하는 Command Line Tool 입니다.

깃허브에 나와 있는 한 줄 설명입니다.

이 설명대로, Tuist는 Xcode 프로젝트 모듈화를 위한 툴입니다.

Installation

curl -Ls https://install.tuist.io | bash

이 스크립트를 실행하여 Tuist를 설치할 수 있습니다.

사용해보기

Tuist docs

위 링크에 나와 있는 대로 프로젝트를 만들어 보겠습니다.

  1. 우선 테스트할 디렉토리를 생성합니다.

  2. 다음 명령어를 실행하여 Tuist를 세팅합니다.

    그럼 디렉토리가 다음과 같이 구성됩니다.

    문서에는 Info.plist, AppDelegate.swift, Project.swift 및 테스트 파일들이 같이 생성된다고 적혀 있습니다. 위 디렉토리에서는 Info.plist가 보이지 않지만 일단 진행해 보겠습니다...🥶
    (Project.swiftPackages.swift와 동일하다고 합니다.)

  3. 다음 명령어를 실행하여 Tuist Manifest를 열고 수정할 수 있습니다.

    그러면 Xcode가 자동으로 열리게 됩니다.

    아직 Mainfest에 대한 자세한 이해가 없기 때문에, 추후 알아보게 된다면 포스트를 해야겠습니다.

  4. 드디어 Xcode 프로젝트를 생성합니다. 다음 명령어를 사용하여 Xcode 프로젝트를 생성합니다.

    **.xcodeproj**.xcworkspace가 생성됩니다.

    xcworkspace는 프로젝트가 의존하게 될 다른 프로젝트를 추가할 때 필요하게 됩니다.
    (Cocoapod이 xcworkspace를 사용하는 것과 같은 의미가 되는 것 같습니다.)

    그런데 tuist generate는 현재 프로젝트 뿐만 아니라, 이 프로젝트가 의존하고 있는 모든 프로젝트까지 생성하게 됩니다. 이 때 의존하는 프로젝트를 제외한 개인의 프로젝트만 골라서 생성하고 싶을 때는 --project-only 옵션을 사용하면 된다고 합니다.

    다음과 같이 프로젝트가 생성되었습니다!

tuist generate 명령이 실행되면서 만든 폴더 구조(바로 위 Xcode의 폴더 구조)와, 저 위에 있는 2. 다음 명령어를 실행하여 Tuist를 세팅합니다.에 나와 있는 트리 구조가, 정확히는 Targets가 일치하는 것으로 보아, tuist generateTargets 구조를 따라 Xcode 프로젝트를 생성하는 것 같습니다.

맞는 것 같지만 궁금하니 한 번 Targets의 내용을 바꾸어 실험해보겠습니다.

  1. 시원하게 밀어버리고 다시 init부터 해보았습니다.

  2. 각 Target의 하위 폴더에 hello.swift를 끼워 넣어 보았습니다.

  3. 바로 생성해보겠습니다.

    각 폴더에 hello.swift가 들어가 있네요!

프로젝트에 적용하기

저희는 프로젝트에 바로 Tuist를 적용해보기로 했습니다.
기존에 있는 프로젝트가 아닌, 새로 프로젝트를 만들어서 설정했습니다.

tuist init --platform ios

위 명령어를 입력하여 새로운 프로젝트를 생성해줍니다.

위에서 말한 대로 Targets 폴더에서 프로젝트 구조를 수정해 줄 수 있습니다.

저는 Kit과 UI 프레임워크를 따로 생성하여 관리하지 않을 것이어서, 우선 저 두 폴더를 삭제해 주겠습니다.

이제 tuist edit으로 Manifest를 수정해줍니다.

  • Project.swift에서 additionalTargets에 있는 추가 타겟들을 제외해줍니다.

  • Tuist/ProjectDescriptionHelpers/Project+Templates.swift를 열고, organizationName과 bundleId를 수정해줍니다.

    저는 replace로 "io.tuist"를 "com.testapp"으로 변경해주었습니다.

라이브러리 설정

앱에 사용할 라이브러리를 명시하여 추가해줄 수 있습니다.

이번 포스트에서는 많이 사용되는 라이브러리인 RxSwift, SnapKit을 추가해보도록 하겠습니다.

Tuist Doc - tuist fetch 를 보면, tuist fetch 명령어를 실행할 경우 Tuist/Dependencies.swift에 있는 항목들을 받아와 준다고 적혀 있습니다.

그 후 Tuist Doc - Adding External Dependencies에 나와 있는 내용처럼 let dependencies = ...을 구성해 주어야 합니다.

// Dependencies.swift

import ProjectDescription

let spm = SwiftPackageManagerDependencies([
    .remote(url: "https://github.com/ReactiveX/RxSwift", requirement: .upToNextMajor(from: "6.5.0")),
    .remote(url: "https://github.com/SnapKit/SnapKit", requirement: .upToNextMajor(from: "5.6.0")),
])

let dependencies = Dependencies(
    swiftPackageManager: spm,
    platforms: [.iOS]
)

이제 터미널에서 Ctrl+C를 눌러 편집을 종료해줍니다. 그 후 tuist fetch 명령어를 입력하여 Dependencies.swift에 있는 프레임워크들을 다운받아 줍니다.

이렇게 결과 화면이 뜨게 되면 라이브러리들이 모두 받아진 것입니다.

그럼 tuist generate 명령으로 프로젝트를 실행시켜 보겠습니다.

프로젝트를 열게 되면 아마 위에서 다운받은 라이브러리들이 보이지 않을 것입니다. Project.swift에서 추가적으로 설정을 해줘야 하기 때문입니다.

Xcode를 닫고, 터미널에 다시 tuist edit을 입력하여 Manifest 편집을 열어 줍니다.

앱의 타겟을 추가해주기 위해 Project.swift의 하단에 있는 let project = Project.app(...) 부분을 아래와 같이 설정해 줍니다.

let dependencies: [TargetDependency] = [
    .external(name: "RxSwift"),
    .external(name: "RxCocoa"),
    .external(name: "RxRelay"),
    .external(name: "SnapKit"),
]

let targets: [Target] = [
    Target(
        name: "TestTuist",
        platform: .iOS,
        product: .app,
        bundleId: "com.testapp",
        infoPlist: .default,
        sources: ["Targets/TestTuist/Sources/**"],
        resources: ["Targets/TestTuist/Resources/**"],
        dependencies: dependencies
    )
]

// Creates our project using a helper function defined in ProjectDescriptionHelpers
let project = Project(
    name: "TestTuist",
    organizationName: "com.testapp",
    settings: .settings(defaultSettings: .recommended),
    targets: targets
)

Project.swift를 관리하는 팩토리 클래스를 만들어 사용하는 경우도 있는 것 같습니다.

터미널을 다시 Ctrl+C로 닫고 tuist generate를 입력하여 프로젝트를 생성해줍니다.

이제 프로젝트가 완성되었습니다!

추가적으로 Info.plist, xcconfig 및 기타 많은 설정들을 관리해줄 수 있습니다. 아직 추가 설정은 사용해보지 않아서, 사용하게 된다면 다시 포스트할 예정입니다.

Signing (개발자 계정 필요)

프로젝트를 여러 사람이 같이 개발하는 경우, Xcode 프로젝트에서 Signing을 관리해 주어야 합니다.

저희 팀의 경우 제가 Apple 개발자 계정이 있어서, 프로젝트를 설정해 준 후 GitHub에 업로드하였습니다.

Tuist Doc - tuist signing

위와 같이 따로 Signing 설정을 해주지 않을 경우 실제 기기에서 실행이 되지 않습니다.

인증서 및 기타 파일 생성

Tuist에서 Signing을 관리하려면 총 3가지 파일이 필요합니다.

  • Provisioning Profile (iOS 앱은 .mobileprovision)
  • 키체인에 있는 개발자 계정 인증서 - Public (.cer)
  • 키체인에 있는 개발자 계정 인증서 - Private (.p12)

Certificates

  1. Apple Developer - account

    위 사이트에 접속하여 로그인합니다.

  2. + 버튼을 누른 후 저는 iOS App Development를 선택해 주었습니다.

  3. 이 때 Certificate Signing Request라는 파일을 업로드하라고 요구합니다. "Learn More >" 버튼을 누르면 해당 파일을 생성하는 방법이 나와 있습니다.

  4. 아래와 같은 파일이 생성됩니다.

  5. 위 파일을 업로드하고 Continue를 누르면 인증서가 생성됩니다.

  6. Download를 눌러 인증서를 다운받습니다.

  7. "키체인 접근"이 열리게 되고, 검색어로 "apple"을 입력하면 다음과 같은 인증서들이 보이게 됩니다.

  8. 테스트하다가 인증서를 여러 개 만들어 버렸는데, 위와 같은 형식 중 가장 하단에 있는 것으로 사용하면 되는 것 같습니다. (정확하지는 않습니다..)

  9. 다음 절차를 거쳐 .p12 파일을 생성합니다.

  10. 중요: 여기서 비밀번호를 입력하라는 창이 뜨는데, 이 때 비밀번호는 반드시 비어 있어야 합니다. 창이 뜨면 비밀번호 란에 아무것도 입력하지 않고 다음을 눌러야 합니다.

    이렇게 하지 않으면 Tuist가 인증서를 인식하지 못하고, tuist generate 명령 실행 시 에러가 나게 됩니다.

  11. 이제 6번에서 다운받은 .cer 파일과 .p12의 이름을 알맞게 바꿉니다. 저는 프로젝트 이름.cer, 프로젝트 이름.p12로 설정하였습니다.

Provisioning Profile

Profile을 다운로드하기 전에 팀원들의 기기를 등록해야 합니다.

  1. Certificates, Identifiers & Profiles - Devices를 클릭합니다.
  2. + 버튼을 누르면 기기를 등록하는 창이 뜨게 됩니다.
  3. 플랫폼을 선택합니다.
  4. Device Name은 팀원의 기기를 구별할 수 있을 정도로만 작성하면 됩니다.
  5. Device ID(UDID)는 구글에 udid 키워드로 검색하면 획득하는 방법이 나와 있습니다.
  6. Continue를 누르고, 기기 정보가 올바른지 확인 후 Register을 눌러 등록합니다.

Provisioning Profile은 다음과 같이 얻을 수 있습니다.

  1. Certificates, Identifiers & Profiles - Profiles에 접속합니다.
  2. + 버튼을 누르고, 저는 iOS 앱이기 때문에 iOS App Development를 선택해 주었습니다. Continue를 누릅니다.
  3. 개발할 앱을 선택하고, 밑에 있는 Provisioning Profile Configuration은 No로 해주었습니다. Continue를 누릅니다.
  4. 사용할 Certificates를 선택해 준 후 Continue를 클릭합니다. 저는 아까 위에서 생성한 인증서를 선택했습니다.
  5. 이제 위에서 등록한 기기 목록이 뜨게 되고, 팀원의 기기들을 알맞게 체크해줍니다. Continue를 누릅니다.
  6. 이름을 적절하게 입력해 준 후 Generate를 누릅니다.
  7. Download를 눌러 파일을 획득합니다.

이제 Signing에 필요한 3가지 파일을 모두 생성했습니다.

이 파일들은 팀원들이 모두 가지고 있어야 하고, 만약 Git을 사용한다면 .gitignoreSigning/을 반드시 추가하여 인증서가 유출되지 않도록 해야 합니다.

Tuist Signing

위 파일들을 Tuist/Signing 폴더에 넣어야 합니다. Signing 폴더를 생성한 후, 3가지 파일을 생성한 폴더 안에 넣어 줍니다.

중요: .mobileprovision 파일의 이름은 반드시 Target.Debug.mobileprovisioning으로 변경해 주어여 햡니다.
만약 Release 모드의 profile이 필요하다면 이름을 Target.Release.mobileprovisioning으로 추가해줍니다.

저는 타겟 이름이 TestTuist이기 때문에 TestTuist.Debug.mobileprovisioning으로 설정해 주었습니다.

master.key

이제 한 가지 작업만 남았습니다.

Tuist 폴더에 master.key라는 파일을 생성해야 합니다.

파일을 생성해 주고, 다음 명령어를 입력하여 나오는 값을 master.key 파일 안에 그대로 입력해줍니다.

openssl rand -base64 32

모든 설정이 끝났습니다..!

이제 tuist generate 명령어를 입력하면 Signing이 자동으로 설정되어 있을 것입니다.

tuist generate 명령을 실행하면 .p12.cer 파일 뒤에 .encrypted가 붙게 됩니다. 이는 Tuist 자체에서 파일을 암호화 시키며, 터미널에서 tuist signing decrypt 명령어를 입력하여 암호화를 풀거나 tuist signing encrypt 명령어를 입력하여 다시 암호화할 수 있습니다.

profile
초보 iOS 개발자입니다ㅏ

2개의 댓글

comment-user-thumbnail
2022년 12월 24일

유익한 자료 감사합니다~

답글 달기
comment-user-thumbnail
2023년 2월 6일

안녕하세요 좋은 내용 감사드립니다. 하나 질문 드릴께 있습니다.
Trinap 앱 깃헙에 혹시 구글 로그인을 사용하시나여??
현재 저도 tuist를 이용하여 프로젝트를 구성하고 있는데 SPM을 통한 구글로그인 구현이 계속 안되고 있어서요..
만약 구글로그인을 구현하셨다면 조언을 조금 구하고 싶습니다.

답글 달기