Zustand 미들웨어란?

송연지·2025년 4월 8일
1

🧠 Zustand 미들웨어란? 왜 써야 할까?

Zustand를 사용하다 보면 middleware라는 개념을 마주치게 됩니다. 처음에는 생소하지만, 조금만 이해하면 강력한 기능을 간단하게 붙일 수 있어요. 이 글에서는 Zustand 미들웨어가 뭔지, 왜 필요한지, 그리고 실전에서 어떻게 사용하는지를 예시와 함께 정리해볼게요.


📌 미들웨어(Middleware)란?

Zustand의 미들웨어는 상태를 읽거나 수정하는 과정에서 중간에 끼어들어 어떤 작업을 추가할 수 있는 기능입니다.


const store = create(middleware((set, get) => ({
  state: 'value',
  update: () => set({ state: 'new value' }),
})));

상태가 set으로 변경되기 전/후로 어떤 작업을 하고 싶을 때, 바로 이 미들웨어를 사용합니다.


✅ 왜 써야 하나요?

사용 목적설명
🔍 디버깅/로깅상태가 어떻게 바뀌었는지 콘솔에 찍어보기
💾 상태 저장localStorage나 sessionStorage에 저장해서 새로고침해도 복구 가능
🧪 개발자 도구 연동Chrome 확장에서 상태를 추적 (Redux Devtools와 비슷)
⏱ 비동기 래핑비동기 작업을 깔끔하게 다룰 수 있도록 확장 가능
🧼 공통 처리set 전에 유효성 검사, 에러 핸들링 등 로직을 한 곳에서 관리

⚙️ Zustand 대표 미들웨어 3가지


1. devtools – 개발자 도구 연동

ts
복사편집
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';

const useStore = create(devtools((set) => ({
  count: 0,
  increase: () => set((state) => ({ count: state.count + 1 })),
})));

Chrome에서 Zustand Devtools 확장으로 상태 확인 가능!


2. persist – 상태를 브라우저 저장소에 저장


import { create } from 'zustand';
import { persist } from 'zustand/middleware';

const useUserStore = create(persist(
  (set) => ({
    user: null,
    setUser: (user) => set({ user }),
  }),
  {
    name: 'user-storage', // localStorage 키 이름
  }
));

유저 정보, 다크모드 설정 등 새로고침해도 유지하고 싶은 상태에 활용하면 좋습니다.


3. 커스텀 미들웨어 – 로깅 기능 직접 만들기


const logger = (config) => (set, get, api) =>
  config((args) => {
    console.log('🧪 상태 변경 전:', get());
    set(args);
    console.log('✅ 상태 변경 후:', get());
  }, get, api);

const useStore = create(logger((set) => ({
  count: 0,
  increase: () => set((state) => ({ count: state.count + 1 })),
})));

직접 미들웨어를 만들어서 내가 원하는 기능을 상태 변경 흐름에 자연스럽게 붙일 수 있어요.


🔗 미들웨어는 어떻게 겹쳐 쓸까?

Zustand의 미들웨어는 체이닝이 가능합니다. 예를 들어 persistdevtools를 동시에 쓰고 싶다면:


const useStore = create(
  devtools(
    persist((set) => ({
      darkMode: false,
      toggle: () => set((state) => ({ darkMode: !state.darkMode }))
    }), {
      name: 'settings-storage'
    })
  )
);

💡 결론

Zustand는 미들웨어 덕분에 단순한 상태 관리 그 이상을 할 수 있습니다. 특히 persistdevtools는 실제 프로젝트에서 자주 쓰이는 필수 기능이고, 커스텀 미들웨어를 작성하면 내 프로젝트에 딱 맞는 상태 흐름을 만들 수 있어요.

복잡한 Redux 설정 없이도 유연하고 직관적인 상태 관리를 원한다면, Zustand + Middleware 조합은 정말 강추입니다.

💬 그래서 우리 프로젝트에서는?

이미 로컬스토리지 직접 쓰고 있는데, 굳이 Zustand의 persist 미들웨어를 왜 써야 할까?

결론 먼저 말하면:

✅ 로컬스토리지를 더 안정적이고, 간편하게, zustand랑 잘 연동되게 쓰고 싶다면 → persist 미들웨어 쓰는 게 훨씬 낫다.


📦 1. 직접 사용하는 로컬스토리지 vs. persist 미들웨어 차이

항목직접 localStorage 사용zustand persist 미들웨어 사용
데이터 저장/불러오기직접 setItem, getItem 해야 함자동으로 저장 & 불러오기
데이터 구조 관리JSON parse/stringify 필요내부적으로 알아서 처리
상태와 분리상태와 별도 관리, 복잡해짐상태와 자연스럽게 통합됨
초기화 타이밍useEffect로 따로 처리해야 함zustand 생성 시점에 알아서 초기화함
유지보수 및 테스트따로 분리된 로직 관리 필요미들웨어 내부에 다 캡슐화됨
devtools 연동불가가능 (persist + devtools 같이 사용 가능)

❌ 직접 사용하는 방식


const [theme, setTheme] = useState(() => {
  return localStorage.getItem('theme') || 'light';
});

useEffect(() => {
  localStorage.setItem('theme', theme);
}, [theme]);

→ 이거 계속 반복되면 귀찮고 버그 생기기 쉬움.

→ 특히 다수 상태 동기화할 때 불일치 문제 생김.


✅ Zustand persist 미들웨어 방식


import { create } from 'zustand';
import { persist } from 'zustand/middleware';

const useThemeStore = create(
  persist(
    (set) => ({
      theme: 'light',
      toggleTheme: () => set((s) => ({ theme: s.theme === 'light' ? 'dark' : 'light' }))
    }),
    {
      name: 'theme-storage' // localStorage key
    }
  )
);

→ 이러면 한 줄도 없이 알아서 localStorage 연동돼.

상태 관리 + 저장 + 초기 로드 + 일관성 유지까지 자동으로.


🎯 그래서 미들웨어 왜 쓰냐면?

  1. 너가 이미 zustand를 쓰고 있다면, persist는 거의 필수급으로 궁합 좋고
  2. 코드 양이 훨씬 줄어듦 (초기화 + 저장 + 상태 싱크 다 자동)
  3. 유지보수 시 상태/저장소 동기화 버그 거의 사라짐
  4. devtools, logger 등 다른 미들웨어랑 조합해서 쓰기도 쉬움

🧠 결론

너가 지금 상태를 zustand로 잘 쓰고 있고, 상태를 저장할 필요가 있다면

굳이 수동으로 localStorage 관리하지 말고, persist 미들웨어 써라.

profile
프론트엔드 개발쟈!!

0개의 댓글