Tuist ๋์ ๊ธฐ
- #iOS
- #SwiftUI
- #Tuist
๋ค์ด๊ฐ๋ฉฐ
์๋ ํ์ธ์. ์๋์ ๋ชจ๋ฐ์ผํ์์ iOS์ฑ๊ฐ๋ฐ์ ๋งก๊ณ ์๋ ์ ๊น๊ธฐ๋ณด๋ผ๊ณ ํฉ๋๋ค.
์ต๊ทผ fromm iOSํ๋ก์ ํธ์๋ ์ฑ์์ฒด์ ์ฑ๋ฅ๊ณผ ๊ฐ๋ฐ ์๊ฐ ๋จ์ถ ๋ฑ์ ์ํด ์ฌ๋ฌ ๊ฐ์ง ์๋๋ค์ด ์ด๋ฃจ์ด์ง๊ณ ์์ต๋๋ค. ๊ทธ ์ค ํ๋๊ฐ The Modular Architecture(์ดํ TMA)์ ๋์ ์ ๋๋ค.
์๋ ๋ง๊น์ง๋ง ํด๋ fromm ํ๋ก์ ํธ๋ ํ๋์ ๊ฑฐ๋ํ ์ฑ์ผ๋ก ์กด์ฌํ์์ต๋๋ค. ๊ณตํต์ผ๋ก ์ฌ์ฉํ๋ ๋ชจ๋์ด ์์์ง๋ง ์ฌ์ ํ ์์กด์ฑ ํ์ ์ด ์ฝ์ง ์์๊ณ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ถ๋ฆฌ๋์ด์์ง ์์์ ์ฝ๋๊ฐ ๊ณ์ธต์ ๋๋๋ค ์ ์์์ฃ . ์ปดํ์ผ์์์ ์ก์ ์๋ ์์ด์ ๋์น๋ ๊ฒฝ์ฐ๋ ๊ฐํน ์์์ต๋๋ค.
๋๋ฌธ์ ์ฌํด์ด๋ถํฐ๋ ๊ณตํต ๋ชจ๋ ๋ฟ ์๋๋ผ ์ฑ ๋ด ๋๋ฉ์ธ๋ค์ ๊ณ์ ์์ ๋ชจ๋๋ก ๋ถ๋ฆฌํด๋๊ฐ๋ฉฐ ๊ธฐ์กด์ ์๋ ๋ฌธ์ ๋ค์ ํด๊ฒฐํด๋๊ฐ๊ณ ์์๋๋ฐ์. (fromm์ฑ์ ๋ชจ๋ํ ๋์ ํ๊ธฐ)
๋ชจ๋์ด ๋ช ๊ฐ ์์์ ๋๋ ๊ด์ฐฎ์์ง๋ง ์๊ฐ ์ ์ ๋์ด๋๋ฉด์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๋ณํฉ ์ ํ๋ก์ ํธ ํ์ผ์ ์ถฉ๋๋ ์์ฃผ ๋ฐ์ํ๊ณ , ์ด๋ป๊ฒ ๋ชจ๋์ ๋๋ ๊ฒ์ธ๊ฐ์ ๋ํ ์ ๋ฆฌ๊ฐ ์ ์ด๋ฃจ์ด์ง์ง ์์ ๋ชจ๋๊ฐ์ ์์กด์ฑ ๊ด๋ฆฌ๋ ๊ณ์ธต ํ์ ์ด ์ฝ์ง ์์์ก์ต๋๋ค. ๊ฒ๋ค๊ฐ ์์ง์ ๋ช ๋ง์ค ๋์ง ์์ง๋ง ์ ์ ๋ ๋น๋ ์๊ฐ์ด ์ค๋ ๋์ด๋๋ ๊ฒ๋ ๊ณ์์ ์ธ ์์ฐ์ฑ ์ ํ์ ์์ธ์ด ๋์ด์์ต๋๋ค.
๊ทธ๋์ ์ด๋ฐ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํด ์์ํ ์ ์ฒด ํ๋ก์ ํธ์ Tuist๋ฅผ ์ ์ฉํ๊ธฐ๋ก ํ์์ต๋๋ค.
Tuist๋ก ์ํ์ฑ ํ๋ก์ ํธ ๋ง๋ค๊ธฐ
์ด๋๋ถํฐ ์ด๋ป๊ฒ ์ ์ฉํ๋ฉด ์ข์๊น์? ์๋น์ค ์ ๋ฐ์ดํธ๊ฐ ์ง์์ ์ผ๋ก ์ด๋ฃจ์ด์ง๊ณ ์๋ ์ผ์ ์์ ์ฑ ์ ์ฒด๋ฅผ Tuist๋ก ์ ํํ๋ ๊ฒ์ ๋๋ฌด ํฌ๊ณ ์คํจํ๊ธฐ ์ฌ์ด ์๋์ฒ๋ผ ๋๊ปด์ก์ต๋๋ค. ๋จผ์ ์๊ณ ์ฑ๊ณตํ๊ธฐ ์ฌ์ด ์๋๋ฅผ ์ฐพ์์ต๋๋ค. ์ต๊ทผ์ ๋ง๋ SwiftUI ์ปดํฌ๋ํธ๊ฐ ๋ ์ฌ๋๊ณ ์์ ๋ ์ปดํฌ๋ํธ๋ฅผ ๋์์ด๋ ๋ฑ ๋ค๋ฅธ ๋๋ฃ๊ฐ ์ง์ ์ฌ์ฉํ ์ ์๋ ์ํ์ฑ์ ๋ง๋ค์ด๋ณด๋ ๊ฒ์ด ์ข๊ฒ ๋ค๋ผ๋ ์๊ฐ์ด ๋ค์์ต๋๋ค.
์์ ๋ ์ปดํฌ๋ํธ๋ ์๋์ ๊ฐ์ต๋๋ค
- pop up
- bottom sheet
- button
์ ์์ ๋ฌผ๋ค์ View์ modifierํํ๋ก ์์ ๋์๊ณ ์ํ์ฑ์ modifier๋ฅผ ์ฌ์ฉํ ์์ ๋ค์ ๋จ์ํ ๋ณด์ฌ์ฃผ๊ธฐ๋ง ํ๋ ์ฑ์ ๋๋ค.
Tuist๋ ์์ ์์ ๋น์ ์ต์ ๋ฒ์ ์ด๋ 4.12.1 ๋ฒ์ ์ ์ฌ์ฉํ์์ต๋๋ค
mise use tuist@4.12.1
์ํ์ฑ ๊ตฌ์กฐ
Tuist๋ก ๋ง๋ค ์ํ์ฑ์ ์์กด์ฑ ๊ทธ๋ํ๋ ์ ๋ง ๊ฐ๋จํฉ๋๋ค
์ฑ์์ UIComponent๋ชจ๋์ ๋ฐ๋ผ๋ณด๋ฉด์ bottom sheet, pop up, button๊ณผ ๊ด๋ จ๋ modifier๋ค์ ์ ๊ทผ์ด ๊ฐ๋ฅํ๊ฒ ๋๊ณ UIComponent๋ ํด๋น ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ๋ ํ์ํ ์๊น์ด๋ ํฐํธ, ์ด๋ฏธ์ง ๋ฑ์ ๋ฆฌ์์ค๋ค์ Resource๋ชจ๋์ ์ ๊ทผํ์ฌ ๊ฐ์ ธ์ต๋๋ค.
tuist edit
์ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด ๋์ค๋ Manifest๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค.
// swift-tools-version: 5.9
// Tuist/Package.swift
import PackageDescription
#if TUIST
ย ย import ProjectDescription
ย ย let packageSettings = PackageSettings(
ย ย ย ย productTypes: ["UIComponent": .framework,
ย ย ย ย ย ย ย ย ย ย ย ย "Resource": .framework]
ย ย )
#endif
let package = Package(
ย ย name: "SampleApp",
ย ย dependencies: [
ย ย ย ย .package(path: "../Packages/UIComponent"),
ย ย ย ย .package(path: "../Packages/Resource")
ย ย ]
)
packageSettings๋ฅผ ๋ณด์๋ฉด UIComponent์ Resource๋ .frameworkํ์ ์ผ๋ก ์ง์ ์ด ๋์ด์๋๋ฐ์. ์ธ๋ถ ํจํค์ง๋ฅผ ์ด๋ป๊ฒ ๊ฐ์ ธ์ฌ ์ง ์ง์ ํ๋ ๋ถ๋ถ์ ๋๋ค. ์ฌ๊ธฐ์ .framework๋ dynamic framework๋ก ํจํค์ง๋ฅผ ๊ฐ์ ธ์ฌ ๊ฒ์์ ๋ํ๋ ๋๋ค. ์ด๋ ๊ฒ ๊ฐ์ ธ์ฌ ๊ฒฝ์ฐ ๋งค๋ฒ app ์คํ ํ์ผ์ ํฌํจ์ํค๊ธฐ ์ํด ๋น๋ํ์ง ์๊ณ Bundle์ ์ฌ๋ ค์ ธ์ ๋ฐํ์ ์์ linking์ด ๋๊ธฐ ๋๋ฌธ์ ์ฑ ๋น๋ ์๊ฐ์ด ๋จ์ถ๋๋ ํจ๊ณผ๊ฐ ์์ต๋๋ค.
์ด์ ๋ ์ง์ SampleApp์ ์์กด์ฑ์ ๋ฃ์ด์ฃผ์ด์ผ ํ๋๋ฐ์. ์ ๋ง ๊ฐ๋จํฉ๋๋ค. SampleApp์ ๊ฒฝ์ฐ๋ ํ์ํ ์์กด์ฑ์ด UIComponent๋ชจ๋ ๋ฟ์ด๋ฏ๋ก ์์กด์ฑ์ UIComponent๋ง ์ถ๊ฐํ๋ฉด ๋๊ณ UIComponent์์ ์์์ Resource ๋ชจ๋์ ์ ๊ทผํ์ฃ . ์๋์ ๊ฐ์ด UIComponent๋ง ๋ณด๋๋ก ํ๋ฉด ๋์ ๋๋ค.
// Project.swift
import ProjectDescription
let project = Project(
ย ย name: "SampleApp",
ย ย targets: [
ย ย ย ย .target(
ย ย ย ย ย ย name: "SampleApp",
ย ย ย ย ย ย destinations: .iOS,
ย ย ย ย ย ย product: .app,
ย ย ย ย ย ย bundleId: "io.tuist.SampleApp",
ย ย ย ย ย ย infoPlist: .default,
ย ย ย ย ย ย sources: ["SampleApp/Sources/**"],
ย ย ย ย ย ย resources: ["SampleApp/Resources/**"],
ย ย ย ย ย ย dependencies: [
ย ย ย ย ย ย ย ย .external(name: "UIComponent") // ์ด ๋ถ๋ถ ํ์ค๋ก ๋!
ย ย ย ย ย ย ]
ย ย ย ย )
ย ย ]
)
์์ ๊ฐ์ด Manifest๋ฅผ ์์ฑํ๊ณ ์๋์ ๊ฐ์ด ๋ช ๋ น์ด๋ฅผ ์์ฑํ๋ฉด ์๋์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ถ ํ๋ก์ ํธ๊ฐ ์์ฑ๋ฉ๋๋ค
tuist install
tuist generate
Resource ๋ชจ๋
์ ์ฒด ๊ตฌ์กฐ๋ ์ก์๊ณ ๊ทธ๋ผ ์ ๋ฐฉ์์ผ๋ก ๊ตฌ์กฐ ๋ด๋ถ์ ํฌํจ๋ ๋ชจ๋์์ ๋ฆฌ์์ค๋ ์ด๋ป๊ฒ ๊ฐ์ ธ์ค๋์ง ์์์ผ ์ฌ์ฉํ ์ ์๋๋ฐ์. Tuist๋ Xcode์์ ์ฌ์ฉ๊ฐ๋ฅํ Resource๋ค์ ๋ํ ์ธํฐํ์ด์ค๋ค์ ์ ๊ณตํฉ๋๋ค. ์ด ์ธํฐํ์ด์ค๋ค์ ํด๋น ๋ชจ๋์ root์์น์ Derived๋๋ ํ ๋ฆฌ ์์ ์กด์ฌํ๋๋ฐ์. ํด๋น ๋ชจ๋์ Package.swift์ ์๋ target ์ค resource๊ฐ ์ง์ ๋ target์ ์ฝ์ด๋ค์ฌ TuistBundle+{ํ๊น์ด๋ฆ}.swiftํ์ผ์ ํํ๋ก ์์ฑํฉ๋๋ค.
๋ง์ฝ ์๋์ ๊ฐ์ Package.swiftํ์ผ์ด๋ผ๋ฉด
// Resource๋ชจ๋์ Package.swift
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.
...
targets: [
.target(
name: "FrommColor",
resources: [
.process("ColorAssets.xcassets")
]
),
.target(
name: "FrommFont",
resources: [
.process("Fonts")
]
),
...
]
...
Derived์๋ ์๋์ ๊ฐ์ด ๊ฐ target๋ณ Bundle์ ๋ํ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณต๋๊ณ ๊ฐ target๋ด์์ ํด๋น ์ธํฐํ์ด์ค์ ์ ๊ทผ์ด ๊ฐ๋ฅํฉ๋๋ค. ์ด๋ฐ ๊ธฐ๋ฅ์ Tuist ๋ด๋ถ์ ์ผ๋ก SwiftGen์ ์ฌ์ฉํด์ ์ด๋ฃจ์ด์ง๋ฏ๋ก ๊ฐ์์ค๋ฐ ๋ฐํ์ ํฌ๋์์ ๋ํ ์ํ์ ๋๋ ํ์๋ ์์ต๋๋ค.
Resource
| Derived
| InfoPlists
| ๋ชจ๋ ํ๊น์ ๋ํ plist
| Sources
| TuistBundle+FrommColor.swift
| TuistBundle+FrommFont.swift
์์ค์ฝ๋ ์์์๋ ์๋์ ๊ฐ์ด Color extension์ ์ ๊ณตํ๋ฉด ์ธ๋ถ ๋ชจ๋์์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๊ฒ๋ฉ๋๋ค
import SwiftUI
public extension Color {
ย ย // Text Color Tokens
ย ย static let textPrimary = Color("text_primary", bundle: Bundle.module)
ย ย static let textSecondary = Color("text_secondary", bundle: Bundle.module)
ย ย
ย ย static let textTertiary = Color("text_tertiary", bundle: Bundle.module)
ย ย
ย ย ...
๊ฒฐ๊ณผ๋ฌผ
๊ฒฐ๊ณผ๋ฌผ์ ์์ ๊ฐ์ต๋๋ค. ์ํ๋ ๋๋ก ์ ๋์ํ๋ค์! ์ด์ SwiftUI์ Canvas๊ฐ ์๋๋ผ ์ค์ ๋๋ฐ์ด์ค ์์์ ์์ ํ ๊ฒฐ๊ณผ๋ฌผ๋ค์ด ์ํ๋ ๋๋ก ๋์ํ๋์ง ์ก์์ผ๋ก ํ์ธํ ์ ์๊ฒ ๋์์ต๋๋ค. ์ ์ฒด์ฑ์ ๋น๋ํ์ง ์๊ณ ๋ฑ ํ์ํ ๋ชจ๋๋ง ๋น๋ํด์ ๋ง์ด์ฃ . ์ํ์ฑ์ ๋น๋ํ๋ ์๊ฐ์ 1์ด๋ ๊ฑธ๋ฆฌ์ง ์์์ต๋๋ค!
Tuist๊ฐ ์ต์ํด์ง๋ค๋ฉด ์ํ ํ๋ก์ ํธ๋ฅผ ๋ง๋๋๋ฐ ๊ฑธ๋ฆฌ๋ ์๊ฐ๋ 5๋ถ์ด ์ฑ ๊ฑธ๋ฆฌ์ง ์์ ๊ฒ์ผ๋ก ์๊ฐ๋ฉ๋๋ค.
๋ง์น๋ฉฐ
์ฌํด ์ด๋ถํฐ ์์๋ fromm ์ฑ์ ์ต์ ํ๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด๊ฐ๋ ์ฌ์ ์ ์ด์ Tuist๋ฅผ ๋์ ํ๋ฉฐ ํ์ธต ๋ ์ฒด๊ณ์ ์ผ๋ก ๋ณํด๊ฐ๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ด ์ฌ์ ์์๋ ์์ง ํด๊ฒฐ ํด์ผํ ๊ตต์งํ ์ฃผ์ ๋ค์ด ์ฌ๋ฟ ๋จ์์์ฃ . ๋ํ์ ์ผ๋ก Tuist๊ฐ ์ ์ํ๋ TMA ๊ตฌ์กฐ์ ํ์ฌ ์ฌ์ฉํ๊ณ ์๋ TCA๋ฅผ ์ ์ตํฉํ๋ ๋ฐฉ๋ฒ ๋ฑ์ด ์์ต๋๋ค.
๋ง๋ง์น ์์ง๋ง iOS ๊ฐ๋ฐ์๋ก์จ ๋งค์ฐ ํฅ๋ฏธ๋ก์ด ์ฃผ์ ์ด๊ธฐ๋ ํ์ฃ . ๊ณ ๊ฐ๋ค์๊ฒ ํ์ํ ๊ธฐ๋ฅ ๊ฐ๋ฐ์๋ง ์ง์คํ ์ ์๋๋ก ํ์ ์์ฐ์ฑ์ ์ด๋๊น์ง ๋์ด ์ฌ๋ฆด ์ ์์์ง ๊ธฐ๋๊ฐ ๋๊ธฐ๋ ํ๊ตฌ์. ํฅํ ์์ ๊ด๋ จ ๋์ด์ ๋ ์ข์ ๊ฒฐ๊ณผ๋ฌผ์ ๊ณต์ ํ ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
๋ถ์กฑํ์ง๋ง ๊ธด ๊ธ ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.