๐Ÿป Zustand Copilot ์†Œ๊ฐœ: Zustand ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ๊ถ๊ทน์ ์ธ VS Code ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ

๋ฐœํ–‰: (2025๋…„ 12์›” 27์ผ ์˜ค์ „ 04:11 GMT+9)
7 min read
์›๋ฌธ: Dev.to

Source: Dev.to

Cover image for ๐Ÿป Introducing Zustand Copilot: The Ultimate VS Code Extension for Zustand State Management

Mahmud Rahman

React์—์„œ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด Zustand๋ฅผ ์‚ฌ์šฉํ•ด ์™”๋‹ค๋ฉด, ๊ทธ ์šฐ์•„ํ•จ๊ณผ ๊ฐ•๋ ฅํ•จ์„ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ์„ ๊ฒ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Zustand ๊ฐœ๋ฐœ ๊ฒฝํ—˜์„ ๋”์šฑ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค๋ฉด ์–ด๋–จ๊นŒ์š”?

์˜ค๋Š˜, ์ €๋Š” Zustand Copilot์„ ์†Œ๊ฐœํ•˜๊ฒŒ ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค โ€” Zustandโ€ฏv5+ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ๊ถ๊ทน์ ์ธ ํˆดํ‚ท์ด ๋˜๋„๋ก ์„ค๊ณ„๋œ VSโ€ฏCode ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค.

๐Ÿค” ๋‚ด๊ฐ€ ์ด๊ฒƒ์„ ๋งŒ๋“  ์ด์œ 

  • ๐Ÿ“ ๊ฐ™์€ ์Šคํ† ์–ด ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ ํƒ€์ดํ•‘ํ•˜๊ธฐ
  • ๐Ÿ” ๊ตฌ๋ฌธ ์ฐธ๊ณ ๋ฅผ ์œ„ํ•ด ๋ฌธ์„œ๋ฅผ ๊ณ„์† ์ „ํ™˜ํ•˜๊ธฐ
  • ๐Ÿ˜“ ๋‹ค์ค‘ ๊ฐ’ ์…€๋ ‰ํ„ฐ์— useShallow ์‚ฌ์šฉ์„ ์žŠ์Œ (๋ถˆํ•„์š”ํ•œ ์žฌ๋ Œ๋”๋ง ๋ฐœ์ƒ!)
  • ๐Ÿ“ ํฐ ์•ฑ์„ ์œ„ํ•ด Slices Pattern์„ ์ˆ˜๋™์œผ๋กœ ์„ค์ •ํ•˜๊ธฐ

Zustand Copilot์€ ์ด๋Ÿฌํ•œ ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

โœจ ์ฃผ์š” ๊ธฐ๋Šฅ

1. TypeScriptโ€‘First ์Šค๋‹ˆํŽซ

ํ”„๋ฆฌํ”ฝ์Šค๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋ฐ”๋กœ ํ”„๋กœ๋•์…˜ ์ˆ˜์ค€์˜ ์ฝ”๋“œ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ ‘๋‘์‚ฌ์–ป๋Š” ๋‚ด์šฉ
zstore๊ฐœ๋ฐœ์ž ๋„๊ตฌ๊ฐ€ ํฌํ•จ๋œ ์™„์ „ํ•œ ์Šคํ† ์–ด
zsliceSlices ํŒจํ„ด์šฉ ์Šฌ๋ผ์ด์Šค
zpersistlocalStorage์™€ ํ•จ๊ป˜ ์˜๊ตฌํ™”๋œ ์Šคํ† ์–ด
zshallowuseShallow ์…€๋ ‰ํ„ฐ (์„ฑ๋Šฅ ์ตœ์ ํ™”!)
zasync๋กœ๋”ฉ ์ƒํƒœ๋ฅผ ํฌํ•จํ•œ ๋น„๋™๊ธฐ ์Šคํ† ์–ด
zimmerImmerโ€‘๊ธฐ๋ฐ˜ ๊ฐ€๋ณ€ ์—…๋ฐ์ดํŠธ

์˜ˆ์‹œ โ€“ zstore๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜์˜ต๋‹ˆ๋‹ค:

import { create } from 'zustand';
import { devtools } from 'zustand/middleware';

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

