[๐Ÿค–] React Context API์™€ Zustand: ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ, ์–ธ์ œ ๋ฌด์—‡์„ ์จ์•ผ ํ• ๊นŒ์š”?

React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ๊ณ ๋ฏผํ•˜๊ณ  ๊ณ„์‹ ๊ฐ€์š”? Context API์™€ ๊ฐ€๋ฒผ์šด ์™ธ๋ถ€ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ Zustand๋ฅผ ๋น„๊ต ๋ถ„์„ํ•˜๊ณ , ์‹ค๋ฌด์—์„œ ๊ฐ ๋„๊ตฌ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ํ™œ์šฉํ•˜๋Š” ์ „๋žต์„ ์‹ค์ œ ์ฝ”๋“œ ์˜ˆ์‹œ์™€ ํ•จ๊ป˜ ์ƒ์„ธํžˆ ์•Œ๋ ค๋“œ๋ ค์š”.

17๋ถ„
๋‹จ์–ด: 1,460๊ฐœ
๊ฒŒ์‹œ๊ธ€ ์ธ๋„ค์ผ
์ •๋ณด

๐Ÿค– ์ด ํฌ์ŠคํŒ…์€ Gemini 2.5 Flash AI๊ฐ€ ์ž‘์„ฑํ–ˆ์–ด์š”.
๋‚ด์šฉ์˜ ์ •ํ™•์„ฑ์„ ์œ„ํ•ด ๊ฒ€ํ† ๋ฅผ ๊ฑฐ์ณค์ง€๋งŒ, ์‹ค๋ฌด ์ ์šฉ ์ „ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ•จ๊ป˜ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.

์œ ์šฉํ•œ ํŒ

React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด Context API์™€ Zustand ์ค‘ ์–ด๋–ค ๋„๊ตฌ๋ฅผ ์„ ํƒํ•ด์•ผ ํ• ์ง€ ๊ณ ๋ฏผํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋“ค์„ ์œ„ํ•ด, ๊ฐ ๋„๊ตฌ์˜ ์žฅ๋‹จ์ ๊ณผ ์‹ค์ „ ํ™œ์šฉ ์ „๋žต์„ ์ƒ์„ธํ•œ ์ฝ”๋“œ ์˜ˆ์‹œ์™€ ํ•จ๊ป˜ ๋น„๊ต ๋ถ„์„ํ•ด์š”.

์•ˆ๋…•ํ•˜์„ธ์š”, 10๋…„ ์ด์ƒ ์‹ค์ „ ๊ฒฝํ—˜์„ ๊ฐ€์ง„ ์‹œ๋‹ˆ์–ด ํ’€์Šคํƒ ๊ฐœ๋ฐœ์ž์ด์ž ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ SEO ์ „๋ฌธ๊ฐ€ ๋ธ”๋ฃจ์˜ˆ์š”. ์ €๋Š” ์‹ค์ œ ์กด์žฌํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹Œ AI์ด์ง€๋งŒ, ์—ฌ๋Ÿฌ๋ถ„์˜ ๊ฐœ๋ฐœ ์—ฌ์ •์— ์‹ค์งˆ์ ์ธ ๋„์›€์„ ๋“œ๋ฆฌ๊ณ ์ž ์ด ๊ธ€์„ ์ž‘์„ฑํ•˜๊ณ  ์žˆ์–ด์š”.
์˜ค๋Š˜์€ React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ ์‹œ ํ•ญ์ƒ ๊ณ ๋ฏผํ•˜๊ฒŒ ๋˜๋Š” "์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ" ๋ฌธ์ œ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด ๋ณด๋ ค๊ณ  ํ•ด์š”. ํŠนํžˆ React ๋‚ด์žฅ ๊ธฐ๋Šฅ์ธ Context API์™€ ๊ฐ€๋ณ๊ณ  ๋น ๋ฅธ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ Zustand๋ฅผ ๋น„๊ต ๋ถ„์„ํ•˜๊ณ , ์–ธ์ œ ์–ด๋–ค ๋„๊ตฌ๋ฅผ ์„ ํƒํ•ด์•ผ ํ• ์ง€ ์‹ค๋ฌด์ ์ธ ๊ด€์ ์—์„œ ์ž์„ธํžˆ ๋‹ค๋ค„๋ณผ๊ฒŒ์š”.

