iyOmSd/Title: Swift

[Swift] Tuist 모듈화 툴

냄수 2022. 8. 5. 21:00
반응형

Tuist..!

모듈화를 위한 툴이에요

드디어 해보게 되었는데요...

Tuist에대한 정보가 많이 부족하더라구요

정보에 보탬이되고자 정리를 해서 공유해보려고해요!

 

Tuist에러 때문에 쉐도우복싱도 많이하고... 시간 먹방도 많이했어요...

잘 생각해보고 도입하셔야합니다...🫠

 

 

협업을 하다보면 project.pbxproj 파일에서 많은 충돌이 일어나는 문제도 해결이되고

관리하는 측면에서도 이점이 있어서 사용한다고해요

Xcode의 설정이나 폴더들의 구조를 Project.swift파일에 정의하고 그 내용을 토대로 프로젝트를 구성해줘요

 

설치는 어렵지않아요

문서에 있는대로 따라가볼게요

 

tuist 3.9.0 기준으로 작성된 게시글이에요!!

 

tuist 설치

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

 

프로젝트를 생성할 위치로 이동해서 Tuist를 이용해서 프로젝트를 생성해줄거에요

// 🚨기존프로젝트를 열때는 사용하지않습니다🚨
// 원하는경로로 이동후 tuist로 프로젝트생성
tuist init --platform ios // UIKit
tuist init --platform ios --template swiftui // SwiftUI

설치하면 이런 구조로 생성되있을거에요( 게시글은 SwiftUI명령어를 이용해서 생성했습니다 )

게시글을 쓰면서알았는데 폴더이름에 tuist___가 들어갔을 때 오류가날수있으니 폴더명 구분되게 해주시면 좋을것같아요

폴더이름이 바뀌기전 이름이라  혼동에 주의하세욥

 

 

Tuist를 사용하면

이제부터

Xcode보다 터미널을 이용해서 많은 작업들을 하게될거에요

터미널을 통해서 프로젝트를 생성하고, 라이브러리를 받아오고, Xcode파일을 생성해줄거에요

 

Tuist 설정을 변경하고 싶을 땐 Tuist폴더가 있는 위치에서

tuist edit

명령어를 입력해서 설정파일을 열 수 있어요

 

열리고나면 뭐가되게많죠??

 

구경이 끝났으면 터미널로 돌아와서

tuist generate

하면 방금봤던 프로젝트설정을 토대로 아래와같은 구조로 프로젝트가 생성됬을거에요

 

어떻게 이런 구조를 잡았는지 보고 원하는 구조대로 만들어보도록 해볼게요!

 

다시 tuist edit을 통해서

Tuist설정 파일을 열고

Project.swift파일을 보면

"TuistTest"프로젝트이름은 여기서 넣어줬네요

정의된 app()함수를보면

결과적으로 Project타입을 반환해요

 

 

Project

Project타입은

프로젝트를 만들어봤으면 대충 감이오는 네이밍을 제외하고 알아볼게요

 

option

트위스트에서 자동으로 만들어주는 파일에 대한 옵션을 조절할 수 있어요

대표적으로 이미지에셋에 대해서 자동으로 파일과 이름을 만들어주는데 이기능을 disable할 수 있습니다.

let options: Options = .options(
    disableBundleAccessors: true,
    disableSynthesizedResourceAccessors: true
)

packages

엑스코드에서 사용하는 SPM이라고 생각하시면돼요

엑스코드 SPM를 사용할경우에 여기에 정의해서 사용합니다

 

이기능과 유사하게

뒤에서 나오겠지만 Tuist자체로의 SPM을 사용할 수도 있어요

Tuist의 SPM을 사용하게되면 캐싱도 유리한면이 있지만

아직 완벽하게 구현되지않아서 이슈가 많은편이에요

저는 몇몇 라이브러리들을 사용할 떄 골치가 아파서 packages로 섞어서 사용하기도 했어요

 

settings

프로젝트 Build Setting쪽에 들어갈 setting정보들을 설정합니다.

매칭되는 key값을 문서에서 찾아서 값을 넣어주면 프로젝트생성시 설정되어있습니다.

let baseSettings: [String: SettingValue] = [
    "SWIFT_OBJC_BRIDGING_HEADER": "./Sources/NamSoo-Bridging-Header.h"
]

let releaseSettings: [String: SettingValue] = [
    "EXCLUDED_SOURCE_FILE_NAMES": "제외할파일"
]

let settings: Settings = .settings(
    base: baseSettings,
    release: releaseSettings,
    defaultSettings: .recommended
)

 

