ReactorKit의 상태 관리와 이벤트 처리 메커니즘

  1. 아키텍처 개요 ReactorKit은 단방향 데이터 흐름(Unidirectional Data Flow)과 반응형 프로그래밍을 기반으로 하는 아키텍처 프레임워크입니다. Reactor는 상태 관리의 핵심 객체로서, View로부터 Action을 수신하고 정의된 비즈니스 로직을 통해 State를 방출하는 단방향 제어 흐름(View → Action → Reactor → State → View)을 구현합니다.

  2. 상태 관리 구조와 문제점 State는 불변성(Immutability) 원칙을 준수하기 위해 값 타입인 구조체로 구현됩니다. 이는 단일 진실 공급원(Single Source of Truth)을 보장하지만, 부수 효과(Side Effect)를 초래할 수 있습니다.

    struct State {
        var presentationEvent: Void? = nil
        var contentData: String? = nil
    }
    
    
  3. 값 타입의 특성으로 인해, 특정 프로퍼티만 변경하더라도 전체 State 객체가 새로 인스턴스화되어 방출됩니다. 이는 불필요한 State Emission과 View 리렌더링을 유발할 수 있습니다.


해결 방안

  1. Reducer에서 State 초기화

    func reduce(state: State, mutation: Mutation) -> State {
        var newState = state
        switch mutation {
        case .triggerEvent(let data):
            newState.presentationEvent = data
            newState.presentationEvent = nil  // Explicit state reset
        }
        return newState
    }
    
    
  2. @Pulse Property Wrapper 활용
    
    struct State {
        @Pulse var presentationEvent: Event?  // Transient state
        var persistentData: String?  // Persistent state
    }
    
    // UI에서 바인딩 예시
     reactor.pulse(\\.$showErrorAlert)  // $ prefix 사용
            .compactMap { $0 }
            .observe(on: MainScheduler.instance)
            .subscribe(onNext: { [weak self] message in
                self?.showAlert(message: message)
            })
            .disposed(by: disposeBag)
    

Reducer 내에서 상태를 직접 초기화하는 방식은 상태 변화에 대한 명시적 제어(Explicit Control)를 제공합니다. 그러나 다음과 같은 한계점으로 인해 채택하지 않았습니다.

@Pulse는 ReactorKit이 제공하는 특수 목적 Property Wrapper로, 일회성 이벤트 처리를 위해 최적화되었습니다.


@Pulse 프로퍼티 래퍼의 동작 원리