OPEN HYPER STEP
← 목록으로 (stack-analysis)
STACK-ANALYSIS · 6 / 90
stack-analysis
CHAPTER 6 / 90
읽기 약 2
FUNCTION

상태 관리 비교: useState vs Zustand vs Redux


핵심 개념

로컬 vs 글로벌 판단·Zustand 패턴·Redux Toolkit·Jotai/Recoil — 이커머스 장바구니.

본문

상태 관리 결정 트리

📋 코드 (9줄)
상태가 컴포넌트 1개에서만 사용?
├─ Yes → useState
└─ No (여러 컴포넌트 공유)
    ├─ 부모-자식 관계 단순?
    │   ├─ Yes → props drilling 또는 context
    │   └─ No
    │       ├─ 작은 앱 + 단순 상태 → Zustand
    │       ├─ 큰 앱 + 복잡 상태 → Redux Toolkit
    │       └─ Atomic 모델 선호 → Jotai

Zustand — 가장 단순한 글로벌 상태

TYPESCRIPT📋 코드 (64줄)
// store/cart.ts
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

type CartItem = { id: string; name: string; price: number; quantity: number };

type CartStore = {
  items: CartItem[];
  addItem: (item: Omit<CartItem, 'quantity'>) => void;
  removeItem: (id: string) => void;
  updateQuantity: (id: string, qty: number) => void;
  total: () => number;
  clear: () => void;
};

export const useCartStore = create<CartStore>()(
  persist(
    (set, get) => ({
      items: [],
      addItem: (item) => set((state) => {
        const existing = state.items.find(i => i.id === item.id);
        if (existing) {
          return {
            items: state.items.map(i =>
              i.id === item.id ? { ...i, quantity: i.quantity + 1 } : i
            ),
          };
        }
        return { items: [...state.items, { ...item, quantity: 1 }] };
      }),
      removeItem: (id) => set((state) => ({
        items: state.items.filter(i => i.id !== id),
      })),
      updateQuantity: (id, qty) => set((state) => ({
        items: state.items.map(i => i.id === id ? { ...i, quantity: qty } : i),
      })),
      total: () => get().items.reduce((sum, i) => sum + i.price * i.quantity, 0),
      clear: () => set({ items: [] }),
    }),
    { name: 'cart-storage' }  // localStorage
  )
);


// 사용
function CartIcon() {
  const itemCount = useCartStore((state) => state.items.length);
  return <div>장바구니: {itemCount}</div>;
}

function CartPage() {
  const { items, removeItem, total } = useCartStore();
  return (
    <div>
      {items.map(item => (
        <div key={item.id}>
          {item.name} x {item.quantity}
          <button onClick={() => removeItem(item.id)}>제거</button>
        </div>
      ))}
      <div>총: {total()}원</div>
    </div>
  );
}

Redux Toolkit — 큰 앱

TYPESCRIPT📋 코드 (41줄)
// store/cartSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';

const cartSlice = createSlice({
  name: 'cart',
  initialState: { items: [] as CartItem[] },
  reducers: {
    addItem: (state, action: PayloadAction<Omit<CartItem, 'quantity'>>) => {
      const existing = state.items.find(i => i.id === action.payload.id);
      if (existing) {
        existing.quantity += 1;
      } else {
        state.items.push({ ...action.payload, quantity: 1 });
      }
    },
    removeItem: (state, action: PayloadAction<string>) => {
      state.items = state.items.filter(i => i.id !== action.payload);
    },
  },
});

export const { addItem, removeItem } = cartSlice.actions;
export default cartSlice.reducer;


// store/index.ts
import { configureStore } from '@reduxjs/toolkit';
import cartReducer from './cartSlice';

export const store = configureStore({
  reducer: { cart: cartReducer },
});


// 사용
import { useDispatch, useSelector } from 'react-redux';

function CartIcon() {
  const items = useSelector((state: RootState) => state.cart.items);
  return <div>장바구니: {items.length}</div>;
}

Jotai — Atomic

TYPESCRIPT📋 코드 (19줄)
// atoms.ts
import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';

export const itemsAtom = atomWithStorage<CartItem[]>('cart', []);

export const totalAtom = atom((get) =>
  get(itemsAtom).reduce((sum, i) => sum + i.price * i.quantity, 0)
);


// 사용
import { useAtom, useAtomValue } from 'jotai';

function Cart() {
  const [items, setItems] = useAtom(itemsAtom);
  const total = useAtomValue(totalAtom);
  // ...
}

비교

📋 코드 (7줄)
| 라이브러리 | 번들 크기 | 학습 곡선 | 적합 |
|---|---|---|---|
| useState | 0 | ⭐ | 컴포넌트 로컬 |
| Context | 0 | ⭐⭐ | 작은 앱 + 단순 |
| Zustand | 1KB | ⭐⭐ | 중규모 + 단순 |
| Jotai | 3KB | ⭐⭐⭐ | atomic 선호 |
| Redux Toolkit | 14KB | ⭐⭐⭐⭐ | 대규모 + 복잡 |

다음 챕터

CH.7 "데이터 페칭: TanStack Query" — 서버 상태 관리.


AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 코드의 상태 관리 부분을 분석해서
실전 분석 + 개선 우선순위를 알려줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

상태 관리 관련 인기 라이브러리/패턴 5개를
비교 분석해서 패턴 추출를 알려줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 프로젝트 전체에서 상태 관리
최적화 가능 위치를 보고해줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 한국 프론트엔드 시장의
상태 관리 트렌드를 솔직히 알려줘.

⭐ 이것만 기억하세요
상태 관리 비교: useState vs Zustand vs Redux 이 3가지만 확실히 잡으세요
1.Zustand는 가장 단순 + 작은 번들 — 80% 케이스에 충분
2.Redux Toolkit은 큰 팀 + 복잡한 상태 — 학습 곡선 높지만 도구 풍부
3.다음 챕터 CH.7에서 TanStack Query — 서버 상태는 클라이언트 상태와 별개


공유하기
진행도 6 / 90