[Swift] ReactorKit 첫걸음: 간단한 카운터 앱 만들기
[Swift] ReactorKit 첫걸음: 간단한 카운터 앱 만들기
ReactorKit은 iOS 애플리케이션의 반응형 프로그래밍을 위한 아키텍처 라이브러리로, React 패턴을 기반으로 합니다. 이 튜토리얼에서는 ReactorKit을 사용하여 간단한 카운터 앱을 만드는 방법을 단계별로 설명하겠습니다. 이 과정을 통해 ReactorKit의 기본 개념과 주요 구성 요소를 익히게 될 것입니다.
1. ReactorKit 소개
ReactorKit은 React 패턴을 적용한 아키텍처로, 애플리케이션 상태 관리와 뷰의 로직을 깔끔하게 분리하는 데 중점을 둡니다. 주요 구성 요소는 다음과 같습니다.
- Reactor: 애플리케이션의 상태와 로직을 관리합니다.
- View: 사용자 인터페이스를 담당하며, Reactor의 상태 변화를 구독합니다.
- Action: 사용자가 발생시키는 이벤트들을 정의합니다.
- Mutation: Action이 발생했을 때 상태를 어떻게 변경할 것인지 정의합니다.
- State: 앱의 현재 상태를 나타냅니다.
이제 이 개념들을 실제 코드에서 어떻게 사용하는지 살펴보겠습니다.
2. 프로젝트 설정
먼저, Xcode에서 새로운 프로젝트를 생성하고, ReactorKit
과 RxSwift
, RxCocoa
를 CocoaPods
나 Swift Package Manager
를 이용해 설치합니다. Podfile
에 다음 내용을 추가한 뒤 pod install
을 실행합니다:
rubypod 'ReactorKit' pod 'RxSwift' pod 'RxCocoa'
3. 기본 구조 설정
Reactor 생성
Reactor
는 앱의 상태와 로직을 관리하는 역할을 합니다. 우리는 카운터 값의 증가와 감소를 처리할 것이므로, 다음과 같이 CounterReactor
를 정의합니다.
swiftimport ReactorKit import RxSwift class CounterReactor: Reactor { // Action: 사용자 이벤트 정의 enum Action { case increase case decrease } // Mutation: 상태 변화를 정의 enum Mutation { case increaseValue case decreaseValue } // State: 앱의 상태 정의 struct State { var value: Int } // 초기 상태 설정 let initialState: State = State(value: 0) // Action을 받아서 Mutation으로 변환 func mutate(action: Action) -> Observable<Mutation> { switch action { case .increase: return Observable.just(Mutation.increaseValue) case .decrease: return Observable.just(Mutation.decreaseValue) } } // Mutation을 받아서 State로 변환 func reduce(state: State, mutation: Mutation) -> State { var newState = state switch mutation { case .increaseValue: newState.value += 1 case .decreaseValue: newState.value -= 1 } return newState } }
View 설정
이제 ViewController
를 설정하여 인터페이스와 Reactor의 상태를 연결합니다.
swiftimport UIKit import ReactorKit import RxSwift import RxCocoa class CounterViewController: UIViewController, View { var disposeBag = DisposeBag() let increaseButton = UIButton() let decreaseButton = UIButton() let valueLabel = UILabel() override func viewDidLoad() { super.viewDidLoad() self.view.addSubview(increaseButton) self.view.addSubview(decreaseButton) self.view.addSubview(valueLabel) self.reactor = CounterReactor() } func bind(reactor: CounterReactor) { // Action: 버튼 클릭 시 액션 발생 increaseButton.rx.tap .map { Reactor.Action.increase } .bind(to: reactor.action) .disposed(by: disposeBag) decreaseButton.rx.tap .map { Reactor.Action.decrease } .bind(to: reactor.action) .disposed(by: disposeBag) // State: 상태 변화 시 UI 업데이트 reactor.state.map { $0.value } .distinctUntilChanged() .map { "\($0)" } .bind(to: valueLabel.rx.text) .disposed(by: disposeBag) } }
4. UI 구성
Storyboard
또는 코드로 버튼과 레이블을 추가하여 레이아웃을 구성합니다. 이 글에서는 코드로 레이아웃을 구성하는 방법을 보여드리겠습니다.
swiftoverride func viewDidLoad() { super.viewDidLoad() self.setupView() self.reactor = CounterReactor() } func setupView() { // 버튼 및 레이블 속성 설정 increaseButton.setTitle("+", for: .normal) increaseButton.setTitleColor(.blue, for: .normal) decreaseButton.setTitle("-", for: .normal) decreaseButton.setTitleColor(.red, for: .normal) valueLabel.text = "0" valueLabel.textAlignment = .center // 레이아웃 설정 let stackView = UIStackView(arrangedSubviews: [decreaseButton, valueLabel, increaseButton]) stackView.axis = .horizontal stackView.distribution = .fillEqually self.view.addSubview(stackView) stackView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor), stackView.widthAnchor.constraint(equalToConstant: 200) ]) }
5. 최종 확인
이제 앱을 실행하여 버튼을 클릭할 때마다 카운터 값이 증가하고 감소하는지 확인해 볼 수 있습니다. 정상적으로 작동한다면, 성공적으로 ReactorKit을 이용하여 간단한 카운터 앱을 만든 것입니다.
결론
이번 튜토리얼에서는 ReactorKit의 기본 개념과 구성 요소를 살펴보고, 이를 활용하여 간단한 카운터 앱을 만들어 보았습니다. ReactorKit을 사용하면 상태 관리와 뷰 로직을 깔끔하게 분리할 수 있어 유지 보수와 확장이 용이합니다. 이 글을 통해 ReactorKit의 기초를 이해하고, 더 복잡한 애플리케이션에도 적용할 수 있는 준비가 되었기를 바랍니다.