프로젝트의 전체 구조와 설계 철학
Projects/
├── App/ # 앱 진입점
│ ├── Sources/
│ │ ├── TwixApp.swift # @main
│ │ ├── AppRootReducer.swift
│ │ └── AppRootView.swift
│ └── Resources/
│
├── Feature/ # 기능 모듈 (UI + 비즈니스 로직)
│ ├── Auth/
│ ├── Onboarding/
│ ├── MainTab/
│ └── Sources/ # Feature Root
│
├── Domain/ # 도메인 로직
│ └── Auth/
│
├── Core/ # 핵심 인프라
│ ├── Network/
│ └── Logging/
│
└── Shared/ # 공통 유틸
├── DesignSystem/
└── ThirdPartyLib/
- 앱의 진입점 (
@main) - Feature들을 조립하여 최종 앱 구성
- AppRootReducer에서 화면 전환 관리
- UI + 비즈니스 로직
- Interface/Sources 분리
- 독립적으로 실행 가능 (Example 타겟)
- 도메인 모델 (Entity, VO)
- 비즈니스 규칙
- Feature와 독립적
- 네트워크, 로깅 등 인프라
- Feature에서 사용하는 공통 기능
- Core/Network, Core/Storage는 singleton을 사용하지 않고 DI 가능한 구조로 제공합니다.
- 디자인 시스템
- 써드파티 라이브러리 래핑
Feature/Auth/
├── Interface/Sources/ # 타입 정의만 (public)
└── Sources/ # 실제 구현 (internal)
장점:
- 빌드 시간 최적화
- 의존성 최소화
- 테스트 용이
예외 (App 직접 조립 Feature):
- Auth / Onboarding / MainTab은 App에서 직접 Path를 관리하는 중간 관리자 Feature로 취급합니다.
- 위 Feature는 Interface/Implementation 분리 및 ViewFactory 강제 규칙에서 예외입니다.
- App은 위 Feature를
makeView(_:)없이 직접 조립할 수 있습니다. - 위 Feature는 내부 하위 Feature 조립 시 Implementation 모듈을 직접 import 할 수 있습니다.
- 위 Feature는 자식 Feature를 Interface-only
makeView(_:)대신 직접 생성할 수 있습니다.
그 외 Feature:
- Interface 모듈만 import합니다.
- 외부 조립은 Interface layer의
makeView(_:)또는 동등한 factory를 통해서만 이뤄집니다.
모든 의존성은 TCA Dependency Container로 주입합니다.
- 모든 모듈에서 TCA Dependency Container를 사용합니다.
- 계층 간 연결은 Interface 모듈만 노출하며, liveValue는 Implementation 모듈에서 제공합니다.
- 의존성 조립은 App/Feature Root에서
.withDependency로 명시적으로 수행합니다.
@Dependency(\.authLoginClient) var authLoginClientView를 직접 노출하지 않고 Factory로 생성:
@Dependency(\.authViewFactory) var authViewFactory
authViewFactory.makeView(store)사용자 → View → Action → Reducer → State 변경 → View 업데이트
↓
Effect (비동기 작업)
↓
새로운 Action
예시: 로그인 플로우
1. 사용자가 "Apple로 로그인" 버튼 탭
↓
2. AuthView: store.send(.appleLoginButtonTapped)
↓
3. AuthReducer: state.isLoading = true
↓
4. Effect: authLoginClient.login(.apple)
↓
5. 성공 시: send(.loginResponse(.success(result)))
↓
6. AuthReducer: return .send(.delegate(.loginSucceeded))
↓
7. AppRootReducer: state.path = .mainTab(...)
↓
8. MainTabView 렌더링
- Reducer 패턴 - Reducer 구현 방법
- Dependency Injection - 의존성 주입
- ViewFactory 패턴 - ViewFactory 구현
- 팀 규칙 - 팀 합의사항
작성일: 2026-01-12