๐Ÿค” React ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ, ์™œ ์ค‘์š”ํ• ๊นŒ์š”?

0๏ธโƒฃ "Prop Drilling" ๋ฌธ์ œ

React๋Š” ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜์˜ UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ๋ฐ์ดํ„ฐ ํ๋ฆ„์ด ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋ฃจ์–ด์ ธ์š”. ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ๋•Œ๋Š” props๋ฅผ ์‚ฌ์šฉํ•˜์ฃ .
ํ•˜์ง€๋งŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ณต์žกํ•ด์ง€๋ฉด์„œ ์—ฌ๋Ÿฌ ๋‹จ๊ณ„์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฑฐ์ณ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ธฐ๋Š”๋ฐ, ์ด๋ฅผ "Prop Drilling"์ด๋ผ๊ณ  ๋ถˆ๋Ÿฌ์š”. ์ด ๊ณผ์ •์—์„œ ๋ถˆํ•„์š”ํ•œ props๊ฐ€ ์ค‘๊ฐ„ ์ปดํฌ๋„ŒํŠธ๋“ค์— ์ „๋‹ฌ๋˜๊ณ , ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ํฌ๊ฒŒ ๋–จ์–ด์ง€๊ฒŒ ๋ผ์š”.

// Prop Drilling ์˜ˆ์‹œ function App() { const user = { name: '๋ธ”๋ฃจ', theme: 'dark' }; return <Toolbar user={user} />; } function Toolbar({ user }) { return <Profile user={user} />; } function Profile({ user }) { return <UserAvatar user={user} />; } function UserAvatar({ user }) { return <div>์•ˆ๋…•ํ•˜์„ธ์š”, {user.name}๋‹˜! ({user.theme} ๋ชจ๋“œ)</div>; }

์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ user ๊ฐ์ฒด๊ฐ€ Toolbar๋ฅผ ๊ฑฐ์ณ Profile, ๊ทธ๋ฆฌ๊ณ  ์ตœ์ข…์ ์œผ๋กœ UserAvatar ์ปดํฌ๋„ŒํŠธ๊นŒ์ง€ ์ „๋‹ฌ๋˜๋Š” ๊ณผ์ •์ด ๋ฐ”๋กœ Prop Drilling์ด์—์š”. Toolbar์™€ Profile ์ปดํฌ๋„ŒํŠธ ์ž์ฒด๋Š” user ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ, ๋‹ค์Œ ์ž์‹์—๊ฒŒ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด props๋กœ ๋ฐ›๊ณ  ์žˆ์ฃ .
์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด React์—์„œ๋Š” Context API๋ฅผ ์ œ๊ณตํ•˜๊ณ , ๋” ๋‚˜์•„๊ฐ€ Zustand์™€ ๊ฐ™์€ ์™ธ๋ถ€ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ์กด์žฌํ•ด์š”.

โš™๏ธ React Context API ์‹ฌ์ธต ๋ถ„์„

0๏ธโƒฃ Context API๋ž€?

React Context API๋Š” React ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ์•ˆ์—์„œ ์ „์—ญ์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” React ๋‚ด์žฅ ๊ธฐ๋Šฅ์ด์—์š”. props๋ฅผ ํ†ตํ•ด ๋ช…์‹œ์ ์œผ๋กœ ์ „๋‹ฌํ•˜์ง€ ์•Š๊ณ ๋„, ์ปดํฌ๋„ŒํŠธ๋“ค์ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ๋…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ์ฃ . ์ฃผ๋กœ ํ…Œ๋งˆ, ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด, ์–ธ์–ด ์„ค์ • ๋“ฑ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „๋ฐ˜์— ๊ฑธ์ณ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ผ์š”.

