본문 바로가기

IOS

Swift - ReactorKit

Android, iOS 앱을 만들면서 많은 디자인 패턴들이 존재한다. 그중에 가장 많이 사용하는것이 MVVM 패턴이다.

여기서 MVVM 패턴이란?

     MVVM은 Model - View - ViewModel의 약자로 소프트웨어 아키텍처 패턴입니다. 

      간단하게.. 화면단을 보여주는 뷰 와 비즈니스 로직을 담당하는 뷰 모델 을 분리하여 프로젝트가 간결해지는 특징을 가지고 있습니다.

ReactorKit 같은 경우 해당 MVVM 을 좀더 규칙적 이게 사용할수 있게 도와주는 라이브러리 입니다.

실제 많은 기업에서 현재 적용중인 디자인 패턴 입니다.

 

1. View는 Action(사용자 입력 등)을 Reactor에게 전달한다

2. Reactor는 전달받은 Action에 따라 비즈니스 로직을 수행한다. 

3. 그 후 Reactor는 상태를 변경하여 View에게 전달한다. 

 

좀~더 자세히 보면

1. Reactor - mutate() 함수

       - View 에서 던져준 Action 스트림을 Mutation 스트림으로 변환

       - 해당 프로세스에서 비즈니스 로직 처리후 Mutation 을 reduce() 함수로 던져줍니다.

    2. Reactor - reduce() 함수

       - Mutation을 받은후 다음상태를 반환합니다.

       - 반환 한값을 View 에서 구독을 받은 다음 UI 변경을 처리합니다.

 

해당 예제는 ReactorKit 상에 있는 예제이며 더욱 심화된 내용은 추가로 포스팅 하도록 하겠습니다.


1. View

  1-1. plusButton 클릭 했을경우 Reactor.Action(plus) 액션을 전달 합니다.

  1-2. minusButton 클릭 했을경우 Reactor.Action(minus) 액션을 전달 합니다.

plusButton.rx.tap
  .map{ ViewReactor.Action.plus }
  .bind(to: reactor.action)
  .disposed(by: disposeBag)

minusButton.rx.tap
  .map{ ViewReactor.Action.minus }
  .bind(to: reactor.action)
  .disposed(by: disposeBag)

2. Action

  2-1. 뷰에서 액션을 요청 받은 plus, minus에 대해 Mutation 에 전달 합니다.

enum Action {
	case plus
	case minus
}

enum Mutation {
	case setPlus
	case setMinus
}

func mutate(action: Action) -> Observable<Mutation> {
	switch action {
		case .plus:
			return Observable.just(Mutation.setPlus)
		case .minus:
			return Observable.just(Mutation.setMinus)
	}
}

 


3. Action

   3-1. mutate 에서 던져준 setPlus, setMinus 에 대해 처리 한후 값을 그대로 반환한다.

struct State {
  var value : Int = 0
}

func reduce(state: State, mutation: Mutation) -> State {
  var state = state
  switch mutation {
    case .setPlus:
    	state.value+=1
    case .setMinus:
    	state.value-=1
  }
  return state
}

4. View

    4-1. state 에서 던져준 각자의 값들을 구독을 받아 UI 변경 처리를 진행 합니다.

reactor.state.map{ $0.value }
  .subscribe(onNext : {
  value in
  self.valueLabel.text = "\(value)"
}).disposed(by: disposeBag)

전체소스 (View)

import UIKit
import RxSwift
import RxCocoa
import RxGesture
import ReactorKit

class ViewController: UIViewController {

    let reactor = ViewReactor()
    let disposeBag = DisposeBag()
    
    @IBOutlet weak var plusButton: UIButton!
    @IBOutlet weak var minusButton: UIButton!
    @IBOutlet weak var valueLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        bind(reactor: reactor)
    }
    
    func bind(reactor : ViewReactor) {
        plusButton.rx.tap
            .map{ ViewReactor.Action.plus }
            .bind(to: reactor.action)
            .disposed(by: disposeBag)
        
        minusButton.rx.tap
            .map{ ViewReactor.Action.minus }
            .bind(to: reactor.action)
            .disposed(by: disposeBag)
        
        reactor.state.map{ $0.value }
            .subscribe(onNext : {
                value in
                self.valueLabel.text = "\(value)"
            }).disposed(by: disposeBag)
    }
}

전체소스 (Reactor)

import Foundation
import RxSwift
import RxCocoa
import RxGesture
import ReactorKit

class ViewReactor: Reactor {
    
    let initialState = State()
    
    enum Action {
        case plus
        case minus
    }
    
    struct State {
        var value : Int = 0
    }
    
    enum Mutation {
        case setPlus
        case setMinus
    }
    
    func mutate(action: Action) -> Observable<Mutation> {
        switch action {
            case .plus:
                return Observable.just(Mutation.setPlus)
            case .minus:
                return Observable.just(Mutation.setMinus)
        }
    }
    
    func reduce(state: State, mutation: Mutation) -> State {
        var state = state
        switch mutation {
            case .setPlus:
                state.value+=1
            case .setMinus:
                state.value-=1
        }
        return state
    }
}

UI, 비즈니스 로직을 완전히 분리 함으로써 추후 유지보수 할경우에 문제가 생기더라도 찾기가 쉽습니다.

해당 라이브러리는 iOS 뿐만 아니라 Android 에서도 사용 가능합니다.

두가지 플랫폼에서 사용하면 서로의 언어를 몰라도 로직을 읽는데 도움이 될꺼라고 생각합니다.

 

참고 : https://github.com/ReactorKit/ReactorKit

 

ReactorKit/ReactorKit

A library for reactive and unidirectional Swift applications - ReactorKit/ReactorKit

github.com

https://medium.com/styleshare/reactorkit-시작하기-c7b52fbb131a

 

ReactorKit 시작하기

오늘은 StyleShare에서 ReactorKit을 사용한지 딱 1년이 되는 날입니다. ReactorKit은 반응형 단방향 앱을 위한 프레임워크로, StyleShare와 Kakao를 비롯한 여러 기업에서 사용하고 있는 기술입니다.

medium.com

 

'IOS' 카테고리의 다른 글

Swift - SceneDelegate  (0) 2021.07.10
Swift - ReactorKit2  (0) 2021.07.06
Swift - Photos + CollectionView + Drag and Drops  (0) 2021.05.30
Swift - Photos + CollectionView + Gesture Multiple Select  (0) 2021.03.07
프로젝트에 SwiftLint를 달아보자  (0) 2021.03.01