target

프로젝트에 대해 타겟(모듈)을 정의합니다.

아래에 타겟부분이 추가되는 거에요

 

schemes

타겟에 해당하는 스킴을 생성합니다.

스킴에따른 빌드나 액션을 해야할때 추가해서 사용합니다.

 

 

또 중요한 타입이 있어요

 

 

Target

사용할 모듈을 정의할 수 있는 타입입니다.

모듈화는 프로젝트를 만들고 그 안에 여러 모듈로 구성되어있는 형태를 구성해서 사용하죠 그 모듈을 정의합니다

platform

iOS, macOS, watchOS 그런 플랫폼 종류입니다

 

product

app, dynamic framework, static framework, dynamic library, unitTest, 등 이러한 종류입니다.

 

infoPlist

info.plist를 정의하는곳입니다.

.default를 사용할 수 있고

문서에서 매칭되는 key값을 찾거나 커스텀으로 추가적으로 값을 넣을 수 있습니다.

let infoPlist: [String: InfoPlist.Value] = [
    "CFBundleShortVersionString": "1.0",
    "CFBundleVersion": "1",
    "UIMainStoryboardFile": "",
    "UILaunchStoryboardName": "LaunchScreen"
]

 

sources, resources

소스파일, 리소스파일이 생성될 위치를 정의합니다

타겟의 하위부터 시작합니다.

targetName
  - Sources
  - Resources

 

이런 구조를 갖게되고

Tuist edit상태에서 똑같이 폴더를 만들어줘야합니다(혹은 파인더에서 생성해도 됩니다)

만들지않으면 tuist generate시에 파일위치를 못찾는다는 에러가 발생합니다.

이렇게말이죠!

해결하기위해선 정의한 구조와 이름을 맞춰줘야해요

폴더생성위치가 헷갈릴떈

Project.swift파일이 있는곳이 프로젝트의 루트라고 보시면되요

따라서 지금같은 위치는 이 파일과 같은 위치에 폴더를 만들어주시면돼요

 

에디터를 끄고 tuist edit으로 다시접근시 폴더가 사라져서 안보여요

하지만 파인더에 가보면 폴더는 존재하고있으니 주의하세요!

 

현재 코드

let project = Project(
    name: "NSiOS",
    organizationName: "nsios.org.",
    options: .options(
        disableBundleAccessors: true,
        disableSynthesizedResourceAccessors: true
    ),
    targets: [
        Target(
            name: "targetName",
            platform: .iOS,
            product: .framework,
            bundleId: "ns.bundle.Tuist",
            deploymentTarget: .iOS(targetVersion: "15.0", devices: .iphone),
            sources: ["Sources/**"],
            resources: ["Resources/**"]
        )
    ]
)

샘플코드를 다지우고 이렇게 간단하게 정의해봤구요

폴더도만들어주고

tuist generate해주면

잘 생성됬네요!!

여기서도

Sources, Resources파일이 안보일텐데

폴더가 비어있어서 사라져있어서그래요

파인더경로에는 생성되어있기때문에 프로젝트내부로 추가만해주고 파일을 추가하면 다음부터는 사라지지않아요!

Project폴더를 클릭한상태로 add files to 를 통해 파일을 추가할거에요

추가할때옵션으로

create groups을 해줘야 정상적으로 swift파일을 생성할 수 있어요

 

dependencies

의존성을 정의해주는 곳입니다.

라이브러리, 프로젝트, 타겟, 패키지, 등 의존성을 추가할 수 있어요

.project는 다른 모듈을 뜻하고

.target은 같은Project에 정의된 타겟들을 뜻하고

.external이 Dependencies파일에 정의한 일반적인 라이브러리를 가져왔을때 사용합니다.

다른모듈들을 의존해서 사용할때 사용하는 그 모듈들을 모두 추가해줘야해요

 

 

라이브러리 의존성추가하기

앱을 개발하다보면 라이브러리도 넣어줘야겠죠?

파일이름을 꼭 Dependencies 로 만들어주세요

위치는 생성된 Tuist폴더안에, Config와 같은레벨에 생성해주세요

라이브러리를 설치하는 방법은 여러가지가 제공되고있어요

Carthage - Dependencies

Tuist SPM - Dependencies

Xcode SPM - Package

 

Dependencies타입은 옵션으로 carthage, spm을 제공해줘요

문서와 같이 링크나 path를 넣어주고 버전을 넣어서 설치합니다.

carthage를 사용할땐 carthage를 따로 설치해줘야해요

brew intall carthage

 

import ProjectDescription