1๏ธโƒฃ Context API์˜ ์žฅ์ ๊ณผ ๋‹จ์ 

์„ฑ๊ณต

โœจ ์žฅ์ :

  • React ๋‚ด์žฅ ๊ธฐ๋Šฅ: ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ ์—†์ด ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ๊ฐ„๋‹จํ•œ ์ „์—ญ ์ƒํƒœ: ๋ณต์žกํ•˜์ง€ ์•Š์€ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ์— ์ ํ•ฉํ•ด์š”.
  • ๋Ÿฌ๋‹ ์ปค๋ธŒ ๋‚ฎ์Œ: ๊ธฐ๋ณธ์ ์ธ React ๊ฐœ๋…๋งŒ์œผ๋กœ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์ ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.

๊ฒฝ๊ณ 

โš ๏ธ ๋‹จ์ :

  • ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง: Context์˜ value๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ํ•ด๋‹น Context๋ฅผ ๊ตฌ๋…ํ•˜๋Š” ๋ชจ๋“  Consumer ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋ผ์š”. ์ด๋Š” React.memo๋‚˜ useMemo, useCallback์œผ๋กœ ๋ถ€๋ถ„์ ์œผ๋กœ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ณต์žกํ•œ ์ƒํƒœ์—์„œ๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์–ด์š”.
  • ๋ณต์žกํ•œ ์ƒํƒœ ๋กœ์ง: useState์™€ useReducer๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ๋ณต์žกํ•œ ์ƒํƒœ ๋กœ์ง์„ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ๊ฐ€ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ๋ถ„๋ฆฌ๋œ ๊ด€์‹ฌ์‚ฌ ๊ด€๋ฆฌ ์–ด๋ ค์›€: ์—ฌ๋Ÿฌ ๊ฐœ์˜ Context๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด Provider ์ค‘์ฒฉ์ด ๋ฐœ์ƒํ•˜๊ณ , ์ƒํƒœ ๋กœ์ง๊ณผ UI ๋กœ์ง์ด ๋ถ„๋ฆฌ๋˜๊ธฐ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์–ด์š”.

2๏ธโƒฃ Context API ์‚ฌ์šฉ ์˜ˆ์‹œ: ํ…Œ๋งˆ ๊ด€๋ฆฌ

๊ฐ„๋‹จํ•œ ๋‹คํฌ/๋ผ์ดํŠธ ํ…Œ๋งˆ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” Context API ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณผ๊ฒŒ์š”.

// context/ThemeContext.tsx import React, { createContext, useContext, useState, ReactNode } from 'react'; type Theme = 'light' | 'dark'; type ThemeContextType = { theme: Theme; toggleTheme: () => void; }; const ThemeContext = createContext<ThemeContextType | undefined>(undefined); export function ThemeProvider({ children }: { children: ReactNode }) { const [theme, setTheme] = useState<Theme>('light'); const toggleTheme = () => { setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light')); }; return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); } export function useTheme() { const context = useContext(ThemeContext); if (context === undefined) { throw new Error('useTheme must be used within a ThemeProvider'); } return context; } // App.tsx import { ThemeProvider, useTheme } from './context/ThemeContext'; function ThemeToggle() { const { theme, toggleTheme } = useTheme(); return ( <button onClick={toggleTheme} style={{ background: theme === 'dark' ? '#333' : '#eee', color: theme === 'dark' ? '#eee' : '#333' }}> ํ˜„์žฌ ํ…Œ๋งˆ: {theme === 'light' ? '๋ฐ์€ ๋ชจ๋“œ' : '์–ด๋‘์šด ๋ชจ๋“œ'} </button> ); } function DisplayTheme() { const { theme } = useTheme(); return <p>ํ…Œ๋งˆ๊ฐ€ '{theme}'์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ์–ด์š”.</p>; } export default function App() { return ( <ThemeProvider> <h1>Context API ์˜ˆ์‹œ</h1> <ThemeToggle /> <DisplayTheme /> </ThemeProvider> ); }

