Tuist로 구성된 멀티 모듈 iOS 프로젝트 템플릿입니다.
MultiModuleTemplate/
├── Workspace.swift
├── Tuist.swift
├── Projects/
│ ├── App/ # 메인 애플리케이션
│ ├── Presentation/
│ │ └── Presentation/ # 화면 및 ViewModel 구성
│ ├── Domain/ # 🔥 도메인 계층 (비즈니스 로직 + Protocol)
│ │ ├── Entity/ # 도메인 엔티티 + Entity Protocol
│ │ ├── UseCase/ # 비즈니스 로직 + UseCase Protocol
│ │ ├── DomainInterface/ # Domain 계층 인터페이스 모듈
│ │ └── DataInterface/ # Data 계층 인터페이스 모듈
│ ├── Data/ # 데이터 계층 (데이터 접근 + Model)
│ │ ├── Model/ # 데이터 전송 객체 (DTO, API Response)
│ │ ├── Repository/ # Repository 구현체 (Domain Protocol 구현)
│ │ ├── API/ # REST API 클라이언트
│ │ └── Service/ # 데이터 처리 서비스
│ ├── Network/ # 네트워크 계층
│ │ ├── Networking/ # 네트워크 기본 설정 및 클라이언트
│ │ └── Foundations/ # 네트워크 기반 유틸리티
│ ├── Core/
│ │ ├── Core/ # 핵심 공통 모듈
│ │ └── ThirdParty/ # Core 레벨 외부 라이브러리
│ └── Shared/
│ ├── DesignSystem/ # 공통 UI 컴포넌트, 폰트 등
│ ├── Shared/ # 공통 공유 모듈
│ └── Utill/ # 공통 유틸리티
├── Tuist/
│ ├── Package.swift
│ └── ProjectDescriptionHelpers/
└── Plugins/
# 1. TuistTool 컴파일 (최초 1회만)
swiftc TuistTool.swift -o tuisttool
# 2. 새 프로젝트 생성 (대화형으로 이름 설정)
./tuisttool newproject# Tuist 4.97.2 최신 명령어
tuist install # 의존성 설치 (새로운 명령어)
tuist generate # 프로젝트 생성
tuist build # 빌드
tuist test # 테스트
# 또는 TuistTool 사용 (권장)
./tuisttool build # clean + install + generate 한번에- App: 메인 애플리케이션 모듈 (앱 진입점 및 설정)
- Presentation: ViewController, ViewModel 등 UI 로직 담당
- Entity: 순수 도메인 엔티티 + Entity 관련 Protocol
- UseCase: 비즈니스 로직 구현체 + UseCase Protocol
- DomainInterface: Domain Entity를 참조하는 인터페이스 모듈
- DataInterface: Data Model을 참조하는 인터페이스 모듈
- Model: DTO 구현체 (Domain Entity로 변환 기능 포함)
- Repository: Repository 구현체 (Domain Protocol 구현)
- API: REST API 클라이언트 및 Endpoint 정의
- Service: 데이터 처리 서비스 (캐싱, 변환 등)
- Networking: 네트워크 기본 설정 및 HTTP 클라이언트
- Foundations: 네트워크 기반 유틸리티
- DesignSystem: 공통 UI 컴포넌트, 폰트, 색상 등 디자인 시스템
- Shared: 공통 공유 모듈 및 기본 설정
- Utill: 날짜, 문자열, 로깅 등 공용 유틸리티
Presentation → Domain (UseCase Protocol)
↓
Domain/UseCase → Domain (Repository Protocol)
↓
Data/Repository → Domain (Entity + Repository Protocol)
↓
Data/Model → Domain (Entity 변환)
- iOS 17.0+
- Xcode 26.0.1+
- Swift 6.0+
- Tuist 4.97.2 (최신 최적화 적용)
- ComposableArchitecture: 상태 관리
- WeaveDI: 의존성 주입
- TCACoordinators: TCA 기반 네비게이션
- FlowStacks: SwiftUI 네비게이션
이 템플릿은 Tuist 4.97.2의 최신 기능들을 완전히 활용하여 최적화되었습니다:
- 새로운
install명령어:fetch대신 더 빠르고 안정적인 의존성 관리 - 바이너리 캐시: 의존성을 framework로 설정하여 빌드 캐시 활용
- Swift 6.0 지원: 최신 Swift 언어 기능 및 성능 개선
tuist inspect implicit-imports: 암시적 의존성 자동 검사tuist inspect code-coverage: 코드 커버리지 분석- 정적 부작용 경고: 잠재적 의존성 문제 사전 감지
- Tuist.swift: 새로운 설정 파일 형식 (
Config.swift→Tuist.swift) - Package.swift: 최적화된 패키지 설정 및 성능 향상
- Settings API: 최신 타입 안전 설정 방식
이 프로젝트는 Domain 계층에 Protocol과 구현을 통합하여 Clean Architecture를 구현합니다:
// Domain/Entity/User.swift
public struct User {
public let id: String
public let name: String
public let email: String
public init(id: String, name: String, email: String) {
self.id = id
self.name = name
self.email = email
}
// 비즈니스 로직
public var displayName: String {
return name.isEmpty ? "Unknown User" : name
}
}
// Domain/Repository/UserRepository.swift
public protocol UserRepository {
func fetchUser(id: String) async throws -> User
func saveUser(_ user: User) async throws
}
// Domain/UseCase/GetUserUseCase.swift
public protocol GetUserUseCase {
func execute(id: String) async throws -> User
}
public final class GetUserUseCaseImpl: GetUserUseCase {
private let repository: UserRepository
public init(repository: UserRepository) {
self.repository = repository
}
public func execute(id: String) async throws -> User {
return try await repository.fetchUser(id: id)
}
}// Data/Model/UserModel.swift
import Domain
public struct UserModel: Codable {
public let user_id: String
public let user_name: String
public let user_email: String
// ✅ Model → Entity 변환 (Data가 Domain 의존)
public func toEntity() -> User {
return User(
id: user_id,
name: user_name,
email: user_email
)
}
}
// Data/Repository/UserRepositoryImpl.swift
import Domain
public final class UserRepositoryImpl: UserRepository {
private let apiService: APIService
public init(apiService: APIService) {
self.apiService = apiService
}
public func fetchUser(id: String) async throws -> User {
let model: UserModel = try await apiService.fetchUser(id: id)
return model.toEntity() // Model → Entity 변환
}
}✅ Domain 통합 방식:
Presentation → Domain (Protocol + Entity)
↓
Data → Domain (Protocol 구현 + Entity 사용)
모든 계층이 Domain을 중심으로 의존
// 관련 Protocol과 구현이 같은 모듈에
// Domain/UseCase/GetUserUseCase.swift
public protocol GetUserUseCase {
func execute(id: String) async throws -> User
}
public final class GetUserUseCaseImpl: GetUserUseCase {
// 구현체도 같은 파일에
}// Mock 구현이 매우 간단
final class MockUserRepository: UserRepository {
func fetchUser(id: String) async throws -> User {
return User(id: "mock", name: "Mock User", email: "mock@test.com")
}
}
// 테스트에서 쉽게 사용
let mockRepo = MockUserRepository()
let useCase = GetUserUseCaseImpl(repository: mockRepo)
let user = try await useCase.execute(id: "test")- Domain: Protocol + Entity + UseCase 통합 관리
- Data: Domain Protocol 구현 + Model 변환
- 모듈 수 감소: Interface 별도 모듈 불필요
프로젝트 전용 CLI 도구입니다. Tuist 명령을 래핑하고, 새 프로젝트 생성, 모듈 스캐폴딩 등을 지원합니다.
# 컴파일
swiftc TuistTool.swift -o tuisttool
# 사용법
./tuisttool <command>| Command | 설명 |
|---|---|
newproject |
🚀 새 프로젝트 생성: ProjectConfig.swift 이름 변경, 디렉토리 자동 생성, 완전 자동화된 프로젝트 생성 |
generate |
tuist generate 실행 |
build |
clean → install → generate 순서로 실행 (Tuist 4.97.2 최적화) |
install |
새로운! tuist install 실행 (의존성 설치) |
clean |
tuist clean 실행 |
cache |
tuist cache 실행 (바이너리 캐시 생성) |
reset |
강력 클린: 모든 캐시 삭제 후 install → generate 재실행 |
inspect |
새로운! 사용 가능한 분석 도구 표시 |
inspect-imports |
새로운! 암시적 의존성 검사 |
inspect-coverage |
새로운! 코드 커버리지 분석 |
moduleinit |
모듈 스캐폴딩 마법사: 자동 의존성 삽입 및 Interface 폴더 생성 |
-
newproject (완전히 새로워짐!)
- 🎯 ProjectConfig.swift 자동 수정: 프로젝트 이름, 번들 ID, 팀 ID 자동 변경
- 📁 필수 디렉토리 사전 생성: MultiModuleTemplateTests, FontAsset 등 자동 생성
- 🔍 이름 변경 검증: 변경 완료 후 실제로 적용되었는지 확인
- 🧹 기존 워크스페이스 정리: 충돌 방지를 위한 기존 파일 삭제
- ✅ 완전 자동화: 대화형 또는 명령어 인자로 완전 자동 생성
-
build (Tuist 4.97.2 최적화)
- 내부적으로
clean → install → generate호출 (fetch대신install사용)
- 내부적으로
-
install (새로운 명령어)
- Tuist 4.97.2의 새로운
tuist install명령어 실행 - 의존성 설치 및 해결 담당
- Tuist 4.97.2의 새로운
-
inspect 시리즈 (새로운 분석 도구들)
inspect: 사용 가능한 분석 도구 목록 표시inspect-imports: 암시적 의존성 검사 (enforceExplicitDependencies 대체)inspect-coverage: 코드 커버리지 분석
-
reset (개선됨)
~/Library/Caches/Tuist,~/Library/Developer/Xcode/DerivedData,.tuist,.build,Tuist/Dependencies삭제- 이후
install → generate순차 실행 (최신 워크플로우)
-
moduleinit
Plugins/DependencyPlugin/ProjectDescriptionHelpers/TargetDependency+Module/Modules.swift에서 모듈 타입 및 케이스 목록을 파싱합니다.Plugins/DependencyPackagePlugin/ProjectDescriptionHelpers/DependencyPackage/Extension+TargetDependencySPM.swift에서 SPM 의존성 목록을 파싱합니다.- 입력 받은 의존성들을
Projects/<Layer>/<ModuleName>/Project.swift의dependencies: [영역에 자동 삽입합니다. - Domain 계층 생성 시,
Interface/Sources/Base.swift를 템플릿으로 생성하도록 선택 가능.
⚠️ 파일 경로 전제
- 위 파서는 특정 경로의 파일 구조/포맷을 기대합니다. 경로가 다르거나 파일 포맷이 변경되면 파싱이 실패할 수 있습니다.
- 경로가 다르다면
availableModuleTypes(),parseModulesFromFile(),parseSPMLibraries()의 파일 경로를 프로젝트에 맞게 수정하세요.
"MultiModuleTemplate" 대신 원하는 이름으로 프로젝트를 생성할 수 있습니다.
# 대화형 입력
./tuisttool newproject
# 명령어 인자로 바로 설정
./tuisttool newproject MyAwesomeApp --bundle-id com.company.appexport PROJECT_NAME="MyAwesomeApp"
export BUNDLE_ID_PREFIX="com.company.awesome"
tuist generatemkdir MyNewProject && cd MyNewProject
tuist scaffold multi-module-project --name MyNewProject| 항목 | 설명 | 기본값 |
|---|---|---|
PROJECT_NAME |
앱 이름 | MultiModuleTemplate |
BUNDLE_ID_PREFIX |
번들 ID 접두사 | io.Roy.Module |
TEAM_ID |
개발팀 ID | N94CS4N6VR |
# 대화형 생성 (권장)
./tuisttool newproject
# 명령어로 한번에 생성
./tuisttool newproject MyApp --bundle-id com.company.myapp --team-id ABC123# Tuist 4.97.2 최적화된 워크플로우
./tuisttool build # clean → install → generate
./tuisttool test # 테스트 실행
# 코드 품질 검사
./tuisttool inspect-imports # 암시적 의존성 검사
./tuisttool inspect-coverage # 코드 커버리지 분석# 강력한 클린 (모든 캐시 삭제)
./tuisttool reset
# 의존성 재설치
./tuisttool install
# 프로젝트 구조 분석
tuist graph --format pdf --path ./graph.pdf# 새 모듈 생성 (자동 의존성 설정)
./tuisttool moduleinit
# 특정 모듈만 포커스
tuist focus <모듈명># CI 파이프라인
./tuisttool reset # 모든 캐시 클린
./tuisttool build # clean → install → generate
./tuisttool test # 테스트 실행
./tuisttool inspect-imports # 의존성 검증# CI와 동일한 환경에서 로컬 테스트
./tuisttool reset && ./tuisttool build && ./tuisttool test- 브랜치를 생성합니다 (
git checkout -b feature/my-feature) - 변경사항을 커밋합니다 (
git commit -m 'Add feature') - 브랜치에 푸시합니다 (
git push origin feature/my-feature) - Pull Request를 생성합니다
이 프로젝트는 MIT License 하에 배포됩니다.
