안녕하세요! 피피아노입니다 🎵
최근 관심 있는 회사들의 채용 공고와 기술 블로그를 살펴보다가 TCA(The Composable Architecture)를 사용하는 곳들이 생각보다 많다는 것을 알게 되었습니다. 특히 제가 지원하고 싶은 회사에서도 TCA를 사용하고 있었습니다.
단순히 이력서에 한 줄 추가하기 위한 공부가 아니라, 실제로 해당 회사와 관련된 프로젝트를 TCA로 구현해보면서 이 기술을 제대로 이해하고 싶었습니다. 그래서 본격적으로 TCA를 학습하게 되었고, 이번 글에서는 그 과정에서 배운 내용들을 정리해보려 합니다.
TCA란?
TCA는 The Composable Architecture의 줄임말로, Point-Free에서 일관성 있고 이해하기 쉬운 방식으로 애플리케이션을 구축하기 위해 제작한 "오픈소스 아키텍처 라이브러리" 입니다.
SwiftUI, UIKit 등에서 사용할 수 있으며, 모든 Apple 플랫폼(iOS, macOS, iPadOS, visionOS, tvOS, watchOS)에서 사용할 수 있습니다.
https://github.com/pointfreeco/swift-composable-architecture
GitHub - pointfreeco/swift-composable-architecture: A library for building applications in a consistent and understandable way,
A library for building applications in a consistent and understandable way, with composition, testing, and ergonomics in mind. - pointfreeco/swift-composable-architecture
github.com
TCA의 핵심 철학은 크게 3가지로 나눌 수 있습니다.
- 단방향 데이터 흐름: 데이터가 한 방향으로만 흐르도록 하여 예측 가능한 상태 관리 구현
- 합성 가능성: 작은 컴포넌트를 조합하여 큰 기능을 만들 수 있는 구조
- 테스트 용이성: 부작용을 명시적으로 관리하여 테스트하기 쉬운 코드 작성
TCA의 핵심 개념
TCA는 State, Action, Reducer, Effect 이렇게 4가지 핵심 구성 요소로 이루어져 있습니다.
1. State
State는 애플리케이션의 현재 상태를 나타내는 데이터 타입입니다.
struct CounterState: Equatable {
var count = 0
var isLoading = false
}
2. Action
사용자 액션이나 시스템 이벤트 등 상태를 변경할 수 있는 모든 동작을 나타냅니다.
enum CounterAction {
case incrementButtonTapped
case decrementButtonTapped
case resetButtonTapped
}
3. Reducer
Action이 주어졌을 때 현재 State를 다음 State로 변환하는 로직을 담당합니다. 이때 Effect(부작용)도 함께 반환할 수 있습니다.
let counterReducer = Reducer<CounterState, CounterAction, CounterEnvironment> { state, action, environment in
switch action {
case .incrementButtonTapped:
state.count += 1
return .none
case .decrementButtonTapped:
state.count -= 1
return .none
case .resetButtonTapped:
state.count = 0
return .none
}
}
4. Effect
네트워크 요청, 타이머, 파일 읽기 등의 부작용을 나타냅니다. Effect는 외부 세계와의 상호작용을 명시적으로 표현합니다.
case .fetchDataButtonTapped:
state.isLoading = true
return environment.apiClient
.fetchData()
.map(CounterAction.dataResponse)
.eraseToEffect()
왜 TCA를 사용할까?
TCA를 공부하면서 가장 궁금했던 것은 기존 방식으로도 충분히 앱을 만들 수 있는데 "굳이 왜 이렇게 복잡하게?"였습니다. 하지만 학습을 진행하면서 TCA가 해결하려는 문제들을 이해하게 되었습니다.
1. 상태 관리의 명확성
일반적인 iOS 개발에서는 상태가 여기저기 흩어져 있습니다.
// 기본적인 방식
class MyViewController: UIViewController {
var count = 0
var userName: String?
var isLoading = false
// 이 값들이 언제, 어디서 바뀌는지 추적하기 어려움
func someMethod() {
count += 1
fetchData()
}
}
하지만 TCA에서는 모든 상태를 하나의 구조체로 관리합니다. 앱이 현재 어떤 상태인지 한눈에 파악할 수 있다는 장점이 있습니다.
// TCA 방식
struct AppState: Equatable {
var count = 0
var userName: String?
var isLoading = false
}
// 상태는 오직 Reducer에서만 변경
2. 예측 가능한 데이터 흐름
TCA의 데이터 경로는 단방향이기 때문에 앱 흐름을 알기 쉽습니다.
사용자 액션 → Action 발생 → Reducer가 State 변경 → UI 자동 업데이트
이러한 흐름 덕분에 "어디서 이 값이 바뀐 거지?"라는 디버깅 상황이 크게 줄어듭니다. 모든 상태 변경은 Reducer를 거치므로, 브레이크포인트 하나면 모든 상태 변경을 추적할 수 있습니다.
3. 테스트 작성이 쉬워짐
TCA에서는 비즈니스 로직만 순수하게 테스트할 수 있어서 테스트하기 훨씬 쉽다는 장점이 있습니다.
// TCA 테스트
func testCounter() {
let store = TestStore(
initialState: CounterState(),
reducer: counterReducer,
environment: ()
)
store.send(.increment) {
$0.count = 1 // 상태가 정확히 이렇게 변했는지 검증
}
}
4. 모듈화하여 조합
작은 Reducer들을 레고 블록처럼 조합하여 큰 기능을 만들 수 있습니다.
// 작은 기능들
let loginReducer = Reducer<LoginState, LoginAction, LoginEnvironment> { ... }
let profileReducer = Reducer<ProfileState, ProfileAction, ProfileEnvironment> { ... }
// 조합하여 큰 기능 만들기
let appReducer = Reducer.combine(
loginReducer.pullback(...),
profileReducer.pullback(...)
)
각 기능을 독립적으로 개발하고 테스트한 뒤, 나중에 조합할 수 있어서 대규모 앱 개발에 유리합니다.
TCA를 사용하는 경우
위와 같은 장점이 있다고 해서 TCA가 모든 프로젝트에 적합하다는 것은 아닙니다. 팀단위로 중대형 이상의 프로젝트를 개발하고 장기간 유지보수가 필요하며 복잡한 상태 관리가 필요한 앱이라면 TCA가 많은 도움이 되지만 간단한 앱이거나 빠른 MVP 개발이 필요한 경우 개인 토이 프로젝트(TCA 학습 목적이 아니라면) TCA가 오히려 과할 수 있습니다.
TCA 적용 방법
TCA를 프로젝트에 적용하기 위해서는 몇 가지 간단한 준비가 필요합니다.
우선 Xcode에서 프로젝트 파일을 만들었다면 아래 화면처럼 File > Add Package Dependencies 를 눌러줍니다.

그리고 나서 오른쪽 상단 검색창에 swift-composable-architecture를 검색하고 오른쪽 하단에 Add Package 버튼을 눌러서 적용해주시면 됩니다!

이것 말고도 TCA에 관해서 설명할 내용이 많지만 내용이 너무 길어지고 딥해지기 때문에 더 꼼꼼하게 공부해서 다시 블로그에 업로드 해보도록 하겠습니다!
감사합니다.
잘못된 내용이 있거나 더 좋은 내용 피드백은 언제나 환영합니다!
궁금하신 부분은 댓글로 질문 부탁드립니다!
'Apple > iOS' 카테고리의 다른 글
| [iOS] Object Capture: 온디바이스 3D 모델 제작하기 (1) | 2025.09.11 |
|---|---|
| [iOS/CoreML] Core ML로 구현하는 온디바이스 AI (2) | 2025.05.11 |
| [iOS] CocoaPods 알아보기 (8) | 2024.08.13 |
| [iOS] Live Activity 알아보기 (0) | 2024.08.09 |
| [iOS] RESTful API 완벽 이해하기 (0) | 2024.07.22 |
