06. ๐Ÿง  ์ƒํƒœ ๊ด€๋ฆฌ ๋„๊ตฌ์˜ ์ฒ ํ•™๊ณผ ์ตœ์ ํ™” ์ „๋žต

2026๋…„ 3์›” 5์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

Context API๋ถ€ํ„ฐ Zustand, Jotai๊นŒ์ง€, ๋‹ค์–‘ํ•œ ์ƒํƒœ ๊ด€๋ฆฌ ๋„๊ตฌ์˜ ์ฒ ํ•™์„ ์ดํ•ดํ•˜๊ณ  ์ƒํ™ฉ์— ๋งž๋Š” ์ตœ์ ์˜ ์ „๋žต์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“Œ ์ด ๋ฉด์ ‘ ํ•ญ๋ชฉ์˜ ๋ชฉํ‘œ

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 23๋ถ„ (ํ•ต์‹ฌ ์š”์•ฝ: 11๋ถ„)

๐Ÿ—บ๏ธ ์ด ์ฑ•ํ„ฐ์˜ ํ๋ฆ„
[๊ฐœ๋… ์‚ฌ์ „] โ†’ [์งˆ๋ฌธ 1: Context API vs ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ] โ†’ [์งˆ๋ฌธ 2: Flux ์•„ํ‚คํ…์ฒ˜] โ†’ [์‹ค์ „ ๋ณ€ํ˜• ์งˆ๋ฌธ]

๐ŸŽฏ ์ด ์ฑ•ํ„ฐ๋ฅผ ๋‹ค ์ฝ์œผ๋ฉด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

  • Context API์˜ ์„ฑ๋Šฅ ํ•œ๊ณ„์™€ ์ „์—ญ ์ƒํƒœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋„์ž… ์‹œ์ ์„ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.
  • Zustand(Flux)์™€ Jotai(Atomic)์˜ ํŒจ๋Ÿฌ๋‹ค์ž„ ์ฐจ์ด๋ฅผ ๊ธฐ์ˆ ์ ์œผ๋กœ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.
  • ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๋Š” 'Selector' ์ตœ์ ํ™” ์›๋ฆฌ๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“š ํ•ต์‹ฌ ๊ฐœ๋… ์‚ฌ์ „ (Concept Glossary)

1. Props Drilling

์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ์ƒ๋‹จ์—์„œ ํ•˜๋‹จ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด, ์ค‘๊ฐ„ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์‚ฌ์šฉํ•˜์ง€๋„ ์•Š๋Š” Props๋ฅผ ๋‹จ์ˆœํžˆ ์ „๋‹ฌ๋งŒ ํ•˜๋Š” ํ˜„์ƒ์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํฌ๊ฒŒ ํ•ด์นฉ๋‹ˆ๋‹ค.

2. Flux ์•„ํ‚คํ…์ฒ˜

๋ฐ์ดํ„ฐ๊ฐ€ ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ํ๋ฅด๋„๋ก ๊ฐ•์ œํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด์ž…๋‹ˆ๋‹ค. Action โ†’ Dispatcher โ†’ Store โ†’ View ์ˆœ์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ํ๋ฅด๋ฉฐ, ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. (Redux, Zustand์˜ ๊ทผ๊ฐ„)

3. ์›์ž์  ์ƒํƒœ (Atomic State)

๊ฑฐ๋Œ€ํ•œ ํ•˜๋‚˜์˜ ์ƒ์ (Store) ๋Œ€์‹ , ์ž‘์€ ๋‹จ์œ„์˜ ์ƒํƒœ(Atom)๋“ค์„ ๋…๋ฆฝ์ ์œผ๋กœ ์ •์˜ํ•˜๊ณ  ์กฐํ•ฉํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๋งŒ ํ•ด๋‹น Atom์„ ๊ตฌ๋…ํ•˜๋ฏ€๋กœ ๋ฆฌ๋ Œ๋”๋ง ์ตœ์ ํ™”์— ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. (Jotai, Recoil)


๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ๋ฐฐ๊ฒฝ ์„ธ๊ณ„๊ด€: '์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ'

  • ๐Ÿฃ ์˜์ฒ  ( ์‹ ์ž… ): "์˜ํ˜ธ ๋‹˜! '์˜์ˆ˜๋„ค ํ…Œ๋งˆ ์„ค์ •' ํ•˜๋‚˜ ๋ฐ”๊พธ๋Š”๋ฐ ์ „์ฒด ํŽ˜์ด์ง€๊ฐ€ ๋‹ค ๋ฆฌ๋ Œ๋”๋ง๋ผ์š”. Context API ์ตœ๊ณ ๋ผ๋ฉด์„œ์š”! ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์•ˆ ์จ๋„ ๋œ๋‹ค๋ฉด์„œ์š”! ๐Ÿ˜ญ"
  • ๐Ÿฆ ์˜ํ˜ธ ( ๋ฆฌ๋“œ ): "์˜์ฒ  ๋‹˜, Context API๋Š” '์ƒํƒœ ๊ด€๋ฆฌ' ๋„๊ตฌ๊ฐ€ ์•„๋‹ˆ๋ผ '์˜์กด์„ฑ ์ฃผ์ž…' ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ „์—ญ์ ์œผ๋กœ ๊ฐ’์„ ๊ณต์œ ํ•˜๋Š” ๋ฐ๋Š” ์ข‹์ง€๋งŒ, ๋นˆ๋ฒˆํ•˜๊ฒŒ ๋ฐ”๋€Œ๋Š” ๋ฐ์ดํ„ฐ์—๋Š” ์ฅ์•ฝ์ด์ฃ . ๋„๊ตฌ์˜ ์ด๋ฆ„๋ณด๋‹ค ๊ทธ ๋„๊ตฌ๊ฐ€ ํ•ด๊ฒฐํ•˜๋ ค๋Š” '์ง„์งœ ๋ฌธ์ œ'๋ฅผ ๋ณด์„ธ์š”."

Q1. Context API์™€ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(Zustand, Jotai ๋“ฑ)์˜ ๊ทผ๋ณธ์ ์ธ ์ฐจ์ด๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

๐ŸŽฏ ์ถœ์ œ ์˜๋„

Context API๊ฐ€ ๋งŒ๋Šฅ์ด ์•„๋‹˜์„ ์ธ์ง€ํ•˜๊ณ  ์žˆ๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ๋Œ€๊ทœ๋ชจ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฆฌ๋ Œ๋”๋ง ์„ฑ๋Šฅ ์„ฑ๋Šฅ ์ตœ์ ํ™” ์ „๋žต์„ ์ดํ•ดํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ ์ด์˜ Naive ๊ตฌํ˜„ (Bad Case)

์˜์ฒ ์ด๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์˜ ๊ฑฐ๋Œ€ํ•œ Context์— ๋ชฐ์•„๋„ฃ์—ˆ์Šต๋‹ˆ๋‹ค.

// ๐Ÿฃ ์˜์ฒ : "Context ํ•˜๋‚˜๋งŒ ์žˆ์œผ๋ฉด ์–ด๋””์„œ๋“  ๊บผ๋‚ด ์“ธ ์ˆ˜ ์žˆ์œผ๋‹ˆ ํŽธํ•ด์š”!"
const AppContext = createContext();
 
function AppProvider({ children }) {
  const [user, setUser] = useState(null);
  const [theme, setTheme] = useState('light');
  const [posts, setPosts] = useState([]); // โš ๏ธ ์—ฐ๊ด€ ์—†๋Š” ๋ฐ์ดํ„ฐ๋“ค์ด ํ•˜๋‚˜์— ๋ฌถ์ž„
 
  return (
    <AppContext.Provider value={{ user, theme, posts }}>
      {children}
    </AppContext.Provider>
  );
}
 
