Zustand Hydration

2026. 2. 24. 10:26·공부하기/ETC

Zustand의 persist 미들웨어에서 사용하는 Hydration(하이드레이션)은

쉽게 말해 스토리지(localStorage 등)에 저장된 데이터를 메모리(Zustand 스토어)로 다시 불러와 합치는 과정을 의미한다.

 

`_hasHydrated`가 왜 필요한가요?

Zustand `persist`는 앱이 실행되자마자 스토리지에서 데이터를 읽어오지만, 이 과정은 찰나의 시간(비동기적 특성)이 걸린다.

이 때 다음과 같은 문제가 발생할 수 있다.

  1. 데이터 불일치 : 새로고침 직후, Zustand 스토어는 잠시 동안 초기값(session: null)을 가진다. 하지만 실제 Local Storage에는 로그인 정보가 들어있다.
  2. 깜빡임 현상(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);
            },
        }
    )
);

작성한 코드의 로직은 다음과 같이 흐른다.

  1. 앱 시작 : `_hasHydrated`는 기본값인 `false`이다.
  2. 데이터 복원 시작: `persist` 미들웨어가 `localStorage`에서 `auth-storage` 키를 찾아 데이터를 읽어온다.
  3. 복원 완료(`onRehydratedStoreage`) : 데이터를 다 읽고 스토어에 반영한 직후, 설정해둔 콜백 함수가 실행된다.
    • `state?.setHasHydrated(true);` 가 실행되면서 `_hasHydrated`가 `true`로 바뀐다.
  4. 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
'공부하기/ETC' 카테고리의 다른 글
  • RAG와 벡터 데이터베이스
  • 실시간 데이터 전송 기술 정리 | Polling, Long-Polling, SSE, WebSocket
  • Unique한 값이 필요할 때 사용하는 UUID, UUID란?
  • JWT 찐하게 이해하기 👀 | JWT 구성과 인증 원리
다섯자두
다섯자두
All I need is 💻 , ☕️ and a dash of luck
  • 다섯자두
    subbni
    다섯자두
  • 전체
    오늘
    어제
    • 전체 글 (89)
      • 개발 이야기 (0)
      • 만들어보기 (17)
        • FromBookToBook (5)
        • Spring (5)
        • Node.js & React (3)
        • TroubleShooting (4)
      • 공부하기 (72)
        • Network (3)
        • Cloud (1)
        • Database (5)
        • Java (13)
        • Javascript (0)
        • Spring (9)
        • React (18)
        • Algorithm (8)
        • 자료구조 (7)
        • ETC (8)
      • 회고 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • velog
  • 공지사항

  • 인기 글

  • 태그

    pdf 프리뷰 실패
    outbox 패턴
    network
    HTTP
    서명알고리즘
    알고리즘
    outbox
    SQL
    aws
    Spring
    pdf 자동 다운로드
    프로젝트
    redis
    SQS
    JPA
    오블완
    Express
    자료구조
    mysql
    티스토리챌린지
    재시도 로직
    Til
    알림 기능
    SSE
    최단거리
    springboot
    Database
    java
    로그인
    실시간 데이터 전송 기술
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
다섯자두
Zustand Hydration
상단으로

티스토리툴바