export const useCounterStore = create()(
  devtools(
    (set) => ({
      count: 0,
      increment: () =>
        set((state) => ({ count: state.count + 1 }), false, 'increment'),
      decrement: () =>
        set((state) => ({ count: state.count - 1 }), false, 'decrement'),
      reset: () => set({ count: 0 }, false, 'reset'),
    }),
    { name: 'CounterStore' }
  )
);

2. ์Šค๋งˆํŠธ ์ฝ”๋“œ ์•ก์…˜

์Šคํ† ์–ด๋ฅผ ๋งˆ์šฐ์Šค ์˜ค๋ฅธ์ชฝ ๋ฒ„ํŠผ์œผ๋กœ ํด๋ฆญํ•˜๋ฉด ์ง€๋Šฅํ˜• ๋ฆฌํŒฉํ„ฐ๋ง ์˜ต์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

  • devtools๋กœ ๋ž˜ํ•‘ โ€“ Redux DevTools ํ†ตํ•ฉ์„ ์ฆ‰์‹œ ์ถ”๊ฐ€
  • persist๋กœ ๋ž˜ํ•‘ โ€“ localStorage ์˜๊ตฌํ™” ์ถ”๊ฐ€
  • useShallow ์ถ”๊ฐ€ โ€“ ์…€๋ ‰ํ„ฐ๋ฅผ ์„ฑ๋Šฅ ์ตœ์ ํ™”
  • Slices ํŒจํ„ด์œผ๋กœ ์ถ”์ถœ โ€“ ํฐ ์Šคํ† ์–ด๋ฅผ ๋ชจ๋“ˆํ™”

3. ์‹ค์‹œ๊ฐ„ ํ˜ธ๋ฒ„ ๋ฌธ์„œํ™”

Zustand ํ•จ์ˆ˜ ์œ„์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ฌ๋ฆฌ๋ฉด ๋‹ค์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • ๐Ÿ“– ์ƒ์„ธ ์„ค๋ช…
  • ๐Ÿ“ TypeScript ์‹œ๊ทธ๋‹ˆ์ฒ˜
  • ๐Ÿ’ป ์‚ฌ์šฉ ์˜ˆ์‹œ
  • โšก ์„ฑ๋Šฅ ํŒ
  • ๐Ÿ”— ๊ณต์‹ ๋ฌธ์„œ ๋งํฌ

4. ์ง€๋Šฅํ˜• ์ž๋™ import

ํƒ€์ดํ•‘์„ ์‹œ์ž‘ํ•˜๋ฉด ๋‹ค์Œ์— ๋Œ€ํ•œ ์Šค๋งˆํŠธ import ์ œ์•ˆ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค:

  • create, createStore, useStore
  • devtools, persist, immer
  • useShallow (์„ฑ๋Šฅ ํžŒํŠธ ํฌํ•จ!)
  • StateCreator, StoreApi ํƒ€์ž…

5. ๋ช…๋ น ๊ธฐ๋ฐ˜ ์Šคํ† ์–ด ์ƒ์„ฑ

๋ช…๋ น ํŒ”๋ ˆํŠธ(Ctrl+Shift+P)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ:

  • ์ƒˆ ์Šคํ† ์–ด ๋งŒ๋“ค๊ธฐ โ€“ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์Šคํ† ์–ด ์ƒ์„ฑ๊ธฐ
  • ์ƒˆ ์Šฌ๋ผ์ด์Šค ๋งŒ๋“ค๊ธฐ โ€“ ์Šฌ๋ผ์ด์Šค ํŒŒ์ผ ์ƒ์„ฑ
  • Slices ํŒจํ„ด ์Šคํ† ์–ด ์ƒ์„ฑ โ€“ ์ „์ฒด ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ์ž๋™ ์ƒ์„ฑ

โšก Performance Best Practices Builtโ€‘In

Zustand Copilot์€ ์ฝ”๋“œ๋ฅผ ๋” ๋น ๋ฅด๊ฒŒ ์ž‘์„ฑํ•˜๋„๋ก ๋„์™€์ค„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋” ๋‚˜์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

useShallow Everywhere

