Zustand의 persist 미들웨어에서 사용하는 Hydration(하이드레이션)은
쉽게 말해 스토리지(localStorage 등)에 저장된 데이터를 메모리(Zustand 스토어)로 다시 불러와 합치는 과정을 의미한다.
`_hasHydrated`가 왜 필요한가요?
Zustand `persist`는 앱이 실행되자마자 스토리지에서 데이터를 읽어오지만, 이 과정은 찰나의 시간(비동기적 특성)이 걸린다.
이 때 다음과 같은 문제가 발생할 수 있다.
- 데이터 불일치 : 새로고침 직후, Zustand 스토어는 잠시 동안 초기값(session: null)을 가진다. 하지만 실제 Local Storage에는 로그인 정보가 들어있다.
- 깜빡임 현상(Flicker) : 사용자 정보가 복원되지 않았는데 AutoGuard가 먼저 작동하면, 분명 로그인한 사용자인데도 아주 잠깐 로그인 페이지로 튕겼다가 다시 돌아오는 현상이 생길 수 있다.
`_hasHydrated`는 데이터를 불러왔으니, 이제 스토어의 값을 믿고 사용해도 된다는 신호등 역할을 한다.
코드의 흐름 이해하기
import type {AuthSession} from "@/shared/domain/models/auth.ts";
import {create} from "zustand";
import {createJSONStorage, persist} from "zustand/middleware";
type AuthState = {
session: AuthSession | null;
_hasHydrated: boolean;
setSession: (session: AuthSession) => void;
clearSession: () => void;
setHasHydrated: (state: boolean) => void;
}
export const useAuthStore = create<AuthState>()(
persist(
(set) => ({
session: null,
_hasHydrated: false,
setSession: (session) => set({ session }),
clearSession: () => set({ session: null }),
setHasHydrated: (state) => set({ _hasHydrated: state }),
}),
{
name: 'auth-storage',
storage: createJSONStorage(() => localStorage),
onRehydrateStorage: () => (state) => {
state?.setHasHydrated(true);
},
}
)
);
작성한 코드의 로직은 다음과 같이 흐른다.
- 앱 시작 : `_hasHydrated`는 기본값인 `false`이다.
- 데이터 복원 시작: `persist` 미들웨어가 `localStorage`에서 `auth-storage` 키를 찾아 데이터를 읽어온다.
- 복원 완료(`onRehydratedStoreage`) : 데이터를 다 읽고 스토어에 반영한 직후, 설정해둔 콜백 함수가 실행된다.
- `state?.setHasHydrated(true);` 가 실행되면서 `_hasHydrated`가 `true`로 바뀐다.
- UI 반영 : 이제 리액트 컴포넌트들이 이 값이 `true`가 된 것을 보고 세션 정보를 확인해도 됨을 판단한다.
실무에서 어떻게 쓰는가?
주로 라우트 가드나 최상위 컴포넌트(App.tsx)에서 사용한다. 데이터가 복원되기 전까지는 아무것도 보여주지 않거나 로딩 스피너를 보여주는 식이다.
// src/app/router/index.tsx 또는 App.tsx
const App = () => {
const hasHydrated = useAuthStore((s) => s._hasHydrated);
// 데이터 복원 전이라면 로딩 화면을 보여줘서 '로그인 페이지 튕김'을 방지함
if (!hasHydrated) {
return <LoadingSpinner />;
}
return <RouterProvider router={router} />;
};
요약
- Hydration: localStorage -> Zustand 스토어로 데이터를 옮기는 과정
- _hasHydrated: "옮기기 작업이 끝났는가?"를 나타내는 상태 변수
- 의미: 새로고침 시 데이터가 복원되는 짧은 순간 동안 생길 수 있는 UI 오류와 잘못된 리다이렉션을 막기 위한 안전장치
'공부하기 > ETC' 카테고리의 다른 글
| RAG와 벡터 데이터베이스 (1) | 2026.01.14 |
|---|---|
| 실시간 데이터 전송 기술 정리 | Polling, Long-Polling, SSE, WebSocket (1) | 2025.04.18 |
| Unique한 값이 필요할 때 사용하는 UUID, UUID란? (0) | 2025.03.19 |
| JWT 찐하게 이해하기 👀 | JWT 구성과 인증 원리 (0) | 2025.03.13 |
| Servlet 이해하기 (Web Server, WAS, Servlet) (0) | 2025.01.22 |