Ch.22 React 심화 — 상태 관리 패턴

Zustand — 가벼운 상태 관리

Redux와 Zustand의 차이를 비교할 수 있다Zustand store를 생성하고 액션을 정의할 수 있다React 컴포넌트에서 Zustand를 사용할 수 있다

Redux는 복잡하다 더 쉬운 방법이 있다

상태 관리 라이브러리를 검색하면 Redux가 나오지만 action, reducer, dispatch, store 설정에 100줄이 넘습니다.

상태 관리, 10줄이면 충분하지 않을까?

Zustand — 독일어로 '상태'. 최소한의 코드로 전역 상태를 관리합니다.


article

핵심 내용

Zustand은 Redux의 보일러플레이트를 95% 줄였습니다

create() 함수 하나로 상태와 액션을 한 번에 정의합니다

// stores/todo-store.ts
import { create } from "zustand";

interface Todo {
  id: number;
  text: string;
  done: boolean;
}

interface TodoStore {
  todos: Todo[];
  addTodo: (text: string) => void;
  toggleTodo: (id: number) => void;
  removeTodo: (id: number) => void;
}

export const useTodoStore = create<TodoStore>((set) => ({
  // 상태
  todos: [],

  // 액션
  addTodo: (text) => set((state) => ({
    todos: [...state.todos, {
      id: Date.now(),
      text,
      done: false,
    }],
  })),

  toggleTodo: (id) => set((state) => ({
    todos: state.todos.map(t =>
      t.id === id ? { ...t, done: !t.done } : t
    ),
  })),

  removeTodo: (id) => set((state) => ({
    todos: state.todos.filter(t => t.id !== id),
  })),
}));

set() 함수의 원리 set()에 전달한 객체는 기존 상태와 얕은 병합(shallow merge)됩니다. 변경하고 싶은 필드만 반환하면 됩니다.

store를 훅처럼 호출하면 끝 Provider도 필요 없습니다

// 컴포넌트에서 사용
import { useTodoStore } from "@/stores/todo-store";

function TodoList() {
  // 필요한 것만 선택적으로 구독
  const todos = useTodoStore((s) => s.todos);
  const toggleTodo = useTodoStore((s) => s.toggleTodo);

  return (
    <ul>
      {todos.map((todo) => (
        <li
          key={todo.id}
          onClick={() => toggleTodo(todo.id)}
          style={{ textDecoration: todo.done ? "line-through" : "none" }}
        >
          {todo.text}
        </li>
      ))}
    </ul>
  );
}

function AddTodo() {
  const addTodo = useTodoStore((s) => s.addTodo);
  const [text, setText] = useState("");

  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      addTodo(text);
      setText("");
    }}>
      <input value={text} onChange={(e) => setText(e.target.value)} />
      <button type="submit">추가</button>
    </form>
  );
}

바이브 코더 팁 AI에게 "Zustand store로 장바구니 상태 관리해줘"라고 하면 바로 사용할 수 있는 store 코드를 생성합니다.

Zustand을 사용하려면 Redux처럼 Provider로 앱을 감싸야 한다

Zustand에서 상태를 업데이트하는 함수는?

Zustand에서 성능 최적화를 위해 해야 하는 것은?

key

핵심 용어

📝

보일러플레이트

Redux: action + reducer + dispatch / Zustand: create() 하나

🏗️

Provider

Redux: Provider 필수 / Zustand: 불필요

📦

번들 크기

Redux: ~16KB / Zustand: ~1KB

📈

학습 곡선

Redux: 높음 / Zustand: 낮음 (5분이면 시작)

🎯

선택적 구독

s => s.todos처럼 필요한 값만 선택하면 해당 값이 바뀔 때만 리렌더

⚠️

전체 구독 금지

useTodoStore()처럼 전체를 구독하면 어떤 값이든 바뀔 때마다 리렌더

edit_note

정리 노트

Zustand 상태 관리 핵심 정리

Zustand 기본

create()
스토어를 생성하고 상태와 액션을 정의
selector
useStore(s => s.count)처럼 필요한 값만 구독해서 리렌더링 최적화
Provider 불필요
Context와 달리 Provider 없이 어디서든 사용 가능

Context vs Zustand

Context
간단한 전역 데이터(테마, 언어)에 적합, Provider 필요
Zustand
복잡한 상태 로직, 빈번한 업데이트에 적합, 보일러플레이트 최소

Zustand는 selector로 필요한 값만 구독하면 불필요한 리렌더링을 방지할 수 있습니다.

퀴즈와 인터랙션으로 더 깊이 학습하세요

play_circle인터랙티브 레슨 시작