HIT해

Redux와 MVVM : 단방향 vs 양방향 데이터 흐름 정리 본문

Swift/CS

Redux와 MVVM : 단방향 vs 양방향 데이터 흐름 정리

힛해 2025. 5. 25. 01:42
728x90

Redux와 MVVM: 단방향 vs 양방향 데이터 흐름 완전 정리

Redux는 주로 React와 같은 프론트엔드 프레임워크에서 사용되는 상태 관리 라이브러리입니다.
단방향 데이터 흐름(One-way Data Flow)을 핵심 원칙으로 하며, 상태 관리 로직을 뷰와 명확히 분리해 복잡한 앱에서도 상태를 예측 가능하고 일관성 있게 관리할 수 있도록 도와줍니다.
이러한 아키텍처는 React뿐 아니라 Swift 등 다양한 환경에서도 채택되고 있습니다.

 

Flux 패턴

Flux는 Facebook이 MVC 패턴의 복잡성과 예측 불가능성을 해결하기 위해 고안한 단방향 데이터 흐름 아키텍처 패턴입니다.
Flux는 Action → Dispatcher → Store → View 구조를 가지며, 데이터가 한 방향으로만 흐르도록 설계되었습니다.
Redux는 Flux의 개념을 발전시켜 단일 StoreReducer(순수 함수)를 도입하여 상태 관리의 예측성과 단순성을 더욱 강화한 구현체입니다.

 

Flux와 Redux의 차이

  • Flux는 여러 Store와 Dispatcher를 사용하지만, Redux는 하나의 전역 Store만 사용합니다.
  • Redux에서는 Dispatcher가 없고, 상태 변경은 Reducer라는 순수 함수로만 처리합니다.
  • Flux는 Store가 직접 상태를 변경할 수 있지만, Redux는 상태 불변성을 강제하여 항상 새로운 상태 객체를 반환합니다.

 

Redux의 데이터 흐름

  1. 상태 변경이 필요한 이벤트가 발생하면, 변경될 정보를 담은 Action 객체가 생성됩니다.
  2. 이 Action 객체는 dispatch 함수를 통해 전달됩니다.
  3. dispatch 함수는 Action을 Reducer 함수로 전달합니다.
  4. Reducer 함수는 현재 상태와 Action을 받아 새로운 상태를 반환하고, Store에 저장합니다.
  5. 상태가 변경되면 View(React 등)는 자동으로 다시 렌더링됩니다.

즉, Action → Dispatch → Reducer → Store → View 순서로 데이터가 단방향으로 흐릅니다.
이러한 구조 덕분에 데이터의 흐름이 명확하고, 예측 및 디버깅이 쉽습니다.

 

Redux vs MVVM 비교

구분 Redux (단방향 데이터 흐름) MVVM (Model-View-ViewModel)
데이터 흐름 단방향(One-way) 양방향(Two-way binding 지원 가능)
구조 Action → Dispatch → Reducer → Store → View View ↔ ViewModel ↔ Model
상태 관리 전역 Store 하나에서 모든 상태 관리 ViewModel이 각 View의 상태를 관리
상태 변경 Action을 통해서만 가능, Reducer(순수 함수) 필요 ViewModel이 직접 Model을 업데이트
대표 사례 Combine, RxSwift, React + Redux Android, WPF, Vue, Angular 등
목적 복잡한 상태의 예측 가능하고 일관된 관리 UI와 비즈니스 로직의 명확한 분리, 바인딩 활용
바인딩 명시적(구독, useSelector 등) 데이터 바인딩(자동 UI 갱신)

왼쪽이 Flux, 오른쪽이 MVC 패턴입니다.
Redux와 MVVM의 데이터 흐름도 위와 같이 유사한 차이가 있습니다.

 

Swift에서의 단방향 데이터 흐름 예시 (TCA 기반)


import ComposableArchitecture
import SwiftUI

// State 정의
struct ChatState: Equatable {
    var message: String = ""
}