// โš ๏ธ ๋ฒ„๊ทธ: user ์ •๋ณด๋งŒ ๋ฐ”๋€Œ์–ด๋„ posts๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๊นŒ์ง€ ๋ชจ๋‘ ๋ฆฌ๋ Œ๋”๋ง๋จ

๐Ÿฆ ์˜ํ˜ธ์˜ ํŒฉํญ ์กฐ์–ธ
"์˜์ฒ  ๋‹˜, Context๋Š” ๊ฐ’์„ ๋ฐฐ๋‹ฌํ•ด ์ฃผ๋Š” 'ํƒ๋ฐฐ ๊ธฐ์‚ฌ'์ผ ๋ฟ์ด์—์š”. ์ƒ์ž๊ฐ€ ํ•˜๋‚˜๋ฉด, ์•ˆ์— ์žˆ๋Š” ๋ฌผ๊ฑด ์ค‘ ํ•˜๋‚˜๋งŒ ๋ฐ”๋€Œ์–ด๋„ ์ƒ์ž ์ „์ฒด๋ฅผ ๋‹ค์‹œ ๋ฐฐ๋‹ฌํ•ด์•ผ ํ•˜์ฃ . ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์€ ์ด '์ƒ์ž'๋ฅผ ์ž˜๊ฒŒ ์ชผ๊ฐœ๊ฑฐ๋‚˜, ํ•„์š”ํ•œ ๋ฌผ๊ฑด๋งŒ ์™ ๊ณจ๋ผ๋‚ด๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค."

๐Ÿฆ ์˜ํ˜ธ์˜ ์•„ํ‚คํ…์ฒ˜ ๊ฐ€์ด๋“œ (Good Case)

์˜ํ˜ธ ๋ฆฌ๋“œ๊ฐ€ Zustand๋ฅผ ํ™œ์šฉํ•ด ๊ด€์‹ฌ์‚ฌ๋ณ„๋กœ ์Šคํ† ์–ด๋ฅผ ๋ถ„๋ฆฌํ•˜๊ณ  ์ตœ์ ํ™”ํ•˜๋Š” ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

// ๐Ÿฆ ์˜ํ˜ธ: "๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•˜๊ณ , ํ•„์š”ํ•œ ์ƒํƒœ๋งŒ ๊ตฌ๋…(Subscribe)ํ•˜์„ธ์š”."
 
// Zustand: Flux ํŒจํ„ด ๊ธฐ๋ฐ˜์˜ ๊ฐ€๋ฒผ์šด ์Šคํ† ์–ด
const useThemeStore = create((set) => ({
  theme: 'light',
  toggleTheme: () => set((state) => ({ theme: state.theme === 'light' ? 'dark' : 'light' })),
}));
 
function ThemeButton() {
  // โœ… Selector๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ theme๋งŒ ๊ตฌ๋…. ๋‹ค๋ฅธ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ์–ด๋„ ์—ฌ๊ธฐ๋Š” ์•ˆ์ „ํ•จ!
  const theme = useThemeStore((state) => state.theme);
  const toggleTheme = useThemeStore((state) => state.toggleTheme);
 
  return <button onClick={toggleTheme}>{theme} ๋ชจ๋“œ</button>;
}

