Skip to content

Zustand Store โ€‹

๐Ÿ’ก Point

  • Zustand๋Š” ์ƒํƒœ(state)์™€ ๋กœ์ง(action)์„ ํ•œ ๊ณณ์— ๋ชจ์•„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋ฒผ์šด ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค.
  • useAppStore๋ผ๋Š” ํ›…์„ ๋งŒ๋“ค์–ด๋‘๋ฉด, ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ๋ฐ”๋กœ ๋ถˆ๋Ÿฌ์™€์„œ ๊ฐ’์ด๋‚˜ ํ•จ์ˆ˜๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋‹ค.
    • useAppStore()๋Š” ํ›…์ด๋ฏ€๋กœ ๋ฌด์กฐ๊ฑด ํ•จ์ˆ˜์ฒ˜๋Ÿผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.
    • useAppStore((state) => state.count) ๊ฐ™์ด ์„ ํƒ์ž๋ฅผ ์“ฐ๋ฉด ํ•„์š”ํ•œ ๊ฐ’๋งŒ ๊ตฌ๋…ํ•ด์„œ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.
    • ํ•œ ๋ฒˆ ๋งŒ๋“  ์Šคํ† ์–ด๋Š” ์•ฑ ์ „์ฒด์—์„œ ๋‹จ์ผ ์ธ์Šคํ„ด์Šค(์‹ฑ๊ธ€ํ†ค)๋กœ ๋™์ž‘ํ•ด, ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ™์€ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

1. Store ์ƒ์„ฑํ•˜๊ธฐ โ€‹

useAppStore๋Š” ๋‹จ์ˆœํ•œ ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” React์—์„œ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์ปค์Šคํ…€ ํ›…์ด๋‹ค.
์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ํ˜ธ์ถœํ•˜๋ฉด Zustand๊ฐ€ ์ž๋™์œผ๋กœ ๊ตฌ๋…์„ ๊ฑธ๊ณ , ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•œ๋‹ค.

tsx
import { create } from "zustand";

interface StoreState {
  count: number; // ์ƒํƒœ (state)
  increment: () => void; // ์ƒํƒœ๋ฅผ ๋ฐ”๊พธ๋Š” ํ•จ์ˆ˜ (action)
}

const useAppStore = create<StoreState>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}));

export default useAppStore;
  • create: Zustand์˜ ํ•ต์‹ฌ ํ•จ์ˆ˜, store๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • set: Zustand๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ƒํƒœ ์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜.
  • count : ์ƒํƒœ(state) โ†’ ํ˜„์žฌ ๊ฐ’ ์ €์žฅ์†Œ (์—ฌ๊ธฐ์„  ๊ธฐ๋ณธ๊ฐ’ 0)
  • increment: action โ†’ set์„ ์ด์šฉํ•ด count๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚ค๋Š” ํ•จ์ˆ˜
๐Ÿงฉ ํƒ€์ž… ์„ค๊ณ„ TypeScript

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ• โ€‹

ts
interface StoreState {
  count: number; // ์ˆซ์ž ํƒ€์ž…
  increment: () => void; // ์ธ์ž ์—†์Œ, ๋ฐ˜ํ™˜๊ฐ’ ์—†์Œ
}

StoreState๋ผ๋Š” ์ด๋ฆ„์˜ ํƒ€์ž… ์„ค๊ณ„๋„ ์ƒ์„ฑ

  • count: ๋ฐ˜๋“œ์‹œ ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค.
  • increment: ๋ฐ˜๋“œ์‹œ ํ•จ์ˆ˜์—ฌ์•ผ ํ•˜๋ฉฐ, ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฐ˜ํ™˜๊ฐ’์ด ์—†๋‹ค.

์ด๋ ‡๊ฒŒ ํƒ€์ž…์„ ์ •์˜ํ•˜๋ฉด, store.count = "abc" ๊ฐ™์€ ์‹ค์ˆ˜๋ฅผ ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.


์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ผ๋ฉด? โ€‹

js
const store = {
  count: 0,
  increment: function () {
    store.count += 1;
  },
};

JS์—์„œ๋Š” ๊ตฌ์กฐ๋งŒ ๋งž์œผ๋ฉด ๋ฌธ์ œ์—†์ด ๋™์ž‘ํ•œ๋‹ค. ํ•˜์ง€๋งŒ TS๋Š” ํƒ€์ž… ๊ทœ์น™์„ ์—„๊ฒฉํžˆ ์ง€์ผœ์•ผ ํ•˜๋ฏ€๋กœ ์•ˆ์ •์„ฑ์ด ๋†’์•„์ง„๋‹ค.


2. ์ปดํฌ๋„ŒํŠธ์—์„œ store ์‚ฌ์šฉํ•˜๊ธฐ โ€‹

tsx
import useAppStore from "./store/useAppStore";