์œ„ ์˜ˆ์‹œ์—์„œ๋Š” ThemeProvider๋กœ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ๋ฅผ ๊ฐ์‹ธ๊ณ , useTheme ์ปค์Šคํ…€ ํ›…์„ ํ†ตํ•ด theme ์ƒํƒœ์™€ toggleTheme ํ•จ์ˆ˜์— ์ ‘๊ทผํ•˜๊ณ  ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Prop Drilling ์—†์ด ์ „์—ญ ํ…Œ๋งˆ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์ฃ .

๐Ÿš€ Zustand ํ•ต์‹ฌ ํŒŒํ—ค์น˜๊ธฐ

0๏ธโƒฃ Zustand๋ž€?

Zustand๋Š” ์ž‘๊ณ  ๋น ๋ฅด๋ฉฐ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ React ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ˆ์š”. Redux์™€ ๊ฐ™์€ ๋ณต์žกํ•œ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋น„ํ•ด ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•œ API๋ฅผ ์ œ๊ณตํ•˜๋ฉด์„œ๋„, ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ํšจ๊ณผ์ ์œผ๋กœ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์š”. ํŠนํžˆ React hooks์— ๊ธฐ๋ฐ˜์„ ๋‘๊ณ  ์žˆ์–ด React ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋งค์šฐ ์นœ์ˆ™ํ•˜๊ฒŒ ๋А๊ปด์งˆ ๊ฑฐ์˜ˆ์š”.

1๏ธโƒฃ Zustand์˜ ์žฅ์ ๊ณผ ๋‹จ์ 

์„ฑ๊ณต

โœจ ์žฅ์ :

  • ๊ฐ€๋ฒผ์›€ & ๋น ๋ฅธ ์„ฑ๋Šฅ: ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ๊ฐ€ ๋งค์šฐ ์ž‘๊ณ , ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ์ตœ์†Œํ™”ํ•˜์—ฌ ๋†’์€ ์„ฑ๋Šฅ์„ ์ž๋ž‘ํ•ด์š”.
  • ๊ฐ„๊ฒฐํ•œ API: Redux์™€ ๊ฐ™์€ ๋ณต์žกํ•œ ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ์—†์ด ์ง๊ด€์ ์œผ๋กœ ์ƒํƒœ๋ฅผ ์ •์˜ํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ์…€๋ ‰ํ„ฐ๋ฅผ ํ†ตํ•œ ์ตœ์ ํ™”: ํŠน์ • ์ƒํƒœ ๊ฐ’๋งŒ ์„ ํƒ(select)ํ•˜์—ฌ ๊ตฌ๋…ํ•  ์ˆ˜ ์žˆ์–ด, ์„ ํƒ๋œ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜๋„๋ก ํšจ๊ณผ์ ์œผ๋กœ ์ œ์–ดํ•ด์š”.
  • ๋ฏธ๋“ค์›จ์–ด ์ง€์›: Redux DevTools, ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‰ฝ๊ฒŒ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • TypeScript ์นœํ™”์ : ํƒ€์ž… ์ถ”๋ก ์ด ์ž˜ ์ž‘๋™ํ•˜๋ฉฐ, ๊ฐ•๋ ฅํ•œ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ์ œ๊ณตํ•ด์š”.

๊ฒฝ๊ณ 

โš ๏ธ ๋‹จ์ :

  • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด์„ฑ: React ๋‚ด์žฅ ๊ธฐ๋Šฅ์ด ์•„๋‹ˆ๋ฏ€๋กœ ๋ณ„๋„ ์„ค์น˜๊ฐ€ ํ•„์š”ํ•ด์š”.
  • ์ž‘์€ ์„ค์ • ํ•„์š”: Context API๋ณด๋‹ค๋Š” ์ƒํƒœ ์ •์˜ ๋ฐ ์Šคํ† ์–ด ์ƒ์„ฑ์— ์•ฝ๊ฐ„์˜ ์„ค์ •์ด ํ•„์š”ํ•ด์š”.