๐Ÿ“Š ๋ ˆ๋ฒจ๋ณ„ ๋‹ต๋ณ€ ๊ฐ€์ด๋“œ (Self-Check)

  • Level 1 (Junior): "Context API๋Š” ๋ฆฌ์•กํŠธ ๋‚ด์žฅ ๊ธฐ๋Šฅ์ด๊ณ , ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ถ”๊ฐ€ ์„ค์น˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. Context๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์•„์ง€๋ฉด ์„ฑ๋Šฅ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."
  • Level 2 (Senior): "Context API๋Š” '์ƒํƒœ ์ „ํŒŒ'๋ฅผ ๋‹ด๋‹นํ•˜๋ฉฐ, ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์˜ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด useMemo๋‚˜ Context ์ชผ๊ฐœ๊ธฐ(Splitting)๊ฐ€ ํ•„์š”ํ•จ์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ ์ƒํƒœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” '๋ฐœํ–‰-๊ตฌ๋…(Pub-Sub)' ๋ชจ๋ธ์„ ํ†ตํ•ด ๋ฆฌ์•กํŠธ ๋ฐ–์—์„œ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉฐ ์ตœ์ ํ™”๋œ ๋ฆฌ๋ Œ๋”๋ง์„ ์ œ๊ณตํ•จ์„ ์–ธ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค."
  • Level 3 (Specialist): "๋™์‹œ์„ฑ ๋ชจ๋“œ(Concurrent Mode)์—์„œ์˜ 'Tearing' ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด useSyncExternalStore๋ฅผ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๋Š”์ง€ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ Zustand์˜ ๊ฐ€๋ฒผ์šด ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ์™€ Jotai์˜ Bottom-up ๋ฐฉ์‹์ด ์‹ค์ œ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ ์•„ํ‚คํ…์ฒ˜์—์„œ ์–ด๋–ค ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ๊ฐ–๋Š”์ง€ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค."

Q2. Flux ์•„ํ‚คํ…์ฒ˜์˜ ํ•ต์‹ฌ ์›๋ฆฌ์™€, ์™œ ๋ฆฌ์•กํŠธ ์ƒํƒœ๊ณ„์—์„œ ์ด ํŒจํ„ด์ด ์ฃผ๋ฅ˜๊ฐ€ ๋˜์—ˆ๋Š”์ง€ ์„ค๋ช…ํ•ด ๋ณด์„ธ์š”.

๐ŸŽฏ ์ถœ์ œ ์˜๋„

๋ฐ์ดํ„ฐ ํ๋ฆ„์˜ ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ(Predictability)์ด ๋Œ€๊ทœ๋ชจ ์•ฑ์—์„œ ์™œ ์ค‘์š”ํ•œ์ง€, ๊ทธ๋ฆฌ๊ณ  ๋ณต์žกํ•œ ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋ฅผ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•œ ์„ค๊ณ„ ๋Šฅ๋ ฅ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ ์ด์˜ Naive ๊ตฌํ˜„ (Bad Case)

์˜์ฒ ์ด๋Š” ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ์„œ๋กœ์˜ ์ƒํƒœ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•˜๋Š” '์–‘๋ฐฉํ–ฅ ๋ฐ”์ธ๋”ฉ' ์ง€์˜ฅ์— ๋น ์กŒ์Šต๋‹ˆ๋‹ค.

// ๐Ÿฃ ์˜์ฒ : "A ์ปดํฌ๋„ŒํŠธ์—์„œ B ์ปดํฌ๋„ŒํŠธ ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•ด์„œ ์ƒํƒœ๋ฅผ ๋ฐ”๊ฟ€๊ฒŒ์š”!"
function ComponentA({ updateB }) {
  return <button onClick={() => updateB('์ƒˆ๋กœ์šด ๊ฐ’')}>B ๋ฐ”๊พธ๊ธฐ</button>;
}
 
// โš ๏ธ ๊ฒฐ๊ณผ: ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋””์„œ ์™œ ๋ฐ”๋€Œ์—ˆ๋Š”์ง€ ์ถ”์ ํ•˜๊ธฐ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•ด์ง (๋””๋ฒ„๊น… ์ง€์˜ฅ)

๐Ÿฆ ์˜ํ˜ธ์˜ ํŒฉํญ ์กฐ์–ธ
"์˜์ฒ  ๋‹˜, ๋ฐ์ดํ„ฐ๊ฐ€ ์ด๋ฆฌ์ €๋ฆฌ ํŠ€์–ด ๋‹ค๋‹ˆ๋ฉด ์•ฑ์ด ์ปค์กŒ์„ ๋•Œ ๋ฒ”์ธ์„ ์ฐพ์„ ์ˆ˜ ์—†์–ด์š”.Flux๋Š” '๋ฐ์ดํ„ฐ๋Š” ๋ฌด์กฐ๊ฑด ํ•œ ๊ธธ๋กœ๋งŒ ๊ฐ„๋‹ค'๋Š” ๊ทœ์น™์„ ์„ธ์›Œ ๋ฒ”์ฃ„(?)๋ฅผ ์˜ˆ๋ฐฉํ•ฉ๋‹ˆ๋‹ค."

