ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Redux Architecture (ReSwift)
    Swift/아키텍쳐 2021. 11. 18. 13:12

    https://github.com/ReSwift/ReSwift/

     

    GitHub - ReSwift/ReSwift: Unidirectional Data Flow in Swift - Inspired by Redux

    Unidirectional Data Flow in Swift - Inspired by Redux - GitHub - ReSwift/ReSwift: Unidirectional Data Flow in Swift - Inspired by Redux

    github.com

    ReSwift는 Swift의 단방향 데이터 흐름 아키텍처를 Redux 와 유사하게 구현한 것이다. ReSwift는 앱 구성 요소를 아래 세 가지로 분리하고 있다.

     

    • State : ReSwift 앱에서 전체 앱 상태는 데이터 구조에 명시적으로 저장됩니다. 이것은 복잡한 상태 관리 코드를 피하고 더 나은 디버깅을 가능하게 하며 훨씬 더 많은 이점을 제공합니다.
    • Views : ReSwift 앱에서 state가 변경되면 view가 업데이트됩니다. view는 현재 앱 상태의 단순한 시각화가 됩니다.
    • State Changes : ReSwift 앱에서는 동작을 통해서만 state 변경을 수행할 수 있습니다. Actions은상태 변경을 설명하는 작은 데이터 조각입니다. state가 변경될 수 있는 방식을 크게 제한함으로써 앱을 더 쉽게 이해하고 많은 공동 작업자와 더 쉽게 작업할 수 있습니다.

     

    • Store 는 전체 앱 상태를 단일 데이터 구조의 형태로 저장합니다. 이 State는 Store에 Actions를 전달해야만 수정할 수 있습니다. Store의 상태가 변경될 때마다 Store는 모든 관찰자에게 알립니다.
    • Actions 은 상태 변경을 설명하는 선언적 방법입니다. Actions에는 코드가 포함되어 있지 않으며 Store에서 사용하고 Reducers로 전달합니다. Reducers는 각 작업에 대해 다른 State 변경을 구현하여 Action을 처리합니다.
    • Reducers 는 현재 작업과 현재 앱 상태를 기반으로 새 앱 상태를 생성하는 순수한 기능을 제공합니다.

    => 앱의 상태는 State로 정의되고, Action을 통해 State가 변경된다. 그리고 이를 Reducer가 담당한다. (Reducer가 Action에 선언했던 함수를 구현하고 Reducer로 상태를 변경하면 Store에서 이를 감지해 모든 구독 객체들에게 알려주는 셈)

     

    어떤식인지 구조를 이해하기 위해 예제를 살펴보았다.

    import ReSwift
     
    let mainStore = Store<AppState>(
      reducer: counterReducer,
      state: nil
    )
     
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
      
      var window: UIWindow?
    
      ...
    }
    
    // mainStore 라는걸 보관한다. - Reducer와 state가 있음
    
    struct AppState: StateType {
      var counter: Int = 0
    }
    
    // State에는 값을 저장해둔다.
    
    struct CounterActionIncrease: Action {}
    struct CounterActionDecrease: Action {}
    
    // 이렇게 Action을 선언해둔다.
    
    func counterReducer(action: Action, state: AppState?) -> AppState {
        // if no state has been provided, create the default state
        var state = state ?? AppState()
        
        switch action {
        case _ as CounterActionIncrease:
            state.counter += 1
        case _ as CounterActionDecrease:
            state.counter -= 1
     
        return state
    }
    
    // 이렇게 Reducer에 Action 선언해 둔걸 구현하고, state를 변경한다.
    
    // 아래 최종 사용!
    
    class CounterViewController: UIViewController, StoreSubscriber {
    
        @IBOutlet var counterLabel: UILabel!
    
        override func viewWillAppear(_ animated: Bool) {
            mainStore.subscribe(self)
        }
    
        override func viewWillDisappear(_ animated: Bool) {
            mainStore.unsubscribe(self)
        }
    
        func newState(state: AppState) {
            counterLabel.text = "\(state.counter)"
        }
    
        @IBAction func increaseButtonTapped(_ sender: UIButton) {
            mainStore.dispatch(
                CounterActionIncrease()
            )
        }
    
        @IBAction func decreaseButtonTapped(_ sender: UIButton) {
            mainStore.dispatch(
                CounterActionDecrease()
            )
        }
    }
    
    // 저장소를 mainStore 구독하고 상태 변화가 일어날때마다 textlabel을 변경한다.

     

    Counter 예제

    https://github.com/ReSwift/CounterExample

     

    위의 예제에서 다루지 않은 부분인 Router는 https://github.com/ReSwift/ReSwift-Router 이런식으로 구성되어 있는것 같다.

     

    내 생각

    아키텍쳐를 공부할수록, 아키텍쳐보다 이 아키텍쳐가 무엇을 강조하고 있는가가 중요하다는것을 느끼게 된다.

    이 아키텍쳐는 Action을 통해 정의한 Reducer를 통해서만 상태를 바꾸겠다는게 핵심인거같다.

    (State, Action) -> State

     

    아래는 왜 만들어지게 되었는가 동기에 대한 내용이다. 그리고 몇가지 과제 에 대한 내용도 있다. (단점이라고 볼 수 있는) 만약 도입을 생각하고 있다면 꼭 읽어보는게 좋을것 같다.

    https://academy.realm.io/posts/benji-encz-unidirectional-data-flow-swift/

    728x90

    'Swift > 아키텍쳐' 카테고리의 다른 글

    Ribs - 로그인편  (0) 2021.10.15
    Ribs 예제 도입기 - Root편  (0) 2021.10.15
    Ribs 예제 도입기 - Ribs 설치 편  (0) 2021.10.15
    Ribs 에 대해서...  (0) 2021.09.30
    Clean Architecture  (0) 2021.06.18

    댓글

Designed by Tistory.