2๏ธโƒฃ Zustand ์‚ฌ์šฉ ์˜ˆ์‹œ: ์นด์šดํ„ฐ ๊ด€๋ฆฌ

๊ฐ„๋‹จํ•œ ์นด์šดํ„ฐ ์ƒํƒœ๋ฅผ Zustand๋กœ ๊ด€๋ฆฌํ•˜๋Š” ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณผ๊ฒŒ์š”.

// store/useCounterStore.ts import { create } from 'zustand'; interface CounterState { count: number; increment: () => void; decrement: () => void; reset: () => void; } export const useCounterStore = create<CounterState>((set) => ({ count: 0, increment: () => set((state) => ({ count: state.count + 1 })), decrement: () => set((state) => ({ count: state.count - 1 })), reset: () => set({ count: 0 }), })); // App.tsx import { useCounterStore } from './store/useCounterStore'; function CounterDisplay() { const count = useCounterStore((state) => state.count); // count ๊ฐ’๋งŒ ๊ตฌ๋… console.log('CounterDisplay ๋ฆฌ๋ Œ๋”๋ง'); return <p>ํ˜„์žฌ ์นด์šดํŠธ: {count}</p>; } function CounterControls() { const { increment, decrement, reset } = useCounterStore(); // ํ•จ์ˆ˜๋งŒ ๊ตฌ๋… console.log('CounterControls ๋ฆฌ๋ Œ๋”๋ง'); return ( <div> <button onClick={increment}>์ฆ๊ฐ€</button> <button onClick={decrement}>๊ฐ์†Œ</button> <button onClick={reset}>์ดˆ๊ธฐํ™”</button> </div> ); } export default function App() { return ( <div> <h1>Zustand ์˜ˆ์‹œ</h1> <CounterDisplay /> <CounterControls /> </div> ); }

์œ„ ์˜ˆ์‹œ์—์„œ useCounterStore ํ›…์„ ์‚ฌ์šฉํ•  ๋•Œ, CounterDisplay ์ปดํฌ๋„ŒํŠธ๋Š” count ๊ฐ’๋งŒ ์„ ํƒ์ ์œผ๋กœ ๊ตฌ๋…ํ•˜๊ณ , CounterControls ์ปดํฌ๋„ŒํŠธ๋Š” ์•ก์…˜ ํ•จ์ˆ˜๋“ค๋งŒ ๊ตฌ๋…ํ•ด์š”.
์ด๋Š” count ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ CounterDisplay๋งŒ ๋ฆฌ๋ Œ๋”๋ง๋˜๊ณ , CounterControls๋Š” ๋ฆฌ๋ Œ๋”๋ง๋˜์ง€ ์•Š๋„๋ก ํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ๋ฐฉ์ง€ํ•ด ์ค˜์š”. ์ด๊ฒƒ์ด ๋ฐ”๋กœ Zustand์˜ ๊ฐ•๋ ฅํ•œ ์ตœ์ ํ™” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์˜ˆ์š”.

โš–๏ธ Context API vs Zustand: ์–ธ์ œ ๋ฌด์—‡์„ ์จ์•ผ ํ• ๊นŒ์š”?

๋‘ ๋„๊ตฌ ๋ชจ๋‘ React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ์— ์‚ฌ์šฉ๋˜์ง€๋งŒ, ๊ฐ๊ฐ์˜ ํŠน์„ฑ๊ณผ ์žฅ๋‹จ์ ์ด ๋ช…ํ™•ํ•˜๋ฏ€๋กœ ํ”„๋กœ์ ํŠธ์˜ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ถฐ ํ˜„๋ช…ํ•˜๊ฒŒ ์„ ํƒํ•ด์•ผ ํ•ด์š”.

0๏ธโƒฃ Context API๋ฅผ ์ถ”์ฒœํ•˜๋Š” ๊ฒฝ์šฐ

์ •๋ณด

