HIT해
Redux와 MVVM : 단방향 vs 양방향 데이터 흐름 정리 본문
Redux와 MVVM: 단방향 vs 양방향 데이터 흐름 완전 정리
Redux는 주로 React와 같은 프론트엔드 프레임워크에서 사용되는 상태 관리 라이브러리입니다.
단방향 데이터 흐름(One-way Data Flow)을 핵심 원칙으로 하며, 상태 관리 로직을 뷰와 명확히 분리해 복잡한 앱에서도 상태를 예측 가능하고 일관성 있게 관리할 수 있도록 도와줍니다.
이러한 아키텍처는 React뿐 아니라 Swift 등 다양한 환경에서도 채택되고 있습니다.
Flux 패턴
Flux는 Facebook이 MVC 패턴의 복잡성과 예측 불가능성을 해결하기 위해 고안한 단방향 데이터 흐름 아키텍처 패턴입니다.
Flux는 Action → Dispatcher → Store → View 구조를 가지며, 데이터가 한 방향으로만 흐르도록 설계되었습니다.
Redux는 Flux의 개념을 발전시켜 단일 Store와 Reducer(순수 함수)를 도입하여 상태 관리의 예측성과 단순성을 더욱 강화한 구현체입니다.
Flux와 Redux의 차이
- Flux는 여러 Store와 Dispatcher를 사용하지만, Redux는 하나의 전역 Store만 사용합니다.
- Redux에서는 Dispatcher가 없고, 상태 변경은 Reducer라는 순수 함수로만 처리합니다.
- Flux는 Store가 직접 상태를 변경할 수 있지만, Redux는 상태 불변성을 강제하여 항상 새로운 상태 객체를 반환합니다.
Redux의 데이터 흐름
- 상태 변경이 필요한 이벤트가 발생하면, 변경될 정보를 담은 Action 객체가 생성됩니다.
- 이 Action 객체는 dispatch 함수를 통해 전달됩니다.
- dispatch 함수는 Action을 Reducer 함수로 전달합니다.
- Reducer 함수는 현재 상태와 Action을 받아 새로운 상태를 반환하고, Store에 저장합니다.
- 상태가 변경되면 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의 양방향 바인딩에 가깝다
단방향 데이터 흐름과 양방향 데이터 흐름의 장단점
구분 | 단방향 데이터 흐름 | 양방향 데이터 흐름 |
---|---|---|
장점 |
|
|
단점 |
|
|
정리
단방향 데이터 흐름은 복잡한 애플리케이션에서 데이터 추적과 유지보수에 유리하며, 양방향 데이터 흐름은 간단한 폼이나 실시간 입력 등 사용자와의 상호작용이 많은 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 |