Web Development/JAVASCRIPT

์ƒํƒœ๊ด€๋ฆฌ [3ํŽธ] - Zustand์˜ ์œ ์—ฐํ•จ์ด ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ ์–ด๋ ค์šด ์ด์œ 

devflate 2025. 3. 22. 12:55

๐ŸŒ€ Zustand๋Š” ์™œ Flux ์•„ํ‚คํ…์ฒ˜๊ฐ€ ์•„๋‹๊นŒ?

  • Action์ด๋ผ๋Š” ๊ฐœ๋…์ด ํ•„์ˆ˜ ์•„๋‹˜
  • Dispatcher๊ฐ€ ์—†์Œ
  • ์ƒํƒœ ๋ณ€๊ฒฝ ํ๋ฆ„์„ ์—„๊ฒฉํžˆ ์ œ์–ดํ•˜์ง€ ์•Š์Œ
  • set()์œผ๋กœ ์–ธ์ œ๋“ ์ง€ ์ƒํƒœ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

โš”๏ธ Zustand์˜ set() vs Redux์˜ dispatch()

๋น„์œ  Redux (dispatch) Zustand (set)
์—ญํ•  ๋น„์„œ์—๊ฒŒ ๋ฉ”๋ชจ ์ „๋‹ฌ ์ง์ ‘ ์ˆ˜์ฒฉ์— ์ž‘์„ฑ
์ œ์–ด ํ๋ฆ„ ๊ฐ„์ ‘์  (Action → Reducer) ์ง์ ‘ ์ƒํƒœ ๋ณ€๊ฒฝ
๋””๋ฒ„๊น… ์•ก์…˜ ๋กœ๊ทธ ์ถ”์  ๊ฐ€๋Šฅ ์ถ”์  ์–ด๋ ค์›€ (์ˆ˜๋™ ๋กœ๊น… ํ•„์š”)


๐Ÿšง Zustand๊ฐ€ ๋Œ€ํ˜• ํ”„๋กœ์ ํŠธ์—์„œ ์–ด๋ ค์šด ์ด์œ 

1. ์•„ํ‚คํ…์ฒ˜์™€ ๊ตฌ์กฐ ๊ฐ•์ œ๊ฐ€ ์—†๋‹ค

  • Redux๋Š” ๊ตฌ์กฐ ๊ฐ•์ œ → ํ˜‘์—…์— ์œ ๋ฆฌ
  • Zustand๋Š” ์ž์œ ๋กœ์šด ๋งŒํผ ์„ค๊ณ„ ์ผ๊ด€์„ฑ ๋ถ€์กฑ

2. ์ƒํƒœ ๋ณ€๊ฒฝ ์ถ”์  ์–ด๋ ค์›€

  • Redux: DevTool๋กœ ์ƒํƒœ/์•ก์…˜ ์ถ”์  ๊ฐ€๋Šฅ
  • Zustand: ์ˆ˜๋™ ๋กœ๊ทธ๋‚˜ ๋ฏธ๋“ค์›จ์–ด ํ•„์š”

3. ๋น„๋™๊ธฐ ํ๋ฆ„์ด ํ‘œ์ค€ํ™”๋˜์ง€ ์•Š์Œ

  • Redux: thunk, saga, RTK Query ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹ ์ œ๊ณต
  • Zustand: ๋ฏธ๋“ค์›จ์–ด ๊ธฐ๋Šฅ ์ œํ•œ์ , ์ปค์Šคํ…€ ์„ค๊ณ„ ํ•„์š”

4. ์ƒํƒœ ๋ถ„๋ฆฌ/๋ชจ๋“ˆํ™”์˜ ์–ด๋ ค์›€

Redux๋Š” slice๋กœ ๋„๋ฉ”์ธ ๋ถ„๋ฆฌ ๊ฐ€๋Šฅ, Zustand๋Š” ๋‹จ์ผ store ๋ฐฉ์‹ ๊ธฐ๋ณธ

5. ํ•œ๋ฒˆ์— ์—ฌ๋Ÿฌ Store๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๋ฐฉ์‹

Redux๋Š” extraReducers๋ฅผ ์‚ฌ์šฉํ•ด์„œ, ๊ฐ๊ฐ์˜ store ๋‚ด๋ถ€์˜ state๋ฅผ ํŽธํ•˜๊ฒŒ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

// Redux ์˜ˆ์‹œ
// userSlice.ts
extraReducers: (builder) => {
  builder.addCase('LOGOUT', () => ({ name: '', token: null }));
};

// postSlice.ts
extraReducers: (builder) => {
  builder.addCase('LOGOUT', () => ({ posts: [] }));
};

 

Zustand๋Š” Redux์ฒ˜๋Ÿผ ํ•œ๋ฒˆ์— ์—ฌ๋Ÿฌ store๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ํ•œ์ •์ ์ด๊ธฐ ๋•Œ๋ฌธ์—, ์™ธ๋ถ€ ๋กœ์ง ๋‚ด์— store ์กฐ์ž‘ ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ( => ์ฝ”๋“œ๊ฐ€ ๋ถ„์‚ฐ๋˜๊ธฐ ๋•Œ๋ฌธ์— Redux์— ๋น„ํ•ด ์ฝ”๋“œ๋ฅผ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ์–ด๋ ค์›€์ด ์žˆ๋‹ค.)

// ์ƒํƒœ์™€ set์„ ๊ฐ๊ฐ์˜ store๋กœ ๋ถ„๋ฆฌ
// stores/userStore.ts
export const useUserStore = create(set => ({
  user: null,
  setUser: (user) => set({ user }),
}));

// stores/settingsStore.ts
export const useSettingsStore = create(set => ({
  darkMode: false,
  setDarkMode: (val) => set({ darkMode: val }),
}));

// usecases/login.ts
export const login = async (email, pw) => {
  const res = await api.login(email, pw);
  useUserStore.getState().setUser(res.user);
  useSettingsStore.getState().setDarkMode(res.user.prefersDarkMode);
};

๐Ÿ‘‰ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด store๋Š” ์ƒํƒœ๋งŒ ๊ด€๋ฆฌํ•˜๊ณ , ๋ณต์žกํ•œ ํ๋ฆ„์€ ์™ธ๋ถ€ usecase์—์„œ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ!


โœ… ๊ฒฐ๋ก 

๊ตฌ๋ถ„ Redux Zustand
์ฒ ํ•™ ๊ตฌ์กฐํ™”๋œ ์ƒํƒœ ํ๋ฆ„ ์ž์œ ๋กญ๊ณ  ์œ ์—ฐํ•œ ์ƒํƒœ
์žฅ์  ๋””๋ฒ„๊น…, ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ์—†์Œ, ๋น ๋ฅธ ๊ฐœ๋ฐœ
๋‹จ์  ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•˜๊ณ  ๋งŽ์Œ ๊ตฌ์กฐ์  ํ†ต์ผ์„ฑ ๋ถ€์กฑ, ์ถ”์  ์–ด๋ ค์›€
์ถ”์ฒœ ๋Œ€๊ทœ๋ชจ ํ˜‘์—… ํ”„๋กœ์ ํŠธ ์ž‘์€ ๊ทœ๋ชจ, ๋น ๋ฅธ ๊ฐœ๋ฐœ