Zustand
Zustand는 가볍고 빠르며 확장 가능한 상태 관리 라이브러리로, 다양한 기능과 사용 패턴을 제공합니다.
Zustand: 간단하고 강력한 상태 관리 라이브러리
Zustand는 React 환경에서 간편하게 사용할 수 있는 상태 관리 라이브러리로, Flux 패턴에서 영감을 받아 설계되었습니다. Redux처럼 설정이 복잡하지 않으면서도 성능이 뛰어나며, 필요한 상태를 구독하고 액션을 통해 상태를 변경하는 패턴을 제공합니다.
주요 특징
- 간단한 API: Zustand의
create
함수를 통해 상태를 정의하고, 이를 Hook 형태로 컴포넌트에서 쉽게 사용할 수 있습니다. - 불필요한 리렌더링 방지: 상태 변경 시 필요한 부분만 리렌더링되며, 선택자를 통해 특정 상태만 구독할 수 있어 성능 최적화가 용이합니다.
- 확장성: 미들웨어를 통해 상태를 확장할 수 있으며, 다양한 사용 사례에 대응할 수 있습니다.
- React의 최신 기능과 호환: React 18의 동시성 모드와도 잘 통합되며, 서버 사이드 렌더링(SSR)에도 대응할 수 있습니다.
핵심 개념 및 사용법
1. 스토어 생성과 기본 사용법
Zustand에서의 스토어는 상태를 정의하고 관리하는 중심 역할을 합니다. Zustand의 스토어는 create
함수를 사용해 정의됩니다.
import { create } from 'zustand';
const useStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
}));
컴포넌트 내에서 상태를 구독하고 업데이트하는 방식도 매우 간단합니다.
function BearCounter() {
const bears = useStore((state) => state.bears);
return <h1>{bears} 마리의 곰이 있습니다.</h1>;
}
function Controls() {
const increasePopulation = useStore((state) => state.increasePopulation);
return <button onClick={increasePopulation}>곰 추가</button>;
}
2. 불변 상태 관리와 병합
Zustand는 불변 상태 관리를 지원하며, 상태 병합을 자동으로 처리합니다. 상태를 부분적으로 업데이트하는 경우에도 불변성을 유지하며, 깊은 상태 객체를 쉽게 관리하기 위해 immer
와 같은 미들웨어를 사용할 수 있습니다.
3. 자동 선택자 생성(Auto Generating Selectors)
Zustand는 상태 구독 시 특정 속성만 구독할 수 있는 선택자(Selector)를 제공합니다. 선택자를 통해 특정 상태만 구독하면 불필요한 리렌더링을 방지할 수 있습니다. 예를 들어, 상태에서 곰의 수만 구독할 수 있습니다.
const bears = useStore((state) => state.bears);
4. 상태 초기화(Resetting State)
Zustand는 상태를 쉽게 초기화할 수 있습니다. 이를 통해 특정 상태나 전체 상태를 초기값으로 리셋하는 기능을 구현할 수 있습니다.
const useStore = create((set) => ({
bears: 0,
resetBears: () => set({ bears: 0 }),
}));
5. 서버 사이드 렌더링(SSR) 및 하이드레이션
Zustand는 서버 사이드 렌더링을 지원하며, 클라이언트에서 하이드레이션이 완료된 후에도 상태가 유지되도록 설정할 수 있습니다. Next.js와 같은 SSR 프레임워크와도 호환됩니다.
// Next.js에서 Zustand를 사용한 예시
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
const useStore = create(persist((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
}), { name: 'bear-store' }));
6. TypeScript 지원
Zustand는 TypeScript와 완벽하게 호환됩니다. 타입을 사용하여 상태와 액션을 정의하고, 이를 컴포넌트에서 안전하게 사용할 수 있습니다.
import { create } from 'zustand';
interface BearState {
bears: number;
increasePopulation: () => void;
}
const useStore = create<BearState>((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
}));
고급 기능
1. Persist 미들웨어
상태를 로컬 스토리지 또는 세션 스토리지에 저장할 수 있는 persist
미들웨어를 제공합니다. 이 기능을 사용하면 페이지 새로고침 후에도 상태가 유지됩니다.
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
const useStore = create(persist((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
}), { name: 'bear-storage' }));
2. Immer 미들웨어
immer
미들웨어를 사용하면 상태를 불변성 있게 쉽게 업데이트할 수 있습니다. 이는 복잡한 상태 객체의 깊은 부분을 변경하는 데 유용합니다.
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
const useStore = create(immer((set) => ({
user: { name: '', age: 0 },
updateName: (name) => set((state) => { state.user.name = name; }),
})));
3. Redux DevTools 지원
Zustand는 Redux DevTools와 통합할 수 있어, 상태의 변화를 시각적으로 추적하고 디버깅할 수 있습니다.
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
const useStore = create(devtools((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
})));
결론
Zustand는 리액트 기반 프로젝트에서 간편하고 확장성 있는 상태 관리 솔루션을 제공합니다. Redux보다 간결한 API와 뛰어난 성능 최적화 기능을 갖추고 있으며, 다양한 미들웨어와의 통합으로 유연한 상태 관리가 가능합니다.