프론트 상태관리 도구라고 하면 Context API, Redux, Zustand 등 여러 가지가 있다.
사실 이번 Groupie 사이드 프로젝트 전까지만 해도 난 상태관리 도구 없이 useState
만 쓰던 초짜였다.
특강에서 면접 때 상태관리 도구 왜 썼는지 물어보니까 공부해두라는 얘기를 들었다.
찾아보니 최근앤 Zustand가 가볍고 쓰기도 편해서 자주 쓰이는 것 같았다. (내피셜)
프로젝트를 진행하면서 처음에느 로그인/회원가입 모달 상태에 zustand를 도입했고,
최근에는 스터디 필터링 가능에 zustand를 적용했다.
적용하면서 "아 이때 전역 상태관리를 써야 하구나"하고 감이 잡혔다.
useState
나 useReducer
면 충분처음에는 Context API를 쓸까 했지만,
page.tsx에 필터 버튼만 있는 게 아니라 인기글 컴포넌트, 스터디 리스트도 함께 있어서 <Context.Provider>
로 감싸는 구조가 애매했다.
결국 단순 상태 공유와 빠른 반응성을 위해 zustand를 선택했다.
npm install zustand
store
폴더를 만들어 그 안에 스토어 파일을 관리한다. 파일명은 xxxStore.ts
처럼 작성하는 경우가 많다. // store/modalStore.ts
import { create } from "zustand";
type ModalType = "login" | "signup" | null;
// zustand로 전역 모달 스토어 만들기
interface ModalStore {
openModal: ModalType;
open: (type: ModalType) => void;
close: () => void;
}
export const useModalStore = create<ModalStore>((set) => ({
openModal: null,
open: (type) => set({ openModal: type }),
close: () => set({ openModal: null }),
}));
여기서
interface
는 스토어의 상태와 메서드 구조를 정의하는 역할
create()
함수는 zustand의 핵심 함수로, 스토어를 실제로 생성한다.
useModalStore()
훅을 호출하면 된다.// 예: 로그인 폼에서 모달 닫기
import { useModalStore } from "@/store/modalStore";
export default function LoginForm() {
const { close } = useModalStore();
return (
<button onClick={close}>
닫기
</button>
);
}
이렇게 하면 모달을 여는 컴포넌트, 닫는 컴포넌트가 다른 위치에 있어도 상태를 공유할 수 있다!
기술 스택에 zustand가 있다면 모든 상태를 zustand로 써야 하나?
굳이?
useState
가 더 직관적이고 성능도 좋음.예전 발주 페이지에서도 zustand로 전체 상태를 묶었다가,
셀렉트 버튼 상태는 useState
로 되돌린 적이 있다.
지금 생각하면, 거기서는 zustand를 쓰지 않아도 됐던 것 같다.
상태 공유가 진짜 필요한가? 를 먼저 고민하는 게 중요하다는 걸 이번에 체감할 수 있었다.
여러 컴포넌트가 공유해야 하거나, 비동기/복잡한 상태일 때 zustand!
그 외엔 useState