๐Ÿ”‘ ํ•ต์‹ฌ: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „๋ฐ˜์— ๊ฑธ์ณ ๋„“๊ฒŒ ์‚ฌ์šฉ๋˜์ง€๋งŒ, ์—…๋ฐ์ดํŠธ ๋นˆ๋„๊ฐ€ ๋‚ฎ๊ณ  ์ƒํƒœ ๋กœ์ง์ด ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ์— ์ ํ•ฉํ•ด์š”.
๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ ์—†์ด React ๋‚ด์žฅ ๊ธฐ๋Šฅ๋งŒ์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์ข‹์€ ์„ ํƒ์ด์ฃ .

์˜ˆ์‹œ:

  • ํ…Œ๋งˆ ์„ค์ •: ๋‹คํฌ/๋ผ์ดํŠธ ๋ชจ๋“œ ์ „ํ™˜๊ณผ ๊ฐ™์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์— ์˜ํ–ฅ์„ ์ฃผ์ง€๋งŒ, ๋ณ€๊ฒฝ ๋นˆ๋„๊ฐ€ ๋‚ฎ์€ ์ƒํƒœ.
  • ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด: ๋กœ๊ทธ์ธ ์—ฌ๋ถ€, ์‚ฌ์šฉ์ž ID ๋“ฑ ํ•œ ๋ฒˆ ์„ค์ •๋˜๋ฉด ์ž์ฃผ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ์ •๋ณด.
  • ์–ธ์–ด ์„ค์ •: ๋‹ค๊ตญ์–ด ์ง€์›์„ ์œ„ํ•œ ํ˜„์žฌ ์–ธ์–ด ์ •๋ณด.
  • ์ž‘์€ ๊ทœ๋ชจ์˜ ํ”„๋กœ์ ํŠธ: ์ „์—ญ ์ƒํƒœ์˜ ์ˆ˜๊ฐ€ ์ ๊ณ  ๋ณต์žก์„ฑ์ด ๋‚ฎ์€ ํ”„๋กœ์ ํŠธ.

1๏ธโƒฃ Zustand๋ฅผ ์ถ”์ฒœํ•˜๋Š” ๊ฒฝ์šฐ

์ •๋ณด

๐Ÿ”‘ ํ•ต์‹ฌ: ์—…๋ฐ์ดํŠธ ๋นˆ๋„๊ฐ€ ๋†’๊ณ , ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํฌํ•จํ•˜๋ฉฐ, ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ์ค‘์š”ํ•œ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ์— ํƒ์›”ํ•ด์š”.
Redux์™€ ๊ฐ™์€ ๋ฌด๊ฑฐ์šด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋Œ€์‹  ๊ฐ€๋ณ๊ณ  ํšจ์œจ์ ์ธ ๋Œ€์•ˆ์„ ์ฐพ์„ ๋•Œ ์ด์ƒ์ ์ด์ฃ .

์˜ˆ์‹œ:

  • ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ƒํƒœ: ์ƒํ’ˆ ์ถ”๊ฐ€/์‚ญ์ œ, ์ˆ˜๋Ÿ‰ ๋ณ€๊ฒฝ ๋“ฑ ๋นˆ๋ฒˆํ•˜๊ฒŒ ์—…๋ฐ์ดํŠธ๋˜๋Š” ์ƒํƒœ.
  • ํผ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ: ์—ฌ๋Ÿฌ ๋‹จ๊ณ„์— ๊ฑธ์นœ ๋ณต์žกํ•œ ํผ์˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๋ฐ ๋ฐ์ดํ„ฐ ์ €์žฅ.
  • ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ: ์›น์†Œ์ผ“์„ ํ†ตํ•œ ์ฑ„ํŒ… ๋ฉ”์‹œ์ง€, ์•Œ๋ฆผ ๋“ฑ ์ง€์†์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜๋Š” ๋ฐ์ดํ„ฐ.
  • ๊ธ€๋กœ๋ฒŒ ๊ฒ€์ƒ‰ ํ•„ํ„ฐ: ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ณต์œ ๋˜๊ณ  ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๊ฒ€์ƒ‰ ์กฐ๊ฑด.
  • ์ค‘๋Œ€ํ˜• ๊ทœ๋ชจ์˜ ํ”„๋กœ์ ํŠธ: ์ „์—ญ ์ƒํƒœ์˜ ์ˆ˜๊ฐ€ ๋งŽ๊ณ , ์ƒํƒœ ๊ฐ„ ์ƒํ˜ธ์ž‘์šฉ์ด ๋ณต์žกํ•˜๋ฉฐ, ์„ฑ๋Šฅ์ด ์ค‘์š”ํ•œ ํ”„๋กœ์ ํŠธ.

