๐Ÿป 25. Zustand ์ƒํƒœ๊ด€๋ฆฌ ๋ณต์Šต โ€” 1๋ถ€ํ„ฐ 100๊นŒ์ง€ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋„๋ก

JM_Devยท2025๋…„ 5์›” 5์ผ
0
post-thumbnail

ํ”„๋ก ํŠธ์—”๋“œ ์ƒํƒœ ๊ด€๋ฆฌ ๋„๊ตฌ๋Š” ์ •๋ง ๋งŽ๋‹ค.
๊ทธ ์ค‘์—์„œ๋„ ์ตœ๊ทผ ๋“ค์–ด React์—์„œ ๊ฐ€์žฅ ํ•ซํ•œ ๊ฒฝ๋Ÿ‰ ์ƒํƒœ ๊ด€๋ฆฌ ๋„๊ตฌ๊ฐ€ ๋ฐ”๋กœ Zustand์ด๋‹ค.

์ด๋ฒˆ ๊ธ€์€ Zustand๋ฅผ ์ฒ˜์Œ ๋“ค์–ด๋ณด๋Š” ์‚ฌ๋žŒ๋„ ๊ฐœ๋…๋ถ€ํ„ฐ ์‹ค์ „๊นŒ์ง€ ๋ฐ”๋กœ ๋”ฐ๋ผ์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ
์™„์ „ ๊ธฐ์ดˆ๋ถ€ํ„ฐ ์‹ค์Šต ์ฝ”๋“œ, ์žฅ๋‹จ์ , ์‚ฌ์šฉ ํŒ๊นŒ์ง€ ์ •๋ฆฌํ•ด๋ดค๋‹ค.


โœ… Zustand๋ž€?

๋…์ผ์–ด๋กœ "์ƒํƒœ(state)"๋ผ๋Š” ๋œป์ด๊ณ ,
"๊ฐ€๋ณ๊ณ  ์ง๊ด€์ ์ธ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ"

  • Redux๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ„๋‹จํ•˜๊ณ  ์ฝ”๋“œ๋Ÿ‰์ด ์ ๋‹ค
  • Context ์—†์ด๋„ ์ „์—ญ ์ƒํƒœ ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅ
  • ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง๋„ ์ž๋™์œผ๋กœ ๋ฐฉ์ง€ํ•ด์คŒ

๐Ÿ“ฆ ์„ค์น˜ ๋ฐฉ๋ฒ•:

npm install zustand
# ๋˜๋Š”
yarn add zustand

โš™๏ธ ๊ธฐ๋ณธ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

// store.ts
import { create } from 'zustand';

type State = {
  count: number;
  increase: () => void;
  decrease: () => void;
};

export const useCounterStore = create<State>((set) => ({
  count: 0,
  increase: () => set((state) => ({ count: state.count + 1 })),
  decrease: () => set((state) => ({ count: state.count - 1 })),
}));
// App.tsx
import { useCounterStore } from './store';

export default function App() {
  const { count, increase, decrease } = useCounterStore();

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={increase}>+1</button>
      <button onClick={decrease}>-1</button>
    </div>
  );
}

๐Ÿ’ก useCounterStore() ํ›…๋งŒ ๋ถˆ๋Ÿฌ์„œ ์–ด๋””์„œ๋“  ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.
Context, Provider ์ „ํ˜€ ํ•„์š” ์—†์Œ!


๐Ÿง  ์ƒํƒœ ๊ตฌ๋… ์ตœ์ ํ™” (select ์‚ฌ์šฉ)

const count = useCounterStore((state) => state.count);
  • ํŠน์ • ์ƒํƒœ๋งŒ ๊ตฌ๋…ํ•ด์„œ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง ๋ฐฉ์ง€ ๊ฐ€๋Šฅ
  • ๊ธฐ์กด Redux์˜ useSelector์™€ ๋น„์Šทํ•˜์ง€๋งŒ ํ›จ์”ฌ ๊ฐ€๋ณ๊ณ  ์ž์œ ๋กญ๋‹ค

๐Ÿงช ์—ฌ๋Ÿฌ store๋ฅผ ๋ถ„๋ฆฌํ•˜๊ณ  ์‹ถ์„ ๋•?

// userStore.ts
export const useUserStore = create(() => ({
  name: 'unknown',
  setName: (name: string) => set({ name }),
}));

