리덕스와 zutstand 전역 상태 라이브러리에 대해서 알아보던 중에 두 라이브러리 모두 Flux 패턴이라는 공통점이 있었습니다. 이런 전역 상태 라이브러리들도 패턴들이 다양한 것으로 알고 있는데, 나중에 프로젝트의 특성에 맞게 알맞는 라이브러리를 도입하면 좋겠다 생각했습니다!
Redux 혹은 Zustand 를 사용하는데 Flux 패턴이라는 중요한 개념을 모르고 사용하는 것도 좀 아닌것같고,, 내가 면접관이라면 물어볼 것 같기도 하다...
Flux 패턴
Flux 패턴은 메타(Meta)에서 2014년 페이스북 F8 컨퍼런스 MVC 모델의 단점을 보완하기 위해 등장한 아키텍처입니다. Flux 패턴은 단방향 데이터 흐름으로 애플리케이션의 상태를 관리하는 방식입니다.
간단하게 먼저 말하자면, Flux 패턴은 액션(Action)이 발생하면 디스패처(Dispatcher)를 거쳐 스토어(Store) 상태가 업데이트되고, 뷰(View)가 이에 따라 변경되는 방식입니다.
이제 각 단계에서 처리하는 부분에 대해서 간단하게 살펴보겠습니다.
1. 액션(Action)
액션(Action)이란 데이터 변경 요청을 스토어에 전달하기 위한 메시지 역할이라고 생각하시면 됩니다. 애플리케이션에서 일어나면 특정한 이벤트, 예를 들면 '버튼 클릭' , '폼 제출' 등등을 정의하고 전달하는 객체입니다.
{
type: "ADD_TODO",
payload: { text: "새로운 할 일" }
}
일반적으로 type 이라는 필드로 이벤트 종료를 지정하고, 상태 변화에 필요한 데이터를 payload로 담아서 전달합니다.
2. 디스패처(Dispatcher)
디스패처(Dispathcer)는 이제 액션을 스토어로 보내는 중앙 허브같은 역할을 합니다. 만약에 여러 스토어가 있는 경우, 특정 액션을 어떤 스토어가 처리할지 결정하며, 모든 액션이 스토어로 잘 전달되도록 보장합니다.
디스패처는 모든 액션을 중앙에서 관리하고, 스토어에 적절히 분배하는 방식으로 동작하고, Redux에서 dispatch() 함수가 디스패처를 역할을 대신합니다!
3. 스토어(Store)
스토어(Store)는 상태저장소로서, 애플리케이션의 모든 상태를 저장하고 관리하는 곳입니다. 액션이 디스패처를 통해 전달되면, 이제 스토어는 액션의 타입과 데이터를 기반으로 상태를 업데이트합니다.
액션이 전달되면, 스토어는 해당 핵션을 처리하는 함수를 통해 상태를 변경합니다. 그리고 뷰(View)에게 상태가 변경되었음을 알립니다.
위 액션에서 ADD_TODO가 전달이 되면, 스토어는 기존 상태에 새로운 할 일을 추가하고, 상태를 업데이트합니다.
4. 뷰(View)
뷰(View)는 리액트의 컴포넌트에 해당합니다. 스토어에서 뷰에게 상태가 변경되었음을 알려주면 최상위 부모 View(Controller View)는 Store에서 데이터를 받아와 자식 View에게 보냅니다. 즉 스토어의 상태를 구독하고, 렌더링합니다. 상태가 변경되면 뷰는 새로운 상태를 반영하여 다시 렌더링합니다.
이러한 4가지 구조는 단방향 데이터 흐름이 이루어지며, 데이터가 한 방향으로만 전달되기 떄문에 애플리케이션의 상태관리가 단순해지고, 예측 가능하게 유지됩니다.
Flux 패턴은 왜 나온 걸까? MVC 모델
Flux 패턴은 기존 MVC의 문제를 해결하고자 제안되었습니다.
MVC 모델이란?
MVC(Model-View-Controller) 모델은 전통적인 애플리케이션 아키텍처로, UI와 어플리케이션 로직을 분리하는 데 주로 사용됩니다.
MVC 모델의 각각의 구성 요소는 다음과 같은 역할을 합니다. 이는 Flux 패턴과는 다르게 모델과 뷰가 서로 영향을 주고받는 양방향 특성을 띄고 있습니다.
모델의 데이터가 변경되면 뷰가 자동으로 업데이트되고, 반대로 뷰에서 사용자가 어떤 조작을 하면 그 변화가 모델에 반영됩니다. 이로 인해 데이터 흐름이 양방향으로 발생합니다.
즉 이런 양방향 데이터 흐름은 작은 애플리케이션에서는 효과적일 수 있지만, 규모가 커질수록 관리가 어려워진다는 단점이 있습니다.
1. Model
모델(Model)은 애플리케이션의 데이터과 비즈니스 로직을 관리합니다. 데이터의 상태를 유지하며, 수정하거나 가져오는 작업을 수행하고 변경된다면, 뷰(View)에 알려 화면에 반영시킵니다.
2. View
뷰(View)는 사용자에게 화면을 보여주는 UI 요소입니다. 모델에서 데이터를 받아와 렌더링하며, 사용자가 상호작용할 수 있도록 구성됩니다.
3. Controller
컨트롤러(Controller)는 사용자의 입력을 받아 모델과 뷰를 연결하는 역할을 합니다. 컨트롤러는 사용자의 이벤트를 감지하고, 해당 요청을 모델에 전달하거나 뷰를 업데이트하는 상호작용을 관리합니다.
그럼 뭐가 문제인데?
MVC 모델은 Model에 데이터를 저장하고, Controller를 이용하여 Model의 데이터를 관리(CRUD)합니다. 여기서 사용자가 View를 통해 데이터를 입력하면 View 역시 Model을 업데이트하여 데이터가 양방향으로 흐르게 됩니다.
양방향성의 문제점으로는 높은 의존성입니다. 모델과 뷰가 강하게 연결되어 있어, 한 쪽이 변경되면 다른쪽도 영향을 받는 경우가 많습니다. 강한의존성은 코드의 재사용성과 확장성을 낮추며, 새로운 기능을 추가하거나 수정할 때 수정 범위가 커질 수 있습니다.
두번째로는 유지보수의 어려움입니다. 이는 규모가 커질 수록 서로 상호작용하는 모델, 뷰, 컨트롤러가 늘어나며 복잡성이 증가합니다. 이는 유지보수성을 떨어뜨리는 이유중 하나입니다.
Redux, Zustand 그리고 Flux 패턴
Redux와 Zustand는 모두 Flux 패턴을 기반으로 한 상태관리 라이브러리입니다. 이는 단반향 데이터 흐름을 통해 애플리케이션 상태를 예측 가능하도록 돕습니다.
Redux
Redux는 가장 널리 사용되는 Flux 패턴 기반 상태 관리 라이브러리로, 엄격한 상태 관리와 예측 가능한 데이터 흐름을 보장합니다. 간단하게 Redux의 Flux 패턴 구조를 설명하겠습니다.
- Action : 상태 변경을 요청하는 객체로, type과 payload 속성으로 구성됩니다. 이를 통해 상태를 업데이트할 목적과 데이터를 전달합니다.
- Reducer : Redux의 스토어는 리듀서라는 함수에 의해 상태관리합니다. 리듀서는ㄴ Action을 받아 상태를 업데이트하고, 불변성 유지와 순수 함수 원칙을 따릅니다.
- Store : 애플리케이션의 전체 상태가 저장되는 곳으로, 상태가 변화할 때 이를 자동으로 반영하여 UI가 업데이트됩니다.
- Dispatch : Action을 Store에 전달하여 상태를 변경하는 방법입니다.
Zustand
Zustand는 Redux에 비해 가볍고 단순한 상태 관리 라이브러리로, 보다 간편한 Flux 패턴을 제공합니다. Zustand는 Redux의 복잡성을 줄이고, 상태를 간단하게 구성하고 업데이트할 수 있도록 설계되었습니다.
- React Hook 기반 : Zustand는 React의 useStore 훅을 사용하여 상태를 접근하고 업데이트하므로, 리액트와 호환성이 좋고 코드가 무엇보다 간결합니다.
- 성능 최적화 : Zustand는 상태가 변경된 부분만 렌더링을 업데이트하도록 최적화되어 있어, 대규모 상태 관리에서도 성능이 좋다고 생각합니다.
- 상태와 업데이트 로직 통합 : Zustand에서는 상태와 업데이트 로직이 하나의 스토어에 정의됩니다. 이를 통해 Redux처럼 리듀서와 액션을 분리하지 않고, 간단한 함수형 코드로 상태를 관리할 수 있습니다.
결론
Flux 패턴은 기존 MVC 모델의 양방향 데이터 흐름 문제를 해결하기 위해 단방향 데이터 흐름을 제안하여 상태를 명확하게 하고 예측 가능하게 관리할 수 있도록 돕습니다. 이는 복잡한 데이터 흐름 문제를 해결하고 상태 관리의 예측 가능성을 높여, 유지보수성과 확장성을 강화할 수 있습니다.
Redux는 Flux 패턴을 엄격하게 구현하여 대규모 애플리케이션에 적합하지만, 코드가 다소 복잡할 수 있습니다. 반면 Zustand는 Flux 개념을 간소화하여, 더 가볍고, 효율적인 방식으로 상태를 관리합니다. 이는 가벼운 구조의 애플리케이션에 적합합니다.
애플리케이션의 규모와 복잡도를 고려하여 상태관리 라이브러리인 Redux나 Zustand를 적용하는 것이 가장 좋습니다 :)
'프론트엔드 기록 > 리액트' 카테고리의 다른 글
React Query와 Intersection Observer를 활용한 무한스크롤 구현 (0) | 2025.03.05 |
---|---|
빈 화면 없이 자연스럽게 데이터 갱신하여 SSR UX 개선하기 (0) | 2025.03.03 |
[Next.js 14] FSD 기능 관점 폴더 아키텍처에 대한 생각 (2) | 2024.10.04 |
리액트의 동작 원리, Virtual DOM (1) | 2024.09.12 |
NextJS 경로 가로채기 라우팅 (0) | 2024.09.02 |