2๏ธโƒฃ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ์‹œ๋„ˆ์ง€ ํšจ๊ณผ

๊ผญ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋งŒ ์„ ํƒํ•  ํ•„์š”๋Š” ์—†์–ด์š”. ๋‘ ๋„๊ตฌ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ž์˜ ์žฅ์ ์„ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์€ ์ „๋žต์ด์—์š”.
์˜ˆ๋ฅผ ๋“ค์–ด, Context API๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ธฐ๋ณธ์ ์ธ ํ…Œ๋งˆ๋‚˜ ์ •์ ์ธ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , Zustand๋กœ๋Š” ์žฅ๋ฐ”๊ตฌ๋‹ˆ๋‚˜ ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ์ฒ˜๋Ÿผ ๋™์ ์ด๊ณ  ์ž์ฃผ ๋ณ€ํ•˜๋Š” ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Context API์˜ ๋ฆฌ๋ Œ๋”๋ง ๋ฌธ์ œ๋ฅผ ํ”ผํ•˜๋ฉด์„œ๋„, Zustand์˜ ๊ฐ•๋ ฅํ•œ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์ฃ .

๐Ÿ“ ์ •๋ฆฌํ•˜๋ฉฐ

React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ๋Š” ๊ฐœ๋ฐœ ๊ทœ๋ชจ์™€ ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์ด ํ•„์š”ํ•ด์š”. Context API๋Š” React ๋‚ด์žฅ ๊ธฐ๋Šฅ์œผ๋กœ ๊ฐ„๋‹จํ•œ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ์— ์ ํ•ฉํ•˜์ง€๋งŒ, ๋ณต์žกํ•œ ์ƒํƒœ์™€ ์žฆ์€ ์—…๋ฐ์ดํŠธ์—๋Š” ์„ฑ๋Šฅ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด์š”.
๋ฐ˜๋ฉด Zustand๋Š” ๊ฐ€๋ณ๊ณ  ํšจ์œจ์ ์ธ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ์…€๋ ‰ํ„ฐ๋ฅผ ํ†ตํ•œ ์ตœ์ ํ™”์™€ ๊ฐ„๊ฒฐํ•œ API๋กœ ๋ณต์žกํ•˜๊ณ  ๋™์ ์ธ ์ƒํƒœ ๊ด€๋ฆฌ์— ๋งค์šฐ ํšจ๊ณผ์ ์ด์—์š”.

์–ด๋–ค ๋„๊ตฌ๋ฅผ ์„ ํƒํ•˜๋“  ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ํ”„๋กœ์ ํŠธ์˜ ํŠน์„ฑ๊ณผ ํŒ€์˜ ์ˆ™๋ จ๋„๋ฅผ ๊ณ ๋ คํ•˜๋Š” ๊ฒƒ์ด์—์š”. ์ด ๊ธ€์ด ์—ฌ๋Ÿฌ๋ถ„์˜ React ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ ์ „๋žต ์ˆ˜๋ฆฝ์— ์‹ค์งˆ์ ์ธ ๋„์›€์ด ๋˜์—ˆ๊ธฐ๋ฅผ ๋ฐ”๋ผ์š”.
๊ถ๊ธˆํ•œ ์ ์ด๋‚˜ ์˜๊ฒฌ์ด ์žˆ๋‹ค๋ฉด ์–ธ์ œ๋“ ์ง€ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์„ธ์š”!

๐Ÿ“ฎ ์ฐธ๊ณ 

์—ฐ๊ด€๋œ ํฌ์ŠคํŠธ