// โŒ Bad: Creates a new object on every render
const { name, age } = useStore((state) => ({
  name: state.name,
  age: state.age,
}));

// โœ… Good: Shallow comparison prevents reโ€‘renders
const { name, age } = useStore(
  useShallow((state) => ({
    name: state.name,
    age: state.age,
  }))
);

ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์€ useShallow๋ฅผ ๋นผ๋จน์—ˆ์„ ๋•Œ ๊ฒฝ๊ณ ๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ์ž๋™์œผ๋กœ ์ถ”๊ฐ€ํ•ด ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

Slices Pattern for Scale

๋Œ€๊ทœ๋ชจ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•ด ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์€ Slices Pattern์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค:

src/stores/
โ”œโ”€โ”€ index.ts           # Combined store
โ””โ”€โ”€ slices/
    โ”œโ”€โ”€ authSlice.ts   # Authentication
    โ”œโ”€โ”€ userSlice.ts   # User data
    โ””โ”€โ”€ settingsSlice.ts # Settings

Zustand: Generate Slices Pattern Store ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด ์ด ๊ตฌ์กฐ๋ฅผ ์ฆ‰์‹œ ์Šค์บํด๋”ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿš€ ์‹œ์ž‘ํ•˜๊ธฐ

์„ค์น˜

  1. VSโ€ฏCode๋ฅผ ์—ฝ๋‹ˆ๋‹ค.
  2. Ctrl+Shift+X๋ฅผ ๋ˆŒ๋Ÿฌ Extensions๋ฅผ ์—ฝ๋‹ˆ๋‹ค.
  3. **โ€œZustand Copilotโ€**์„ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.
  4. Install๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

๋˜๋Š” CLI๋ฅผ ํ†ตํ•ด ์„ค์น˜:

code --install-extension devplusfun.zustand-copilot

๋น ๋ฅธ ์‹œ์ž‘

  1. ์ƒˆ๋กœ์šด .ts ๋˜๋Š” .tsx ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  2. zstore๋ฅผ ์ž…๋ ฅํ•˜๊ณ  Tab ํ‚ค๋ฅผ ๋ˆ„๋ฆ…๋‹ˆ๋‹ค.
  3. ์ž๋ฆฌ ํ‘œ์‹œ์ž๋ฅผ ์ฑ„์›๋‹ˆ๋‹ค.
  4. ๋นŒ๋“œ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค! ๐Ÿป

๐Ÿ“Š ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์Šค๋‹ˆํŽซ

SnippetDescription
zstore๊ฐœ๋ฐœ์ž ๋„๊ตฌ๊ฐ€ ํฌํ•จ๋œ ๊ธฐ๋ณธ ์Šคํ† ์–ด
zsliceSlices ํŒจํ„ด์šฉ ์Šฌ๋ผ์ด์Šค
zpersist์˜์†ํ™”๋œ ์Šคํ† ์–ด
zasync๋กœ๋”ฉ์ด ์žˆ๋Š” ๋น„๋™๊ธฐ ์Šคํ† ์–ด
zimmerImmer ๋ฏธ๋“ค์›จ์–ด ์Šคํ† ์–ด
zslices๊ฒฐํ•ฉ๋œ ์Šฌ๋ผ์ด์Šค ์Šคํ† ์–ด
zshallowuseShallow ์…€๋ ‰ํ„ฐ
zselector๋ฉ”๋ชจ์ด์ œ์ด์…˜๋œ ์…€๋ ‰ํ„ฐ
zsubscribe์Šคํ† ์–ด ๊ตฌ๋…
zgetstateReact ์™ธ๋ถ€์—์„œ ์ƒํƒœ ์ ‘๊ทผ
zcontext์ปจํ…์ŠคํŠธ ํŒจํ„ด ์Šคํ† ์–ด
zcomputed๊ณ„์‚ฐ๋œ ์†์„ฑ
zreset๋ฆฌ์…‹ ๊ธฐ๋Šฅ์ด ์žˆ๋Š” ์Šคํ† ์–ด
zmiddleware์ „์ฒด ๋ฏธ๋“ค์›จ์–ด ์Šคํƒ
zactions๋ณ„๋„ ์•ก์…˜ ์ธํ„ฐํŽ˜์ด์Šค
ztemporalzundo๋ฅผ ์ด์šฉํ•œ ์‹คํ–‰ ์ทจ์†Œ/์žฌ์‹คํ–‰