// Action 정의
enum ChatAction: Equatable {
    case messageChanged(String)
    case sendMessage
}

// Reducer 정의
let chatReducer = Reducer<ChatState, ChatAction, Void> { state, action, _ in
    switch action {
    case let .messageChanged(newMessage):
        state.message = newMessage
        return .none
    case .sendMessage:
        // 메시지 전송 로직 등
        state.message = ""
        return .none
    }
}

// View
struct ChatView: View {
    let store: Store<ChatState, ChatAction>
    var body: some View {
        WithViewStore(self.store) { viewStore in
            VStack {
                TextField(
                    "메시지 입력",
                    text: viewStore.binding(
                        get: \.message,
                        send: ChatAction.messageChanged
                    )
                )
                Button("전송") {
                    viewStore.send(.sendMessage)
                }
            }
        }
    }
}

 

이 구조에서 상태 변경은 반드시 Action → Reducer → State의 단방향 흐름을 따릅니다.

 

SwiftUI의 binding을 사용하지만, 실제 데이터 변경은 액션을 통해 리듀서에서만 처리됩니다.

 

Swift의 양방향(MVVM) 예시


import SwiftUI

class ChatViewModel: ObservableObject {
    @Published var message: String = ""
}

struct ChatView: View {
    @ObservedObject var viewModel = ChatViewModel()
    var body: some View {
        VStack {
            TextField("메시지 입력", text: $viewModel.message)
            Button("전송") {
                // 메시지 전송 로직
                viewModel.message = ""
            }
        }
    }
}

 

MVVM에서는 @Published@Binding을 통해 View와 ViewModel 간에 값이 자동으로 동기화(양방향 바인딩)됩니다.

  • Redux/Flux는 단방향 데이터 흐름(상태 변경은 오직 액션과 리듀서로만 가능)
  • MVVM은 View와 ViewModel 사이에 양방향 데이터 바인딩이 가능
  • Swift의 RxSwift, Combine 등 리액티브 프레임워크는 Redux와 유사하게 단방향 흐름을 지향하지만, @State, @Binding 등은 MVVM의 양방향 바인딩에 가깝다

 

단방향 데이터 흐름과 양방향 데이터 흐름의 장단점

구분 단방향 데이터 흐름 양방향 데이터 흐름
장점
  • 데이터 흐름이 명확하고 예측 가능하다
  • 디버깅과 데이터 추적이 쉽다
  • 성능 최적화에 유리하다 (불필요한 DOM 조작 최소화)
  • 컴포넌트의 독립성과 재사용성이 높다
  • 대규모 애플리케이션에서 유지보수가 쉽다
  • 코드가 간결해지고, 작성량이 적다
  • 모델과 뷰가 자동으로 동기화되어 편리하다
  • 폼 입력 등 사용자 상호작용이 많은 UI에 유리하다
단점
  • UI 입력값을 상태에 반영하려면 이벤트 핸들러 등 추가 코드가 필요하다
  • 양방향에 비해 코드가 길어질 수 있다
  • 데이터 변화가 많을 때 성능 저하가 발생할 수 있다
  • 데이터 흐름이 복잡해져 디버깅이 어렵다
  • 대규모 프로젝트에서 상태 추적이 힘들고, 예기치 않은 버그가 발생할 수 있다

 

정리
단방향 데이터 흐름은 복잡한 애플리케이션에서 데이터 추적과 유지보수에 유리하며, 양방향 데이터 흐름은 간단한 폼이나 실시간 입력 등 사용자와의 상호작용이 많은 UI에서 편리하다.

'Swift > CS' 카테고리의 다른 글

[iOS/TCA] ifLet  (0) 2024.08.31
[iOS/SwiftUI] refreshable  (0) 2024.08.31
[iOS/SwiftUI] NavigationStack 공식문서 뜯어보기  (1) 2024.08.31
[iOS/SwiftUI] TCA finish() 알아보기  (0) 2024.08.30
[iOS/SwiftUI] defer  (0) 2024.08.30