function App() {
  const { count, increment } = useAppStore();

  return (
    <div>
      <h1>Hello Zustand</h1>
      <p>{count}</p>

      <button onClick={increment}>increment</button>
    </div>
  );
}

export default App;
tsx
import useAppStore from "./store/useAppStore";

function App() {
  // 1. ๊ฐ๊ฐ ๊บผ๋‚ด ์“ฐ๋Š” ๋ฐฉ๋ฒ• (์„ ํƒ์ž ์‚ฌ์šฉ)
  // const count = useAppStore((state) => state.count);
  // const increment = useAppStore((state) => state.increment);

  // 2. ๊ตฌ์กฐ๋ถ„ํ•ด ํ• ๋‹น์œผ๋กœ ํ•œ ๋ฒˆ์— ๊บผ๋‚ด๊ธฐ (์Šคํ† ์–ด ์ „์ฒด์—์„œ ๊บผ๋ƒ„)
  const { count, increment } = useAppStore();

  return (
    <div>
      <h1>Hello Zustand</h1>
      <p>{count}</p>

      {/* ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋กœ ๊ฐ์Œ€ ํ•„์š” ์—†์Œ */}
      {/* <button onClick={() => increment()}>increment</button> */}

      {/* ํ•จ์ˆ˜ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ์ง์ ‘ ์ „๋‹ฌ (increment๊ฐ€ ํ•จ์ˆ˜์ด๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ ๊ฐ€๋Šฅ) */}
      <button onClick={increment}>increment</button>
    </div>
  );
}

export default App;
tsx
import { create } from "zustand";

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

const useAppStore = create<StoreState>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}));

export default useAppStore;
  • onClick={increment}: ๋ฒ„ํŠผ์ด ํด๋ฆญ๋˜๋ฉด increment ์‹คํ–‰
  • onClick={() => increment()}: ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์ต๋ช… ํ•จ์ˆ˜ ์‹คํ–‰, ๊ทธ ์•ˆ์—์„œ increment() ํ˜ธ์ถœ

ํ˜„์žฌ ์ฝ”๋“œ์—์„  ๋‘ ๋ฐฉ์‹์ด ๋™์ผํ•˜์ง€๋งŒ, ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋„˜๊ฒจ์•ผ ํ•  ๋•Œ๋Š” ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.


์ƒํƒœ ๊ตฌ๋… ๋ฐฉ์‹ โ€‹

  • useAppStore((state) => state.count): count๋งŒ ๊ตฌ๋…
  • useAppStore((state) => state.increment): increment๋งŒ ๊ตฌ๋…
  • useAppStore(): ์Šคํ† ์–ด ์ „์ฒด๋ฅผ ๊ฐ€์ ธ์™€ ํ•„์š”ํ•œ ๊ฐ’ ๊บผ๋ƒ„

ํ•„์š”ํ•œ ๊ฐ’๋งŒ ์„ ํƒ์ ์œผ๋กœ ๊ตฌ๋…ํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.


์‹คํ–‰ ํ๋ฆ„ ์š”์•ฝ โ€‹

  1. ์•ฑ ์‹œ์ž‘ โ†’ useAppStore ์ƒ์„ฑ (count=0, increment ์ค€๋น„๋จ)
  2. App ์ปดํฌ๋„ŒํŠธ๊ฐ€ count ๊ตฌ๋…
  3. ๋ฒ„ํŠผ ํด๋ฆญ โ†’ increment ์‹คํ–‰ โ†’ count + 1
  4. Zustand๊ฐ€ ๊ฐ’ ๋ณ€๊ฒฝ ๊ฐ์ง€ โ†’ ์ปดํฌ๋„ŒํŠธ ๋ฆฌ๋ Œ๋”๋ง
  5. ์ƒˆ๋กœ์šด count ๊ฐ’์ด ํ™”๋ฉด์— ๋ฐ˜์˜

์ˆจ๊ฒจ์ง„ ์œ ํ‹ธ โ€‹

Zustand store๋Š” ํ›…์ด๋ฉด์„œ ๋™์‹œ์— ์Šคํ† ์–ด ํ•ธ๋“ค์„ ๊ฐ€์ง„๋‹ค.

tsx
useAppStore.getState()    // ํ˜„์žฌ ์ƒํƒœ ๊ฐ€์ ธ์˜ค๊ธฐ
useAppStore.setState(...) // ์ƒํƒœ ์ง์ ‘ ๋ณ€๊ฒฝ
useAppStore.subscribe(...)// ์ƒํƒœ ๋ณ€๊ฒฝ ๊ตฌ๋…

์ฆ‰, React ํ›…์ฒ˜๋Ÿผ ์“ฐ๋ฉด์„œ๋„, ๋ฆฌ์•กํŠธ ๋ฐ”๊นฅ์—์„œ๋„ ์ƒํƒœ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.