플럭스 패턴(Flux Pattern)을 중심으로 본 Zustand의 동작방식
안녕하세요, 프론트엔드 개발자 코디(Kody)입니다.
한때, React에서 상태 관리를 고민할 때 가장 먼저 떠오르는 라이브러리는 Redux 였습니다.
하지만 Redux는 보일러플레이트 코드가 많고, 설정이 복잡하며, 상태 변경 로직을 유지하는 데 부담이 큰 단점이 있죠.
그래서 최근에는 Zustand 같은 가벼운 상태 관리 라이브러리가 각광받고 있습니다.
Zustand는 Flux 패턴을 기반으로 동작하며, Redux보다 가볍고 직관적인 API를 제공하는 것이 특징인데요.
이번 글에서는 Zustand의 동작 방식을 Flux 패턴을 중심으로 한번 살펴보려합니다.
1. Flux 패턴이란?
Flux는 Facebook이 제안한 단방향 데이터 흐름(Unidirectional Data Flow)을 따르는 상태 관리 패턴입니다.
일반적으로 React의 상태는 부모 → 자식 방향으로만 전달되며, 직접 상태를 수정할 수 없지만, Flux 패턴을 사용하면 중앙에서 상태를 관리하여 예측 가능성을 높일 수 있습니다.
React의 기본 상태 관리 방식 (Props 기반의 단방향 데이터 흐름)
기본적으로 React는 컴포넌트 기반 UI 라이브러리이며, 상태 관리를 위해 컴포넌트 내부 상태(Local State) 를 사용합니다.
React의 상태 관리 방식은 기본적으로 단방향 데이터 흐름(Unidirectional Data Flow) 을 따릅니다.
📌 React의 상태 흐름
부모 컴포넌트 (State 관리) → 자식 컴포넌트 (Props로 전달) → UI 렌더링
📌 기본적인 React 상태 관리 예제
const Parent = () => {
const [count, setCount] = useState(0); // ✅ 상태 관리 (Local State)
return <Child count={count} setCount={setCount} />;
};
const Child = ({ count, setCount }) => {
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
};
✔ 부모 컴포넌트에서 상태를 관리하고, 자식 컴포넌트로 props를 전달하는 방식
✔ 이 패턴을 “Props Drilling(깊이 있는 상태 전달)” 이라고 함
하지만, 컴포넌트가 깊어질수록(Props Drilling) 상태 전달이 어려워지고,
다양한 컴포넌트가 같은 상태를 공유해야 할 경우 Context API를 사용해야 하는 번거로움이 있습니다.
Flux 패턴을 사용하면 무엇이 좋아질까?
Flux 패턴을 사용하면, 상태를 전역에서 관리하고, 직접적인 데이터 변경 없이 Action을 통해 상태를 업데이트할 수 있습니다.
이 방식은 Redux, Zustand 등 다양한 상태 관리 라이브러리에서 채택하는 구조입니다.
📌 Flux 패턴의 핵심 개념
Flux 구성 요소설명
Store | 전역 상태를 관리하는 저장소 |
Action | 상태를 변경하기 위한 이벤트 (유저 입력, API 응답 등) |
Dispatcher | Action을 받아 Store를 업데이트 |
View | Store의 상태를 받아 UI를 렌더링 |
📌 Flux의 데이터 흐름
사용자 입력 → Action 발생 → Dispatcher → Store 상태 변경 → View UI 업데이트
2. Zustand는 어떻게 Flux 패턴을 적용할까?
Zustand는 Flux 패턴을 기반으로 동작하지만, Redux보다 가볍고 직관적인 방식으로 구현되어 있습니다.
📌 Zustand에서의 Flux 패턴 적용
Flux 패턴Zustand의 대응 개념설명
Store | useStore | 상태를 저장하는 중앙 저장소 |
Action | set() 함수 | 상태를 변경하는 함수 (Dispatcher 역할도 포함) |
Dispatcher | set() (내장됨) | Action을 받아 상태를 변경 |
View | React 컴포넌트 | Zustand의 상태를 구독하여 UI를 렌더링 |
Zustand의 Flux 패턴 적용 예제
import { create } from 'zustand';
// ✅ Zustand Store 생성 (상태 및 액션 정의)
const useStore = create((set) => ({
count: 0, // 초기 상태 (State)
increase: () => set((state) => ({ count: state.count + 1 })), // Action (상태 변경)
decrease: () => set((state) => ({ count: state.count - 1 })),
}));
// ✅ View 컴포넌트
const Counter = () => {
const { count, increase, decrease } = useStore();
return (
<div>
<h1>Count: {count}</h1>
<button onClick={increase}>+</button>
<button onClick={decrease}>-</button>
</div>
);
};
export default Counter;
✅ useStore()가 Store 역할을 하며,
✅ set() 함수는 Dispatcher + Action 역할을 수행
✅ React 컴포넌트(View)는 Zustand의 상태를 구독하고 UI를 업데이트
3. Zustand 내부 동작 방식 (Flux 패턴 적용)
Zustand는 내부적으로 단순한 Flux 패턴을 활용하여 상태를 관리합니다.
📌 Zustand 동작 과정
1. 사용자가 버튼 클릭 (`increase()`)
2. `set()` 함수 실행 → 새로운 상태 생성
3. Zustand Store의 상태 변경 감지
4. 상태를 구독하는 React 컴포넌트가 리렌더링됨
✔ Redux처럼 액션(Action) 객체를 따로 만들 필요 없이 set() 함수로 상태를 변경할 수 있음.
✔ 불필요한 보일러플레이트 코드가 없음
4. Zustand vs Redux: Flux 패턴 적용 방식 비교
비교 항목Zustand vs.Redux
패턴 | Flux 기반 | Flux 기반 |
Store | useStore() 하나로 관리 | 여러 개의 reducer를 조합하여 관리 |
Action | set() 함수로 직접 상태 변경 | dispatch({ type, payload }) 사용 |
Reducer 필요 여부 | ❌ 불필요 | ✅ 반드시 필요 |
보일러플레이트 코드 | ✅ 없음 (간단) | ❌ 많음 (Action, Reducer, Middleware 필요) |
Middleware 지원 | ✅ persist(), devtools() | ✅ Redux Middleware (redux-thunk, redux-saga) |
✅ Zustand는 Redux보다 훨씬 가볍고, 불필요한 보일러플레이트 코드 없이 Flux 패턴을 구현할 수 있음.