Contents
see List작성일 2025. 11. 30.
Zustand - 간단한 React 상태 관리
Zustand는 React를 위한 경량 상태 관리 라이브러리입니다. Redux보다 훨씬 간단하고, Context API의 리렌더링 문제를 해결합니다. 보일러플레이트 없이 직관적인 API를 제공합니다.
언제 사용하나요?
- 전역 상태가 필요하지만 Redux는 과한 경우
- 여러 컴포넌트에서 공유하는 상태 관리
- Context의 불필요한 리렌더링 방지
- 비동기 액션이 빈번한 경우
설치 및 기본 사용
npm install zustand
// store.js
import { create } from "zustand";
const useStore = create((set) => ({
// 상태
count: 0,
user: null,
// 액션
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
setUser: (user) => set({ user }),
reset: () => set({ count: 0, user: null }),
}));
export default useStore;컴포넌트에서 사용
import useStore from "./store";
function Counter() {
// 필요한 상태만 구독 (선택적 리렌더링)
const count = useStore((state) => state.count);
const increment = useStore((state) => state.increment);
return (
<div>
<span>{count}</span>
<button onClick={increment}>+1</button>
</div>
);
}
// 여러 상태 한번에 가져오기
function Profile() {
const { user, setUser } = useStore((state) => ({
user: state.user,
setUser: state.setUser,
}));
return <div>{user?.name}</div>;
}비동기 액션
const useStore = create((set, get) => ({
users: [],
loading: false,
error: null,
fetchUsers: async () => {
set({ loading: true, error: null });
try {
const res = await fetch("/api/users");
const users = await res.json();
set({ users, loading: false });
} catch (error) {
set({ error: error.message, loading: false });
}
},
// get()으로 현재 상태 접근
addUser: async (user) => {
const { users } = get();
await api.createUser(user);
set({ users: [...users, user] });
},
}));미들웨어 - persist (로컬 스토리지)
import { create } from "zustand";
import { persist } from "zustand/middleware";
const useStore = create(
persist(
(set) => ({
theme: "light",
setTheme: (theme) => set({ theme }),
}),
{
name: "app-storage", // localStorage 키
partialize: (state) => ({ theme: state.theme }), // 일부만 저장
}
)
);미들웨어 - devtools
import { devtools } from "zustand/middleware";
const useStore = create(
devtools(
(set) => ({
count: 0,
increment: () => set(
(state) => ({ count: state.count + 1 }),
false,
"increment" // 액션 이름 (DevTools에 표시)
),
}),
{ name: "MyStore" }
)
);슬라이스 패턴 (대규모 스토어)
// userSlice.js
const createUserSlice = (set) => ({
user: null,
login: (user) => set({ user }),
logout: () => set({ user: null }),
});
// cartSlice.js
const createCartSlice = (set) => ({
items: [],
addItem: (item) => set((s) => ({
items: [...s.items, item]
})),
});
// store.js
const useStore = create((...a) => ({
...createUserSlice(...a),
...createCartSlice(...a),
}));컴포넌트 외부에서 사용
// API 호출 등에서 직접 사용
const { getState, setState, subscribe } = useStore;
// 현재 상태 조회
const currentUser = getState().user;
// 상태 변경
setState({ count: 10 });
// 상태 변화 구독
const unsubscribe = subscribe(
(state) => state.user,
(user) => console.log("User changed:", user)
);Redux vs Zustand 비교
| 항목 | Redux | Zustand |
|---|---|---|
| 보일러플레이트 | 많음 | 최소 |
| 러닝커브 | 높음 | 낮음 |
| 번들 크기 | ~12KB | ~1KB |
| Provider 필요 | 필수 | 불필요 |
| 미들웨어 | 풍부 | 기본 제공 |
javascript
| No | 작성일 | Title |
|---|---|---|
| 2921 | 2026. 05. 31. | 브라우저 중복 탭 작업 제어: BroadcastChannel과 Web Locks로 자동 저장 충돌 막기 |
| 2866 | 2026. 05. 23. | Node.js 운영 추적 로그 설계: AsyncLocalStorage로 요청 ID와 장애 원인 연결하기 |
| 2787 | 2026. 05. 15. | Node.js fetch 타임아웃·재시도 표준 패턴: AbortSignal로 장애 전파 막기 |
| 2589 | 2026. 04. 23. | ES2026 JavaScript 신기능 완전 가이드: using/await using, Array.fromAsync, Error.isError, Math.sumPrecise 실전 적용 |
| 2490 | 2026. 04. 14. | ES2025/ES2026 완벽 정리: Iterator Helpers, Temporal API, using 키워드 실전 가이드 |
| 2469 | 2026. 04. 13. | ES2026 완벽 가이드: Temporal API, using/await using, Array/Set 신기능 총정리 |
| 2449 | 2026. 04. 12. | ES2025/ES2026 JavaScript 신기능 완벽 정리: Temporal API부터 using 키워드까지 |
| 2425 | 2026. 04. 11. | Node.js 24 LTS 핵심 신기능 완벽 가이드 - V8 13.6, Permission Model, URLPattern |
| 2389 | 2026. 04. 09. | ES2025 핵심 신규 기능 총정리 - Set 연산, Iterator Helpers, Temporal API까지 |
| 2368 | 2026. 04. 08. | ES2025/ES2026 완벽 정리: Temporal API, Resource Management, 새 문법 총정리 |