웹개발/React

React - Zustand

bergerac 2025. 5. 15. 09:11

Zustand란?

Zustand는 React Hooks 기반의 상태 관리 라이브러리다. 불필요한 보일러플레이트 없이. 간단한 API로도 충분히 전역 상태를 관리할 수 있다.

  • 간결성: create 함수 하나로 store 생성
  • 유연성: 다양한 상태 조각을 하나의 store에서 관리 가능
  • 자동 상태 추적: 컴포넌트에서 필요한 상태만 구독

설치하기

npm i zustand

 

1. 전역 Store 생성

Zustand는 create 함수를 통해 store를 생성한다.

store의 이름은 보통 use+데이터명+Store로 작성한다.

import { create } from 'zustand';

interface CountState {
  count: number;
  increment: () => void;
  decrement: () => void;
}

export const useCountStore = create<CountState>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}));

 

2. store 사용하기

생성한 store 컴포넌트 내에서 훅처럼 호출해서 사용하면 된다. 필요한 상태와 메서드를 구조분해할당으로 가져오자

function Component() {
  const { count, increment } = useCountStore();

  return (
    <div>
      <p>{count}</p>
      <button onClick={increment}>증가</button>
    </div>
  )
}

 

3. 여러 store과 함께 사용하기

zustand는 여러 store를 독립적으로 정의하고 사용할 수 있다.

import { useRef, useState } from "react";
import { useUsersStore } from "@/stores/user.store";
import { useAuthStore } from "@/stores/auth.store";

function Zustand02() {
  const { users, addUser } = useUsersStore();
  const userIdRef = useRef(1);
  const { user, logout } = useAuthStore();
  const [username, setUsername] = useState("");

  const handleCreate = () => {
    addUser({
      id: userIdRef.current,
      name: "bergerac",  // 원래는 '이승아'
    });

    userIdRef.current += 1;
  };

  return (
    <div>
      {users.map((user) => (
        <div key={user.id}>
          {user.id} / {user.name}
        </div>
      ))}
      <button onClick={handleCreate}>사용자 추가</button>

      <p>Welcome: {user}</p>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <button onClick={() => useAuthStore.getState().login(username)}>로그인</button>
      <button onClick={logout}>로그아웃</button>
    </div>
  );
}

예제를 통한 Zustand 사용법

// auth.store.ts

import { create } from "zustand";

// 인증 상태 정의
interface AuthState {
  user: string | null;
  isLogged: boolean;
  login: (user: string) => void;
  logout: () => void;
}

// Zustand 저장소 생성
export const useAuthStore = create<AuthState>(set => ({
  user: null,
  isLogged: false,
  login: (user) => set({ user, isLogged: true }),
  logout: () => set({ user: null, isLogged: false }),
}));
  • user에는 로그인한 사용자의 이름이 들어간다.
  • 로그인 시 login(user) 호출 → user에 값 저장, isLogged는 true.
  • 로그아웃 시 logout() 호출 → 상태 초기화.

예를 들어, login('bergerac')을 호출하면 아래와 같은 상태가 된다:

{
  user: 'bergerac',
  isLogged: true
}

사용자 데이터 관리

여러 사용자들을 등록하고 수정하고 삭제하는 저장소 만들기

import { create } from "zustand";

// 사용자 타입 정의
interface User {
  id: number;
  name: string;
}

// 사용자 상태 정의
interface UserState {
  users: User[];
  addUser: (user: User) => void;
  updateUser: (id: number, name: string) => void;
  deleteUser: (id: number) => void;
}

// Zustand 저장소 생성
export const useUsersStore = create<UserState>((set) => ({
  users: [],

  addUser: (user) => set((state) => ({
    users: [...state.users, user]
  })),

  updateUser: (id, name) => set((state) => ({
    users: state.users.map(user =>
      user.id === id ? { ...user, name } : user
    )
  })),

  deleteUser: (id) => set((state) => ({
    users: state.users.filter(user => user.id !== id)
  })),
}));
  • addUser(user) → 새로운 사용자 추가
  • updateUser(id, name) → 특정 사용자의 이름 수정
  • deleteUser(id) → 특정 사용자 삭제

이처럼 set 함수를 이용해 이전 상태를 기반으로 새로운 상태를 계산할 수 있다.


컴포넌트의 사용 예시

zustand는 훅처럼 사용한다. 저장소를 불러와 상태를 직접 가져오고 수정할 수 있다.

import { useAuthStore } from "./auth.store";

function LoginButton() {
  const login = useAuthStore(state => state.login);

  return (
    <button onClick={() => login("bergerac")}>
      로그인
    </button>
  );
}

사용자 목록 출력

import { useUsersStore } from "./user.store";

function UserList() {
  const users = useUsersStore(state => state.users);

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

'웹개발 > React' 카테고리의 다른 글

React - Style 적용하기  (0) 2025.05.16
React - Context  (1) 2025.05.14
React - Axios로 HTTP 요청 보내기  (0) 2025.05.13
React - routing, navigate  (0) 2025.05.12
React - 커스텀 훅(Custom Hook)만들기  (0) 2025.05.11