๐Ÿฆ ์˜ํ˜ธ์˜ ์•„ํ‚คํ…์ฒ˜ ๊ฐ€์ด๋“œ (Good Case)

์˜ํ˜ธ ๋ฆฌ๋“œ๊ฐ€ ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„์˜ ์ •์„์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

// ๐Ÿฆ ์˜ํ˜ธ: "๋ชจ๋“  ๋ณ€ํ™”๋Š” 'Action'์ด๋ผ๋Š” ๊ธฐ๋ก์„ ๋‚จ๊ฒจ์•ผ ํ•ฉ๋‹ˆ๋‹ค."
 
// 1. Action: ์–ด๋–ค ๋ณ€ํ™”๊ฐ€ ์ผ์–ด๋‚ ์ง€ ์ •์˜ (์˜ˆ: { type: 'ADD_POST' })
// 2. Dispatcher/Reducer: Action์„ ๋ณด๊ณ  ์–ด๋–ป๊ฒŒ ์ƒํƒœ๋ฅผ ๋ฐ”๊ฟ€์ง€ ๊ฒฐ์ •
// 3. Store: ์œ ์ผํ•œ ์ง„์‹ค์˜ ์›์ฒœ (Single Source of Truth)
// 4. View: Store์˜ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ ํ™”๋ฉด ๊ฐฑ์‹ 
 
// Zustand/Redux ํŒจํ„ด
const usePostStore = create((set) => ({
  posts: [],
  // ๋ณ€ํ™”์˜ '์ด์œ '๋ฅผ ๋ช…ํ™•ํžˆ ํ•˜๋Š” ์•ก์…˜ ํ•จ์ˆ˜
  addPost: (newPost) => set((state) => ({ posts: [...state.posts, newPost] })),
}));

๐Ÿ“Š ๋ ˆ๋ฒจ๋ณ„ ๋‹ต๋ณ€ ๊ฐ€์ด๋“œ (Self-Check)

  • Level 1 (Junior): "Flux๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ํ๋ฅด๊ฒŒ ํ•˜๋Š” ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ์˜ˆ์ธกํ•˜๊ธฐ ์‰ฝ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค."
  • Level 2 (Senior): "MVC ํŒจํ„ด์˜ ๋ณต์žก์„ฑ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ–ˆ์Œ์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋กœ์ง์ด View์™€ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์–ด ํ…Œ์ŠคํŠธ๊ฐ€ ์‰ฝ๊ณ , ๋ชจ๋“  ์ƒํƒœ ๋ณ€ํ™”๊ฐ€ ์ˆœ์ˆ˜ ํ•จ์ˆ˜(Reducer)์™€ ์•ก์…˜ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์ผ์–ด๋‚˜๋ฏ€๋กœ ๋””๋ฒ„๊น…์ด ์šฉ์ดํ•จ์„ ๊ฐ•์กฐํ•ฉ๋‹ˆ๋‹ค."
  • Level 3 (Specialist): "Flux ํŒจํ„ด์˜ ๋‹จ์ ์ธ '๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ' ๋ฌธ์ œ๋ฅผ Zustand๊ฐ€ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ–ˆ๋Š”์ง€(Redux ๋Œ€๋น„ ๋‹จ์ˆœํ™”) ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ฏธ๋“ค์›จ์–ด(Middleware)๋ฅผ ํ†ตํ•ด ๋กœ๊น…, ์˜์†์„ฑ ์ €์žฅ(Persistence), ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๋“ฑ์„ ํŒŒ์ดํ”„๋ผ์ธ ํ˜•ํƒœ๋กœ ํ™•์žฅํ•˜๋Š” ๊ณ ๊ธ‰ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„ ๊ฒฝํ—˜์„ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค."

