ReactorKit 사용해보기 (1)

이건준·2022년 6월 19일
0

1. 문제제기

  • connect라는 앱을 팀원과 함께 만들게되면서 MVVM 패턴을 도입하기로 하였고 이 중 ViewModel 파트를 RxSwift로 만들기로 하였으나 개발자마다 너무나 다른 스타일로 인해 각자 맡은 화면의 ViewModel코드가 많이 상이할까봐 나름 비슷한 구조로 만들고자 ReactorKit을 사용하기로 결정이 났다

  • 처음 ReactorKit을 사용해보았는데 기본적인 사용방법과 내가 생각할때의 불편했던점을 기술해보고자 한다

2. Reactor 기본구조

  • ReactorKit은 View를 통해 받은 Input을 Action으로 받는다
  • 이 Action을 mutate함수를 이용하여 Mutation으로 변경하고
  • 이 Mutation은 각 Action마다 여러가지의 Mutation으로 변경되어질 수 있다
  • reduce함수를 이용하여 변경되어진 여러가지의 Mutation에 따라 State로 만들어서 다시 화면으로 뿌려주는 형식이다
class FruitReactor: Reactor {
    // MARK: Actions
    enum Action {
        case apple
        case banana
        case grapes
    }
    
    // MARK: State
    struct State {
        var fruitName: String
        var isLoading: Bool
    }
    
    //MARK: Mutations
    enum Mutation { // Action이 Mutation으로 변경, 이 Mutation이 State로 생성될것임
        case changeLabelApple
        case changeLabelBanana
        case changeLabelGrapes
        case setLoading(Bool)
    }
    
    let initialState: State
    
    init() {
        self.initialState = State(fruitName: "선택되어진 과일없음", isLoading: false)
    }
    
    // MARK: Actions -> Mutation
    func mutate(action: Action) -> Observable<Mutation> {
        switch action {
            case .apple:
                return Observable.concat([
                    Observable.just(Mutation.setLoading(true)),
                    Observable.just(Mutation.changeLabelApple)
                        .delay(.milliseconds(500),
                               scheduler: MainScheduler.instance),
                    Observable.just(Mutation.setLoading(false))
                ])
            case .banana:
                return Observable.concat([
                    Observable.just(Mutation.setLoading(true)),
                    Observable.just(Mutation.changeLabelBanana)
                        .delay(.milliseconds(500),
                               scheduler: MainScheduler.instance),
                    Observable.just(Mutation.setLoading(false))
                ])
            case .grapes:
                return Observable.concat([
                    Observable.just(Mutation.setLoading(true)),
                    Observable.just(Mutation.changeLabelGrapes)
                        .delay(.milliseconds(500),
                               scheduler: MainScheduler.instance),
                    Observable.just(Mutation.setLoading(false))
                ])
        }
    }
    
    // MARK: Mutation -> State
    func reduce(state: State, mutation: Mutation) -> State {
        var state = state
        switch mutation {
        case .changeLabelApple:
            state.fruitName = "사과"
        case .changeLabelBanana:
            state.fruitName = "바나나"
        case .changeLabelGrapes:
            state.fruitName = "포도"
        case .setLoading(let val):
            state.isLoading = val
        }
        
        return state
    }
}
  • 위 코드와 같이 Reactor를 짜준다, Reactor는 프로토콜로써 어느정도 일관성있게 코드를 짜게 제공해주기때문에 앞서 말한 ReactorKit선택에 있어 바람직할것이라 생각한다

3. 내가 생각하는 단점 및 해야할 점

  • 아직 많이 미숙하고 모르겠지만 쓰면서 느꼈던것이 State라는 구조체가 하나밖에 없다는 점이였다
  • 기존에 RxSwift같은 경우는 화면단위로 하나의 ViewModel을 만들더라도 여러가지의 데이터를 View에 뿌려줄 수 있었는데 ReactorKit은 미리 정의된 하나의 State만을 보낼 수 있다는 점이 불편했었다
  • 같은 팀원께 듣기를 @Pulse를 이용하여 동일한 State가 나오지않게하게끔 하는 방법이 있다고 하였다, RxSwift와 distinctUntilChanged와 유사한 기능같은데 한번 써봐야알것같다

0개의 댓글