let dependencies = Dependencies(
    carthage: [
        .github(path: "Alamofire/Alamofire", requirement: .exact("5.0.4")),
    ],
    swiftPackageManager: [
        .remote(url: "https://github.com/Alamofire/Alamofire", requirement: .upToNextMajor(from: "5.0.0")),
    ],
    platforms: [.iOS]
)

 

Dependencies을 수정했으면 꼭해야하는 명령어들이 있어요

엄청 자주 사용할 명령어 3대장이죠

tuist clean
tuist fetch
tuist generate

캐싱된상태를 지우고

라이브러리를 다시 fetch하고

프로젝트를 생성하는 과정을 거쳐요

 

 

하지만 위에서 언급했듯이 Tuist는 이슈가 아직 많아서 동작안하는 부분이 있어요

그럴때 Package를 이용해서 Xcode SPM을 이용하는 방법을 생각해볼 수 있을 것같아요

let project = Project(
    
    packages: [
        .package(
            url: "https://github.com/Alamofire/Alamofire",
            .upToNextMajor(from: "5.0.4")
        )
    ],
    targets: [
        Target(
            name: "targetName",
            platform: .iOS,
            product: .app,
            bundleId: "ns.bundle.Tuist",
            deploymentTarget: .iOS(targetVersion: "15.0", devices: .iphone),
            sources: ["Sources/**"],
            resources: ["Resources/**"],
            dependencies: [
                .external(name: "Alamofire - Dependencies이용시"),
                .package(product: "Alamofire - Package이용시")
            ]
        )
    ]
)

Package를 사용할땐 Project의 packages부분을 추가해줘야해요

 

 

브렌치를 변경해서 구조가 달라졌다면 

tuist generate를 통해서 다시 구조를 생성해줘야해요

 

마지막으로 워크스페이스로 관리하는 방법을 알아볼거에요

여러개의 프로젝트를 관리할 수 있죠

 

 

Workspace

파일이름을 꼭 Workspace로 만들어주세요

위치는 Tuist폴더와 같은위치에 추가해주세요 아마 폴더의 최상단이 될거에요

프로젝트마다 Project.swift파일이 존재해야해요

폴더로 구분되지않으면 Project파일을 또생성할 수 없기때문에

지금은 test_Tuist2에서 NSiOS프로젝트가 바로 보이지만 폴더를 또 생성해서

최상단 폴더를 Projects이름으로 구성할거에요

generate시

xcodeproj, xcworkspace, Derived파일은 자동으로 생성되므로 삭제해도 무관합니다

 

tuist edit을 통해서 수정파일을열고

파일을 추가하고

구조를 아래와같이 정의할거에요

구조를 추가하고 Manifests를 클릭하고 폴더를 정의한 구조에맞게

Projects 폴더를 생성하고

그아래로 NSiOS, NamSoo, Enes폴더를 각각 만들어주고

또 그안에도 타겟별로 정의해준 Sources, Resources의 위치도 알맞게 생성해주세요

 

파인더에서도 확인해보면

폴더가 원하는대로 구성된 것을 볼 수 있어요

 

여기서 이제

각 프로젝트별(Enes, NamSoo, NSiOS)

Project.swift파일을 생성해서 관리하면 되요

 

tuist generate를 하면!

//
//  MainApp.swift    << 파일이름
//  NSiOSTarget    << 타겟이름
//
//  Created by 김남수 on 2022/08/05.
//  Copyright © 2022 nsios.org. All rights reserved.    << org이름
//


// 정의된 Project.swift

let project = Project(
    name: "NSiOS",
    organizationName: "nsios.org",
    options: .options(
        disableBundleAccessors: true,
        disableSynthesizedResourceAccessors: true
    ),
    targets: [
        Target(
            name: "NSiOSTarget",
            platform: .iOS,
            product: .app,
            bundleId: "nsios.bundle",
            deploymentTarget: .iOS(targetVersion: "15.0", devices: .iphone),
            sources: ["Sources/**"],
            resources: ["Resources/**"]
        )
    ]
)

이렇게 정의한게 위처럼 뜨는걸 볼 수 있죠

 

처음에 아무파일이 없어서 당황하실 테지만

AppDelegate라던가, MainApp 형식 그냥만들어서 사용하시면

정상적으로 앱을 실행 시킬수 있습니다!

 

 

적용하는과정을 같이 보면좋을것같아서 다른게시글 링크걸어드려요!

2023.01.21 - [iyOmSd/Title: Swift] - [Swift] Tuist 모듈화 응용편 - 모듈화적용후 사용하기

반응형