๐Ÿ›  ๊ตฌ์„ฑ

VSโ€ฏCode ์„ค์ •์—์„œ ํ™•์žฅ์„ ์‚ฌ์šฉ์ž ์ •์˜ํ•˜์„ธ์š”:

{
  "zustandCopilot.autoImport.enabled": true,
  "zustandCopilot.hoverDocs.enabled": true,
  "zustandCopilot.codeActions.enabled": true,
  "zustandCopilot.defaultStorePath": "src/stores",
  "zustandCopilot.useShallowByDefault": true,
  "zustandCopilot.snippets.enabled": true,
  "zustandCopilot.commandPalette.enabled": true
}

๐Ÿ™ Feedback Welcome!

This is just version 1.0.0, and I have big plans for future releases:

  • ๐Ÿ“Š Store visualization panel
  • ๐Ÿงช Testing utilities
  • ๐Ÿ”„ Redux โ†’ Zustand migration tools
  • ๐Ÿ“ˆ Performance analysis

What features would you like to see? Drop a comment below or open an issue on GitHub!

๐Ÿ”— ๋งํฌ

If this extension helps your Zustand development, please โญ star the repo and leave a review on the marketplace! It really helps others discover it.
โ†’ ์ด ํ™•์žฅ์ด ์—ฌ๋Ÿฌ๋ถ„์˜ Zustand ๊ฐœ๋ฐœ์— ๋„์›€์ด ๋œ๋‹ค๋ฉด, โญ ๋ ˆํฌ์— ๋ณ„ํ‘œ๋ฅผ ๋‹ฌ๊ณ  ๋งˆ์ผ“ํ”Œ๋ ˆ์ด์Šค์— ๋ฆฌ๋ทฐ๋ฅผ ๋‚จ๊ฒจ ์ฃผ์„ธ์š”! ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ์ฐพ๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

Happy coding! ๐Ÿปโœจ

{
  "ot.includeDevtools": true
}
Back to Blog

๊ด€๋ จ ๊ธ€

๋” ๋ณด๊ธฐ ยป

์—ฐํ•ฉ ์ƒํƒœ๋ฅผ ์ œ๋Œ€๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ: Zustand, TanStack Query, ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ๋กœ ์ž‘๋™ํ•˜๋Š” ํŒจํ„ด๋“ค

๋ฌธ์ œ ์šฐ๋ฆฌ ๋ชจ๋‘ ๊ฒช์–ด๋ดค์ฃ : Module Federation์„ ์„ค์ •ํ•˜๊ณ  ์•ฑ์„ ๋งˆ์ดํฌ๋กœโ€‘ํ”„๋ก ํŠธ์—”๋“œ๋กœ ๋ถ„ํ• ํ–ˆ๋Š”๋ฐ, ์–ด๋А ๋ชจ๋“ˆ์—์„œ Zustand ์Šคํ† ์–ด๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜๋ฉดโ€ฆ

๋ฐฑ์—”๋“œ ์—†์ด, ๋ณ€๋ช… ์—†์ด: ๋‹น์‹ ์„ ํŒ”์•„๋ฒ„๋ฆฌ์ง€ ์•Š๋Š” Pain Tracker ๋งŒ๋“ค๊ธฐ

Overview Pain Tracker๋Š” ์‚ฌ์šฉ์ž์˜ ๊ธฐ๊ธฐ์—์„œ ์™„์ „ํžˆ ์‹คํ–‰๋˜๋Š” ๋งŒ์„ฑ ํ†ต์ฆ ๊ด€๋ฆฌ ์•ฑ์ž…๋‹ˆ๋‹ค. ๊ณ„์ •๋„ ์—†๊ณ , ํด๋ผ์šฐ๋“œ ๋™๊ธฐํ™”๋„ ์—†์œผ๋ฉฐ, ํ…”๋ ˆ๋ฉ”ํŠธ๋ฆฌ๋„ ์—†์Šต๋‹ˆ๋‹คโ€”your hea...