Zustand 핸드북
핵심 요약
Zustand는 경량·고성능·확장성을 모두 갖춘 React 상태 관리 라이브러리로, 보일러플레이트가 거의 없고 훅 기반 API를 통해 전역 상태를 간편하게 정의·접근·갱신할 수 있다. Context나 Redux에 비해 학습 곡선이 완만하며, 구독 선택자(selector)를 통해 불필요한 리렌더링을 최소화할 수 있다.
1. 탄생 배경 및 철학
- 문제의식: Redux의 복잡한 액션/리듀서/스토어 설계와 과도한 보일러플레이트1
 - 설계 목표
 
- 최소한의 코드로 최대한의 기능 제공
 - 훅(React Hooks) 기반으로 컴포넌트와 자연스럽게 통합
 - Context API 의 단점(전역 리렌더링, 중첩된 Provider) 해소
 
- 이름의 유래: 독일어로 “state”를 뜻함
 
2. 아키텍처 개요
- 스토어(Store)
create함수로 정의- 내부에 상태(state) 및 갱신 메서드(actions)를 포함
 
 - 구독(Subscription)
- 소비 컴포넌트는 
useStore(selector)훅으로 특정 상태만 구독 - 선택한 상태 변화 시에만 리렌더링
 
 - 소비 컴포넌트는 
 - 미들웨어 지원
- 로깅, 퍼시스턴스, 리덕스 DevTools 연동 가능
 
 - 슬라이스 패턴
- 대규모 앱 시 기능별로 스토어 분할 후 결합하여 사용
 
 
3. 설치 및 기본 사용법
npm install zustand
# 또는
yarn add zustand3.1 스토어 정의
import { create } from 'zustand';
 
const useBearStore = create((set) => ({
  bears: 0,                                  // state
  increase: () => set((s) => ({ bears: s.bears + 1 })),  
  reset: () => set({ bears: 0 }),
}));3.2 컴포넌트에서 사용
function BearCounter() {
  const bears = useBearStore((state) => state.bears);
  return <h1>{bears} bears around here…</h1>;
}
 
function Controls() {
  const increase = useBearStore((state) => state.increase);
  return <button onClick={increase}>Add Bear</button>;
}4. 고급 패턴과 모범 사례
4.1 슬라이스 패턴으로 스토어 분할
// fishSlice.js
export const createFishSlice = (set) => ({
  fishes: 0,
  addFish: () => set((s) => ({ fishes: s.fishes + 1 })),
});
 
// bearSlice.js
export const createBearSlice = (set) => ({
  bears: 0,
  addBear: () => set((s) => ({ bears: s.bears + 1 })),
});
 
// store.js
import { create } from 'zustand';
import { createFishSlice } from './fishSlice';
import { createBearSlice } from './bearSlice';
 
const useStore = create((set, get) => ({
  ...createFishSlice(set, get),
  ...createBearSlice(set, get),
}));4.2 리덕스 스타일 dispatch 사용
const types = { INC: 'INC', DEC: 'DEC' };
const reducer = (state, { type, by = 1 }) => {
  switch (type) {
    case types.INC: return { count: state.count + by };
    case types.DEC: return { count: state.count - by };
    default: return state;
  }
};
 
const useStore = create((set) => ({
  count: 0,
  dispatch: (action) => set((s) => reducer(s, action)),
}));4.3 비동기 처리
const useStore = create((set) => ({
  data: null,
  fetchData: async () => {
    const res = await fetch('/api/data');
    const json = await res.json();
    set({ data: json });
  },
}));4.4 퍼포먼스 최적화
- 선택적 구독: 
useStore(state => state.foo) - 불변성 유지: 
set((s) => ({…}))패턴 - 구독 해제: 외부 구독 시 
subscribe와useEffect조합 
5. DevTools 및 미들웨어
- Redux DevTools 연동: 
import { devtools } from 'zustand/middleware' - 퍼시스턴스: 
persist미들웨어로 상태 로컬·세션 저장 - 로깅: 
import { subscribeWithSelector } from 'zustand/middleware'등 
6. 사용 시 고려사항
- 작은 앱: 간단한 전역 상태만 필요 → Zustand 단독 사용 추천
 - 대규모 앱: 슬라이스 패턴 + 미들웨어 조합으로 확장성 확보
 - 서버 상태: React Query 등과 분리하여 관리
 - 테스트 용이성: 순수 함수 형태로 스토어 정의 → 모킹·단위 테스트 수월
 
7. 결론
Zustand는 간결하면서도 강력한 React 상태 관리 도구로, Minimal API와 훅 기반 설계를 통해 생산성을 높인다. 중소 규모 프로젝트부터 대규모 애플리케이션까지, 슬라이스 패턴과 미들웨어를 활용해 유연하게 확장할 수 있어, 현대 React 개발 환경에서 훌륭한 선택지가 된다.
⁂