Q45. Props Drilling์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋‹จ๊ณ„๋ณ„ ์ „๋žต์€ ๋ฌด์—‡์ธ๊ฐ€์š”?

  • ๐ŸŽฏ ์ถœ์ œ ์˜๋„: ๋ฌด์กฐ๊ฑด ์ „์—ญ ์ƒํƒœ๋ฅผ ์“ฐ๊ธฐ๋ณด๋‹ค, ๋ฆฌ์•กํŠธ ๋‹ต๊ฒŒ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ํ•ฉ๋ฆฌ์ ์ธ ํŒ๋‹จ ๋Šฅ๋ ฅ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ๐Ÿ’ก ํ•ต์‹ฌ ์›๋ฆฌ & ๋‹ต๋ณ€: ์ฒซ ๋ฒˆ์งธ๋Š” **์ปดํฌ๋„ŒํŠธ ํ•ฉ์„ฑ(Component Composition)**์ž…๋‹ˆ๋‹ค. Props๋ฅผ ๋ฐ›๋Š” ์ž์‹ ๋Œ€์‹ , ์ž์‹์„ children์œผ๋กœ ๋„˜๊ฒจ ์ค‘๊ฐ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์กด์žฌ๋ฅผ ๋ชจ๋ฅด๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ๋Š” ์—ฐ๊ด€ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋ผ๋ฆฌ ๋ฌถ์–ด Context๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ง€์—ญ์  Context ํ™œ์šฉ์ž…๋‹ˆ๋‹ค. ์ „์—ญ ์ƒํƒœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ด ๋ชจ๋“  ๋ฐฉ๋ฒ•์œผ๋กœ๋„ ํ•ด๊ฒฐ์ด ์•ˆ ๋  ๋งŒํผ '์•ฑ ์ „์ฒด'์—์„œ ๊ณต์œ ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์ตœํ›„์˜ ์ˆ˜๋‹จ์œผ๋กœ ์„ ํƒํ•ด์•ผ ์ฝ”๋“œ์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Q52. Zustand์˜ Selector๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

  • ๐ŸŽฏ ์ถœ์ œ ์˜๋„: ๋ฆฌ๋ Œ๋”๋ง ์กฐ๊ฑด์ธ '์ฐธ์กฐ ๋™์ผ์„ฑ(Reference Identity)'์„ ๊นŠ์ด ์ดํ•ดํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ๐Ÿ’ก ํ•ต์‹ฌ ์›๋ฆฌ & ๋‹ต๋ณ€: state => ({ a: state.a, b: state.b }) ์ฒ˜๋Ÿผ ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋ฐ˜ํ™˜ํ•˜๋ฉด, ์‹ค์ œ ๊ฐ’์ด ๊ฐ™๋”๋ผ๋„ ์ฐธ์กฐ ์ฃผ์†Œ๊ฐ€ ๊ณ„์† ๋ฐ”๋€Œ์–ด ๋งค๋ฒˆ ๋ฆฌ๋ Œ๋”๋ง์ด ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด ๊ฐœ๋ณ„ ๊ฐ’์„ ์›์‹œ ํƒ€์ž…์œผ๋กœ ๋”ฐ๋กœ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜, Zustand์—์„œ ์ œ๊ณตํ•˜๋Š” shallow ๋น„๊ต ํ•จ์ˆ˜๋ฅผ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ ๋„˜๊ฒจ ๊ฐ์ฒด ๋‚ด๋ถ€์˜ '๊ฐ’'๋“ค์ด ๋ณ€ํ–ˆ์„ ๋•Œ๋งŒ ๋ฆฌ๋ Œ๋”๋ง๋˜๊ฒŒ ๊ฐ•์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Q60. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์“ฐ์ง€ ์•Š๊ณ  ๋ฆฌ์•กํŠธ๋งŒ์œผ๋กœ ์ƒํƒœ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•œ๋‹ค๋ฉด ์–ด๋–ค ๊ตฌ์กฐ๋ฅผ ์ œ์•ˆํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

  • ๐ŸŽฏ ์ถœ์ œ ์˜๋„: ๋„๊ตฌ์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ์ˆœ์ˆ˜ ๋ฆฌ์•กํŠธ ์„ค๊ณ„ ์—ญ๋Ÿ‰์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ๐Ÿ’ก ํ•ต์‹ฌ ์›๋ฆฌ & ๋‹ต๋ณ€: useReducer์™€ useContext๋ฅผ ์กฐํ•ฉํ•˜์—ฌ 'Mini Redux' ํ˜•ํƒœ์˜ ๊ตฌ์กฐ๋ฅผ ์ œ์•ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Action๊ณผ Reducer๋กœ ๋กœ์ง์„ ์ •ํ˜•ํ™”ํ•˜๊ณ , ์ด๋ฅผ Context๋ฅผ ํ†ตํ•ด ํ•˜์œ„๋กœ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ด๋•Œ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ํ…Œ๋งˆ ์ „์šฉ Context, ์œ ์ € ์ •๋ณด ์ „์šฉ Context ๋“ฑ์œผ๋กœ **Context๋ฅผ ์„ธ๋ถ„ํ™”(Splitting)**ํ•˜๊ณ , ํ•„์š”์‹œ ์ปดํฌ๋„ŒํŠธ๋ฅผ React.memo๋กœ ๊ฐ์‹ธ ๋ถˆํ•„์š”ํ•œ ์ „ํŒŒ๋ฅผ ๋ง‰๋Š” ์„ค๊ณ„๊ฐ€ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ ์ด์˜ ๋ณต๊ธฐ ์ผ๊ธฐ

