SwiftUI 14일 코스에서 우리는
@Observable 모델로 화면을 만들었다. 작은 화면에서는 그걸로 충분하다.
기능이 커지면 다른 질문이 생긴다 — "이 상태는 누가, 어디서, 왜 바꿨나?", "이 네트워크 요청은 어디서 시작되고 언제 취소되나?", "이 흐름을 어떻게 테스트하나?".
TCA(The Composable Architecture)는 이 질문들에 하나의 규칙으로 답한다. 이 코스는 하루 한 주제, 14일 동안 그 규칙과 대가를 순수 SwiftUI와 나란히 놓고 익힌다.
하루를 이렇게 쓴다
하루에 한 주제를 끝낸다. 한 챕터는 30분 안에 읽히게 썼고, 내용이 큰 주제(Day 7·10·11·12·13·14)는 압축하지 않고 1부·2부 두 챕터로 나눴다. 형식은 SwiftUI 14일 마스터와 같다.
⚖️ 매 섹션 SwiftUI와 비교
"@Observable로는 이렇게 / TCA로는 이렇게"를 코드로 나란히 둔다. TCA가 무엇을 대신 해 주고 대가가 무엇인지를 매번 확인한다.
✅ 컴파일하고, 실행까지 한 코드
예제 코드는 TCA 1.26.2 실제 라이브러리에 붙여 iOS 17 타깃으로 컴파일했다(매크로
@Reducer까지). 복습 정답과 미니 과제 정답은 swift test로 실제로 돌려 확인했다.🔮 코드 예측 · 🔁 복습
복습 박스마다 "이 액션을 보내면 상태가 어떻게 되나"를 먼저 맞히고 펼친다. 마지막 문항은 앞 내용을 다시 묻는다(1부는 지난 Day, 2부는 1부).
🛠 미니 과제
그날의 마지막 챕터에 있다. Preview 하나나
TestStore 테스트 하나로 끝나는 독립 과제다.14일 지도
| 단계 | 끝나면 할 수 있는 것 |
|---|---|
| 1 · 기초 (Day 1–4) | @Observable 모델로 짠 화면을 State·Action·Reducer로 옮기고, 비동기 작업과 취소를 Effect로, 폼을 바인딩으로 다룬다. |
| 2 · 조립과 의존성 (Day 5–7) | 작은 기능을 부모에 끼워 넣고(옵셔널·목록 포함), 네트워크·시계·UUID 같은 바깥 의존성을 교체 가능하게 설계한다. |
| 3 · 테스트 (Day 8–9) | 사용자 흐름 전체를 TestStore로 검증하고, 시간·의존성을 통제하고, 빡빡한 테스트와 느슨한 테스트를 골라 쓴다. |
| 4 · 흐름과 공유 (Day 10–12) | 시트·알림·푸시를 상태로 모델링하고, 여러 화면이 같은 데이터를 안전하게 나눠 쓰고 저장한다. |
| 5 · 실전 (Day 13–14) | 느려지는 지점을 찾아 고치고, 모듈을 나누고, UIKit과 섞고, 옛 TCA 코드를 읽어 현행 API로 옮긴다. |
Day 목록
Day 1 · 왜 TCA인가 약 29분
@Observable이 커질 때의 문제, TCA 5요소 지도, 단방향 흐름과 그 대가
Day 2 · 첫 기능 — Reducer와 Store 약 30분
@Reducer·@ObservableState·Store로 카운터 만들기, @Observable 버전과 나란히
Day 3 · Effect — 비동기와 취소 약 25분
.run으로 비동기 결과를 액션으로 되돌리고, cancellable·cancelInFlight로 멈춘다
Day 4 · 바인딩 약 25분
.sending·BindableAction·BindingReducer로 폼을 잇고, onChange·포커스·테스트까지
Day 5 · 조립 ① — Scope와 부모·자식 약 29분
Scope·store.scope로 자식을 끼우고, delegate 액션과 ifLet으로 부모·자식이 소통한다
Day 6 · 조립 ② — 컬렉션 약 25분
IdentifiedArray와 forEach로 행마다 리듀서·스토어를 붙이고 삭제·이동·재귀를 다룬다
Day 7 · 의존성 1부·2부 · 약 52분
Day 8 · 테스트 ① — TestStore 약 25분
TestStore로 상태 변화·받은 액션·이펙트 종료를 전부 증명하고, 시계를 가짜로 바꾼다
Day 9 · 테스트 ② — 실전 약 25분
non-exhaustive 통합 테스트, 의존성 중간 교체, Swift Testing, 공유 상태, 테스트 함정
Day 10 · 내비게이션 ① 트리 기반 1부·2부 · 약 55분
Day 11 · 내비게이션 ② 스택 기반 1부·2부 · 약 44분
Day 12 · 공유 상태 1부·2부 · 약 52분
Day 13 · 성능과 동시성 1부·2부 · 약 48분
Day 14 · 실전 구조와 총정리 1부·2부 · 약 54분
이 코스를 읽는 법
- SwiftUI 14일 코스를 마쳤다고 가정한다.
@State·@Observable·.task·NavigationStack이 헷갈리면 해당 SwiftUI Day를 먼저 본다(본문에 링크를 달아 두었다). - 기준은 TCA 1.26 · iOS 17+.
ViewStore·WithViewStore같은 옛 API는 Day 14 2부에서 "옛 코드 읽기"로만 다룬다. - 출처는 Point-Free 공식 자료와 개인 위키뿐이다. TCA 공식 문서·튜토리얼·케이스 스터디·예제 앱(1.26.2 고정 링크), 형제 라이브러리(swift-dependencies · swift-sharing · swift-navigation) 문서만 인용한다. SwiftUI 쪽 사실은 Apple 자료.
- 순서대로 읽는다. Day 8·9의 테스트는 Day 3(Effect)과 Day 7(의존성)을, Day 10·11은 Day 5(Scope)를 전제로 쓰였다.
🔑 시간이 부족하면
Day 2·3·5·8만 먼저 읽는다. Reducer·Effect·Scope·TestStore 네 개가 TCA의 뼈대이고, 나머지는 그 위에 얹는 도구다.
SwiftUI 코스와의 관계
| 주제 | SwiftUI 코스 | 이 코스 |
|---|---|---|
| 상태를 어디에 두나 | Day 3·5 — @State·@Observable | Day 1·2 — 기능 하나의 State, Store 하나 |
| 비동기 작업 | Day 12 — .task·취소 | Day 3 — Effect·취소 ID |
| 의존성 주입 | Day 13 — @Environment | Day 7 — @Dependency |
| 테스트 | Day 13 — @Observable 모델 테스트 | Day 8·9 — TestStore 전 흐름 테스트 |
| 내비게이션 | Day 10 — NavigationPath·sheet(item:) | Day 10·11 — 트리/스택 기반, 상태로 모델링 |
| 성능 | Day 9 2부 — 의존성·_printChanges | Day 13 — 액션 비용·관찰 범위 |