ReactorKit 개념
ReactorKit이란?
ReactorKit은 Flux 아키텍처의 단방향 데이터 흐름과 Reactive Programming(RxSwift)의 비동기 스트림 처리를 결합한 iOS 아키텍처 프레임워크 입니다.
ReactorKit은 위에서 서술한 것처럼 Reactive Programming의 개념을 채용했기 때문에 RxSwift와 함께 사용됩니다. 따라서, ReactorKit을 사용하려면 RxSwift에 대한 이해가 전제조건 입니다.
ReactorKit의 핵심 개념은 Reactor 입니다. Reactor는 Rx의 개념인 Observable과 함께 사용되며 비동기적으로 데이터를 처리하고, UI와의 상호작용을 쉽게 관리할 수 있도록 합니다.
이는 MVVM의 뷰 모델(View Model) 의 역할을 한다고 볼 수 있습니다.
다만 ReactorKit의 차이점은 ViewModel을 만들 때 그 안에서의 상태변경 방식을 강제된 규칙 (단방향 데이터 흐름 + 이벤트 모델링) 으로 고정해 둔 것입니다.
다음 그림은 ReactorKit의 작동 방식을 간단하게 표현한 것입니다.

사용자의 Action은 Reactor로, Reactor에서 방출된 State는 View로 Observable 스트림을 통해 전달됩니다. (단방향적 흐름)
View는 Action만 방출하며, Reactor는 State만을 방출합니다.
단방향적 흐름으로 인해 View와 비즈니스 로직을 분리할 수 있으며 모듈 간 결합도를 낮출 수 있습니다.
View와 Reactor
View
View는 데이터를 표시합니다. View Controller와 Cell은 하나의 뷰로 간주됩니다.
View는 사용자의 입력을 Action Stream에 바인딩하고, 뷰 State를 각 UI 컴포넌트에 바인딩 합니다.
뷰 레이어는 비즈니스 로직이 없고, 단순히 액션 스트림과 상태 스트림을 매핑하는 방식을 정의합니다. (Action과 State를 각각의 요소에 바인딩하는 역할만을 수행)
이를 적용하기 위해서는 View 프로토콜을 적용하는 것이 일반적입니다.

View 프로토콜은 다음과 같이 DisposeBag, Reactor, bind(reactor:)가 존재하고 disposeBag과 bind(reactor:) 메서드는 반드시 재정의 해주어야 합니다.
bind 내부에서
- UI 이벤트를 Action으로 변환(map)하여 Reactor의 입력(action)에 연결하고
- State 변화를 관찰하여 UI에 반영하는 바인딩을 정의합니다.
이를 예시 코드로 살펴보면 다음과 같습니다.
import UIKit
import ReactorKit
import RxCocoa
import RxSwift
final class CounterViewController: UIViewController, View {
@IBOutlet weak var valueLabel: UILabel!
@IBOutlet weak var increaseButton: UIButton!
@IBOutlet weak var decreaseButton: UIButton!
@IBOutlet weak var activityIndicatorView: UIActivityIndicatorView!
var disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
self.reactor = CounterViewReactor()
}
func bind(reactor: CounterViewReactor) {
// Action
increaseButton.rx.tap
.throttle(
.milliseconds(500),
latest: false,
scheduler: MainScheduler.instance
)
.map { CounterViewReactor.Action.increase }
.bind(to: reactor.action)
.disposed(by: disposeBag)
decreaseButton.rx.tap
.throttle(
.milliseconds(500),
latest: false,
scheduler: MainScheduler.instance
)
.map { CounterViewReactor.Action.decrease }
.bind(to: reactor.action)
.disposed(by: disposeBag)
// State
reactor.state.map { $0.value }
.distinctUntilChanged()
.map { "\($0)" }
.bind(to: valueLabel.rx.text)
.disposed(by: disposeBag)
}
}
Reactor

Reactor는 View 로부터 Action Stream을 전달 받아, 내부에서 mutate()와 reduce() 과정을 거쳐서 State Stream으로 바꾸어 다시 View에 전달합니다.
이를 위해서는 Reactor 프로토콜을 적용해야하고, 해당 프로토콜은 Action, Mutation, State 를 반드시 정의해야 합니다. 또한 State 초기 값 설정을 위한 initialState도 정의해야 합니다.
Action은 사용자 인터렉션을 나타내고, State는 뷰의 상태를 나타냅니다. Mutation은 Action과 State 사이의 브릿지(bridge) 역할을 합니다.
Reactor는 action stream과 state stream을 변환하는 두 단계인 mutate()와 reduce()를 수행합니다.
mutate()
mutate()는 Action 스트림을 Mutation 스트림으로 변환합니다. 변환된 Mutation 스트림은 reduce() 함수로 전달됩니다.
func mutate(action: Action) -> Observable<Mutation>
모든 사이드 이펙트(예: 비동기 작업, API call)은 여기서 수행됩니다.
reduce()
reduce()는 이전 State와 Mutation을 활용하여 새로운 State를 생성합니다.
func reduce(state: State, mutation: Mutation) -> State
View에서 reactor의 state를 바인딩 해둔 상태라면, 새로운 state가 방출될 때마다 바인딩 된 UI가 자동으로 업데이트 됩니다.
Reference
'Swift' 카테고리의 다른 글
| [ReactorKit] Reactor 살펴보기 (0) | 2026.02.04 |
|---|---|
| RxSwift - Observable 생성 (0) | 2026.01.14 |
| RxSwift - Observable, RxCocoa, Driver (0) | 2026.01.14 |
| ReactiveX Introduction 번역 (0) | 2025.10.01 |
| [Swift] iOS 앱의 라이프 사이클 관리 (0) | 2025.03.18 |