변수를 전역으로 상태관리를 도와주는 도구로 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

persistZustand 상태 를 브라우저 저장소(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 앱에서 로그인 사용자 정보를 관리할 때 localStorageZustand는 서로 다른 목적과 장단점을 가집니다. 상황에 따라 어떤 방식을 선택할지 비교해볼게요.


🗄️ localStorage 활용

특징

  • 브라우저에 영구적으로 저장 → 새로고침, 브라우저 종료 후에도 데이터 유지
  • 문자열 기반 저장소 → JSON 직렬화/역직렬화 필요
  • 보안에 취약 → 토큰이나 민감한 정보는 직접 저장 시 위험

장점

  • 간단하고 빠르게 구현 가능
  • 서버에서 받은 토큰/사용자 정보를 유지하는 데 적합
  • 별도 라이브러리 없이 브라우저 기본 기능 활용

단점

  • 상태 변경 시 UI와 자동 동기화되지 않음 → useEffect로 수동 반영 필요
  • 여러 탭/윈도우 간 동기화는 제한적
  • 민감한 데이터 저장 시 보안 문제 발생 가능

⚡ Zustand 활용

특징

  • React 전역 상태 관리 라이브러리
  • 메모리 기반 → 새로고침 시 데이터 사라짐 (persist 미들웨어로 localStorage 연동 가능)
  • 컴포넌트 간 props drilling 없이 상태 공유 가능

장점

  • UI와 상태 자동 동기화 → 변경 시 필요한 컴포넌트만 리렌더링
  • 코드 구조가 깔끔해지고 유지보수 쉬움
  • 선택적 구독으로 성능 최적화 가능
  • persist 미들웨어로 localStorage와 결합 가능 → 영속성 + 전역 상태 관리 동시 확보

단점

  • 별도 라이브러리 도입 필요
  • 기본적으로는 새로고침 시 상태 초기화 (persist 설정 필요)
  • 단순한 앱에서는 오히려 과도한 추상화가 될 수 있음