์˜ค๋Š˜ 'Context๋Š” ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋‹ค'๋ผ๋Š” ์˜ํ˜ธ ๋‹˜์˜ ๋ง์”€์— ๋จธ๋ฆฌ๋ฅผ ํ•œ ๋Œ€ ๋งž์€ ๊ธฐ๋ถ„์ด๋‹ค. ๊ทธ๋™์•ˆ ๋‚˜๋Š” ์˜ˆ์œ ์ƒ์ž์— ์“ฐ๋ ˆ๊ธฐ(?)๋ฅผ ๊ฐ€๋“ ๋‹ด์•„ ํŽ˜์ด์ง€ ์ „์ฒด์— ๋ฟŒ๋ฆฌ๊ณ  ์žˆ์—ˆ๋‹ค. Zustand๋กœ ์Šคํ† ์–ด๋ฅผ ์ชผ๊ฐœ๊ณ  ๋‚˜๋‹ˆ ์ฝ”๋“œ๋Š” ๊ฐ„๊ฒฐํ•ด์ง€๊ณ , ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์˜ ๋ฆฌ๋ Œ๋”๋ง ํ•˜์ด๋ผ์ดํŠธ๊ฐ€ ์ž ์ž ํ•ด์ง€๋Š” ๊ฑธ ๋ณด๋‹ˆ ๋งˆ์Œ์ด ํ‰์˜จํ•ด์กŒ๋‹ค.

๐Ÿ’ก "์ƒํƒœ ๊ด€๋ฆฌ๋Š” ๋‹จ์ˆœํžˆ ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋ณ€ํ™”์˜ ๋ฒ”์œ„๋ฅผ ํ†ต์ œํ•˜๋Š” ์˜ˆ์ˆ ์ด๋‹ค."

๋‚ด์ผ์€ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ์‚ฌ์ด์˜ ๊ฐ€๊ต, 'Data Fetching๊ณผ ์„œ๋ฒ„ ์ƒํƒœ'๋ฅผ ๋ฐฐ์šธ ์ฐจ๋ก€๋‹ค. ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋Š” ๋˜ ์–ด๋–ค ๋ณต์žกํ•จ์œผ๋กœ ๋‚˜๋ฅผ ๊ดด๋กญํž์ง€ ๊ธฐ๋Œ€๋œ๋‹ค! ๐Ÿ“ก๐Ÿ’จ