어디서 어느 방향으로 데이터가 전달될지 알지 못할 정도로 혼란한 MVC 패턴의 복잡성을 해소하기 위해, Flux 패턴에서는 데이터가 한 방향으로만 흐르도록 했다. Flux는 간단하게 설명하면 어떤 Action이 발생하면, Dispatcher에서 이를 받아와 해석한 후 Store에서 저장된 정보에 변경을 가하고, 그 결과가 View로 다시 전달되도록 한다. 이를 다음과 같은 그림으로 나타낼 수 있다.
하지만 사용자가 View를 통해서 클릭 같은 액션을 발생시킬 수 있기때문에 이를 고려하면 다음과 같은 흐름으로 나타낼 수 있다.
데이터를 변경하는 행위로서 Dispactcher에게 전달되는 객체
모든 데이터의 흐름을 관리하는 중앙 허브
상태 저장소로서 상태와 상태를 변경할 수 있는 메서드를 가지고 있음
React Component
Redux는 전역 상태를 관리하기 위한 정말 좋은 솔루션이지만, 너무 많은 코드를 작성해야한다. 아주 간단한 예시를 적기 위해서라도 많은 코드를 적고, 또 그 코드를 이해하는 것은 너무 어렵다.
Redux와 마찬가지로 Flux 패턴을 따르는 상태관리 라이브러리
// CountStore.ts
import { create } from 'zustand';
interface countState {
count: number;
addCount: () => void;
resetCount: () => void;
}
export const useCountStore = create<countState>((set) => ({
count: 0,
addCount: () => set((state) => ({ count: state.count + 1 })),
resetCount: () => set({ count: 0 }),
}));
count
라는 초기값을 선언하고 그 값을 조작할 수 있는 action addCount
와 resetCount
를 선언합니다.
// example.tsx
import { useCountStore } from 'src/stores/CountStore';
export default function Example() {
const { count, addCount, resetCount } = useCountStore();
return (
<>
<div>{count}</div>
<button onClick={addCount}>클릭</button>
<button onClick={resetCount}>리셋</button>
</>
);
}
store
에서 생성한 useCountStore
를 불러와서 구조 분해 할당을 통해 쉽게 사용할 수 있다.
버튼 클릭 시 count가 늘어나고 초기화 되는 것을 확인할 수 있다.
zustand 는 Middleware로 devtools를 지원하고 있다. Redux Devtools를 설치하면 크롬 개발자 도구에서 Redux Devtools를 확인할 수 있다.
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
interface countState {
count: number;
addCount: () => void;
resetCount: () => void;
}
export const useCountStore = create<countState>()(
devtools((set) => ({
count: 0,
addCount: () => set((state) => ({ count: state.count + 1 })),
resetCount: () => set({ count: 0 }),
}))
);
create
안에 devtools
를 연결하는 방법으로 쉽게 사용할 수 있다.
장점
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
interface countState {
count: number;
actions: {
addCount: () => void;
resetCount: () => void;
};
}
const useCountStore = create<countState>()(
devtools((set) => ({
count: 0,
actions: {
addCount: () => set((state) => ({ count: state.count + 1 })),
resetCount: () => set({ count: 0 }),
},
}))
);
export const useCount = () => useCountStore((state) => state.count);
export const useCountActions = () => useCountStore((state) => state.actions);
const count = useCount();
const { addCount, resetCount } = useCountActions();
action
은 절대 변하지 않기 때문에 전부를 구독해도 리렌더링에 영향을 주지 않음
zustand와 react query를 같이 사용하는 방법
[React] Flux 패턴에 대해서: Redux와 Zustand
Web: React Flux 패턴