// uiStore.ts
export const useUIStore = create(() => ({
  isModalOpen: false,
  toggleModal: () => set((s) => ({ isModalOpen: !s.isModalOpen })),
}));
  • ๊ด€์‹ฌ์‚ฌ๋ณ„๋กœ ์Šคํ† ์–ด๋ฅผ ๋‚˜๋ˆ ์„œ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ
  • ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ๊ฐ€ ์ปค์ ธ๋„ ์ƒํƒœ ๋ถ„๋ฆฌ๊ฐ€ ์‰ฌ์›€

๐Ÿงฉ Redux์™€ ๋น„๊ตํ•ด๋ณด๋ฉด?

ํ•ญ๋ชฉReduxZustand
์ฝ”๋“œ๋Ÿ‰๋งŽ์Œ์ ์Œ (Hooks ๊ธฐ๋ฐ˜)
๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ๋งŽ์Œ (action, reducer ๋“ฑ)๊ฑฐ์˜ ์—†์Œ
๋ฆฌ๋ Œ๋”๋ง ๊ด€๋ฆฌ์ง์ ‘ memoization ํ•„์š”์ž๋™์œผ๋กœ ์ตœ์†Œํ™”ํ•จ
Provider ํ•„์š”์žˆ์ŒโŒ ํ•„์š” ์—†์Œ
TypeScript ์ง€์›OO (ํƒ€์ž… ์ถ”๋ก ๋„ ๋›ฐ์–ด๋‚จ)

๐ŸŽฏ ์–ธ์ œ Zustand๋ฅผ ์„ ํƒํ•˜๋ฉด ์ข‹์„๊นŒ?

  • Redux๋Š” ๋„ˆ๋ฌด ๋ฌด๊ฒ๊ณ  ๋ณต์žกํ•˜๋‹ค๊ณ  ๋А๊ปด์งˆ ๋•Œ
  • Context๋กœ๋Š” ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ต๊ฑฐ๋‚˜ ๋ฐ˜๋ณต๋  ๋•Œ
  • ๋น ๋ฅด๊ฒŒ ํ”„๋กœํ† ํƒ€์ž…์„ ๋งŒ๋“ค๊ฑฐ๋‚˜ ์ž‘์€ ํ”„๋กœ์ ํŠธ์ผ ๋•Œ
  • ๊ฒŒ์ž„, ๋Œ€์‹œ๋ณด๋“œ, ์†Œ์ผ“ ์ƒํƒœ ๋“ฑ ๋น ๋ฅธ ์ƒํƒœ ๋ณ€ํ™” ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ

๐Ÿ“ ๋‚ด๊ฐ€ ๋А๋‚€ ์ 

Zustand๋Š” Redux์ฒ˜๋Ÿผ "์–ด๋ ต๊ฒŒ ๋ฐฐ์šฐ๊ณ  ์จ์•ผ ํ•œ๋‹ค"๋Š” ๋А๋‚Œ์ด ์•„๋‹ˆ๋ผ
"Hook์ฒ˜๋Ÿผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์จ์ง€๋Š”๋ฐ, ์ „์—ญ ์ƒํƒœ๊ฐ€ ๋œ๋‹ค"๋Š” ์ ์ด ๋„ˆ๋ฌด ์ข‹์•˜๋‹ค.
ํŠนํžˆ ์ƒํƒœ ๊ตฌ๋… ์ตœ์ ํ™”๊ฐ€ ์ž˜ ๋ผ์„œ, ๋ฆฌ๋ Œ๋”๋ง ์„ฑ๋Šฅ ์ด์Šˆ๋„ ๊ฑฐ์˜ ์—†์—ˆ๋‹ค.

์ง€๊ธˆ์€ ๊ฑฐ์˜ ๋ชจ๋“  ํ”„๋กœ์ ํŠธ์—์„œ ๊ธฐ๋ณธ ์ƒํƒœ ๊ด€๋ฆฌ๋Š” Zustand๋กœ ์‚ฌ์šฉ ์ค‘์ด๋‹ค.


๐Ÿพ โ€œ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ๋ฌด๊ฒ๊ณ  ๋ณต์žกํ•˜๋‹ค๊ณ  ๋А๊ปด์กŒ๋‹ค๋ฉด,
Zustand๋Š” ํ•œ ๋ฒˆ์ฏค ๊ผญ ์จ๋ณผ๋งŒํ•œ ๋Œ€์•ˆ์ด๋‹ค.โ€

profile
๊ฐœ๋ฐœ์ž๋กœ ์ทจ์—…์„ ์ค€๋น„ ์ค‘ ์ด๋ฉฐ, ์—ด์‹ฌํžˆ ๊ณต๋ถ€ ์ค‘ ์ž…๋‹ˆ๋‹ค!

0๊ฐœ์˜ ๋Œ“๊ธ€