Next.js 기반 팀 프로젝트에서 상태 관리를 위해 Zustand를 도입했습니다.
Redux보다 훨씬 가볍고, Provider 없이도 전역 상태를 관리할 수 있으며, 미들웨어 기능을 통해 devtools, persist까지 연동하면 디버깅과 사용자 경험 모두를 챙길 수 있습니다.
이번 글에서는 Zustand의 초기 세팅을 어떤 기준으로 했고, 왜 그런 구조를 선택했는지 정리해봅니다.
| 이유 | 설명 |
|---|---|
| ⚡ 빠른 설정 | Redux처럼 복잡한 boilerplate 없이 곧바로 store 생성 가능 |
| 🧵 Provider 불필요 | Context 없이도 전역 상태 공유 가능 (Next.js 환경에 유리) |
| 🎯 훅 기반 API | useState처럼 직관적이고 타입스크립트와 궁합이 좋음 |
| 🧩 미들웨어 확장 | devtools, persist, immer 등 확장이 매우 쉽고 유연함 |
src/stores 디렉토리를 만들어 Zustand 상태 로직을 모듈화해서 관리했습니다.
상태는 useXXXStore.ts 형식으로 작성하며, 필요한 곳에서 가져다 쓰는 구조입니다.
Zustand는 Redux DevTools와 연동이 가능합니다.
이를 통해 개발 중 상태 변경 추적, 시간 되돌리기(Time travel), 액션 로그 확인이 가능하며, 복잡한 전역 상태 관리에 도움이 됩니다.
{ name: 'AuthStore' } // DevTools에서 store 이름 설정
로그인 상태, 테마 설정 등은 새로고침해도 유지되어야 하므로
zustand/middleware의 persist를 사용해 localStorage에 상태 저장 기능을 추가했습니다.
{ name: 'auth-storage' } // localStorage에 저장될 키 이름
import { create } from 'zustand'
import { devtools, persist } from 'zustand/middleware'
interface AuthState {
isLoggedIn: boolean
login: () => void
logout: () => void
}
export const useAuthStore = create<AuthState>()(
devtools(
persist(
(set) => ({
isLoggedIn: false,
login: () => set({ isLoggedIn: true }),
logout: () => set({ isLoggedIn: false }),
}),
{
name: 'auth-storage', // localStorage에 표시되는 key 이름
}
),
{
name: 'AuthStore', // Redux Devtools에서 표시되는 store 이름
}
)
)
/src
/stores ← zustand 상태 저장소
└ useAuthStore.ts
/hooks
/providers
/app ← Next.js App Router 전용
zustand관련 로직은app/내부가 아니라src/stores에서 모듈화 관리하는 것이 유지보수에 좋습니다.
| 미들웨어 | 역할 | 실사용 예 |
|---|---|---|
devtools | Redux DevTools 연동 | 상태 변경 추적, 디버깅 |
persist | 상태를 localStorage 등에 저장 | 로그인 유지, 테마 설정 저장 등 |
Zustand는 상태 관리 입문자부터 실무 프로젝트까지 모두 활용 가능한 훌륭한 도구
middleware를 함께 사용하면 기능은 강력해지고, 코드 유지보수는 쉬워진다
useAuthStore, useModalStore, useUserStore 등으로 모듈화 확장이 용이