변수를 전역으로 상태관리를 도와주는 도구로 Zustand 가 있습니다.
Zustand
상황에 따라 Zustand로 대체해야 하는 경우도 있지만 props만으로 충분한 경우를 구분할 필요가 있다.
Props 와 Zustand
Zustand로 대체하는 것이 적절한 경우
- 전역 상태 관리가 필요한 경우
- 로그인 사용자 정보, 테마 설정, 다국어 설정 등 앱 전체에서 공유되는 상태.
- 깊은 컴포넌트 트리에서 props drilling이 심한 경우
- 부모 → 자식 → 손자 → 증손자… 계속 내려주어야 하는 상태라면 유지보수가 어렵습니다.
- 여러 컴포넌트가 동시에 같은 상태를 읽고/갱신해야 하는 경우
- 예: 장바구니, 알림 시스템, 모달 관리.
- 상태 변경이 빈번하고 성능 최적화가 필요한 경우
- Zustand는 선택적 구독을 지원해, 특정 상태만 구독하는 컴포넌트만 리렌더링됩니다.
Zustand로 대체하지 않아도 되는 경우
- 지역적 상태(Local state)만 필요한 경우
- 단일 컴포넌트 내부에서만 쓰이는 입력값, 토글 상태 등은
useState로 충분합니다.
- 단일 컴포넌트 내부에서만 쓰이는 입력값, 토글 상태 등은
- 상태 전달 깊이가 얕은 경우
- 부모 → 자식 정도의 간단한 전달이라면 props로 관리하는 것이 직관적입니다.
- 일회성 데이터 전달
- 특정 화면에서만 필요한 데이터라면 굳이 전역 상태로 올릴 필요가 없습니다.
- 불필요한 복잡성 회피
- 작은 프로젝트나 단순한 UI라면 Zustand를 도입하는 것이 오히려 과도한 추상화가 될 수 있습니다.
⚖️ 정리
- Props → 단순, 지역적, 계층이 얕은 상태 전달에 적합 (버튼 클릭 시 모달 열림 여부 → props/local state)
- Zustand → 전역적, 다수 컴포넌트 공유, 깊은 트리, 성능 최적화가 필요한 경우 적합 (로그인한 사용자 정보(이름, 토큰, 권한) → Zustand)
Persist -> LocalStorage
전역에서 필요한 값을 LocalStorage 에 저장하고 활용하는 경우가 있습니다. zustand 는 새로고침을 하면 초기화 되므로 상황에 따라 다양하게 적용하여야 합니다.
- localStorage만 사용 → 단순히 토큰이나 사용자 ID를 저장해 인증 유지할 때 적합
- Zustand만 사용 → 로그인 상태를 UI 전역에서 관리하고, 새로고침 시 초기화돼도 괜찮을 때 적합
- Zustand + persist(localStorage 연동) → 전역 상태 관리 + 영속성 모두 필요할 때 가장 실용적인 조합
| 구분 | localStorage | Zustand |
|---|---|---|
| 데이터 지속성 | 새로고침/브라우저 종료 후에도 유지 | 기본은 휘발성, persist로 영속성 가능 |
| UI 동기화 | 직접 코드로 반영 필요 | 자동 반영 (React 상태 관리) |
| 복잡도 | 단순 | 라이브러리 도입 필요 |
| 보안 | 민감 데이터 저장 위험 | 메모리 기반이라 상대적으로 안전 (단, persist 시 동일 위험) |
| 적합한 경우 | 토큰, 사용자 ID 등 단순 영속 데이터 | 로그인 상태, 사용자 프로필, UI 전역 공유 상태 |
persist
persist 는 Zustand 상태 를 브라우저 저장소(localStorage, sessionStorage, IndexedDB 등)에 자동으로 저장하고 복원해주는 미들웨어입니다.
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
const useUserStore = create(
persist(
(set) => ({
user: null, // 변수명
setUser: (user) => set({ user }), // method 1
clearUser: () => set({ user: null }), // method 2
}),
{
name: 'user-storage', // localStorage `key` 이름
getStorage: () => localStorage, // (Default) localStorage
}
)
)
위 코드의 동작 방식을 살펴보면 다음과 같습니다.
- 상태 변경 시 자동으로
localStorage에 직렬화된JSON으로 저장됩니다. - 앱이 다시 로드되면
localStorage에서 값을 읽어와 초기 상태로 복원합니다. name옵션으로 저장 키를 지정할 수 있습니다.getStorage옵션으로 저장소를 바꿀 수 있습니다 (예: sessionStorage).
좋은 포인트를 짚으셨어요 👍
React 앱에서 로그인 사용자 정보를 관리할 때 localStorage와 Zustand는 서로 다른 목적과 장단점을 가집니다. 상황에 따라 어떤 방식을 선택할지 비교해볼게요.
🗄️ localStorage 활용
특징
- 브라우저에 영구적으로 저장 → 새로고침, 브라우저 종료 후에도 데이터 유지
- 문자열 기반 저장소 → JSON 직렬화/역직렬화 필요
- 보안에 취약 → 토큰이나 민감한 정보는 직접 저장 시 위험
장점
- 간단하고 빠르게 구현 가능
- 서버에서 받은 토큰/사용자 정보를 유지하는 데 적합
- 별도 라이브러리 없이 브라우저 기본 기능 활용
단점
- 상태 변경 시 UI와 자동 동기화되지 않음 →
useEffect로 수동 반영 필요 - 여러 탭/윈도우 간 동기화는 제한적
- 민감한 데이터 저장 시 보안 문제 발생 가능
⚡ Zustand 활용
특징
- React 전역 상태 관리 라이브러리
- 메모리 기반 → 새로고침 시 데이터 사라짐 (persist 미들웨어로 localStorage 연동 가능)
- 컴포넌트 간 props drilling 없이 상태 공유 가능
장점
- UI와 상태 자동 동기화 → 변경 시 필요한 컴포넌트만 리렌더링
- 코드 구조가 깔끔해지고 유지보수 쉬움
- 선택적 구독으로 성능 최적화 가능
persist미들웨어로 localStorage와 결합 가능 → 영속성 + 전역 상태 관리 동시 확보
단점
- 별도 라이브러리 도입 필요
- 기본적으로는 새로고침 시 상태 초기화 (persist 설정 필요)
- 단순한 앱에서는 오히려 과도한 추상화가 될 수 있음