๐Ÿงฉ 04. Props Drilling์˜ ๋น„๊ทน๊ณผ State Colocation

๐Ÿ“‹ ๊ฐœ์š”

์ƒํƒœ๋ฅผ ๋ฌด์กฐ๊ฑด ์ตœ์ƒ์œ„(App)๋กœ ๋Œ์–ด์˜ฌ๋ฆด ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ Œ๋”๋ง ํญํƒ„์˜ ์›์ธ๊ณผ, ์ƒํƒœ๋ฅผ ์•Œ๋งž์€ ์œ„์น˜์— ๋ฐฐ์น˜(Colocation)ํ•˜๋Š” 5๋…„ ์ฐจ์˜ ์„ค๊ณ„๋ฒ•์„ ๋ฐฐ์›๋‹ˆ๋‹ค.

๐ŸŽฏ ์ด ์„น์…˜์„ ์ฝ๊ณ  ๋‚˜๋ฉด:

  • ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(Redux, Zustand)๋ฅผ ๋„์ž…ํ•˜๊ธฐ ์ „์— ์ปดํฌ๋„ŒํŠธ ์„ค๊ณ„๋ฅผ ๋จผ์ € ์˜์‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ƒํƒœ๋ฅผ ์ตœ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋Œ์–ด์˜ฌ๋ ธ์„ ๋•Œ(Lifting State Up) ๋ฐœ์ƒํ•˜๋Š” ๋ Œ๋”๋ง ํญํƒ„(์žฌ์•™)์„ ์ดํ•ดํ•œ๋‹ค.
  • ์ƒํƒœ๋ฅผ "๊ฐ€์žฅ ํ•„์š”๋กœ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์— ์ตœ๋Œ€ํ•œ ๊ฐ€๊น๊ฒŒ ๋ฐฐ์น˜(State Colocation)"ํ•˜๋Š” ํ•ต์‹ฌ ๊ธฐ์ค€์„ ํš๋“ํ•œ๋‹ค.

๐Ÿ“‹ ๋ชฉ์ฐจ


๐Ÿ“Œ ์ด ๋ฌธ์„œ๋ฅผ ์ฝ๊ธฐ ์ „์—

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 15๋ถ„ / ํ•ต์‹ฌ ํŒŒํŠธ: 8๋ถ„

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

  • ์˜์ฒ (์‹ ์ž…): "๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ์ œ์ผ ๋์— ์žˆ๋Š” ๋Œ“๊ธ€์˜ '์ข‹์•„์š”' ๋ฒ„ํŠผ์„ ์ƒˆ๋กœ ๋‹ฌ์•˜์–ด์š”! ์ด์ œ App.tsx์— likes ์ƒํƒœ๋ฅผ ๋‘๊ณ  ํ”„๋กญ์Šค๋กœ ๋„˜๊ธธ๊ฒŒ์š”."
  • ์˜ํ˜ธ(๋ฆฌ๋“œ): "์˜์ฒ  ๋‹˜... ๋Œ“๊ธ€ ํ•˜๋‚˜์˜ ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €๋Š”๋ฐ ์™œ ์ปค๋ฎค๋‹ˆํ‹ฐ ์ „์ฒด ์‚ฌ์ดํŠธ๊ฐ€ ๋ฒ„๋ฒ…๊ฑฐ๋ฆฌ๋ฉด์„œ ์ƒˆ๋กœ๊ณ ์นจ(๋ฆฌ๋ Œ๋”๋ง)๋˜๋Š” ๊ฑฐ์ฃ ?"

๐Ÿค” ์™œ ์•Œ์•„์•ผ ํ•˜๋Š”๊ฐ€: '๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ(Lifting)'์˜ ์ด๋ฉด

React ๊ณต์‹ ๋ฌธ์„œ์—์„œ๋Š” ๋‘ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ™์€ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•ด์•ผ ํ•  ๋•Œ "์ƒํƒœ๋ฅผ ๊ณตํ†ต ๋ถ€๋ชจ ์š”์†Œ๋กœ ๋Œ์–ด์˜ฌ๋ฆฌ์„ธ์š”(Lifting State Up)" ๋ผ๊ณ  ๊ฐ€๋ฅด์ณ. ์ด ์›์น™์€ ์•„์ฃผ ํ›Œ๋ฅญํ•˜์ง€๋งŒ, ์‹ ์ž… ๊ฐœ๋ฐœ์ž๋“ค์€ ์ข…์ข… ์ด ๋ง์„ ๊ณกํ•ดํ•ด์„œ ๋Œ€ํ˜• ์‚ฌ๊ณ ๋ฅผ ์น˜๊ณ  ๋ง์•„.

๐Ÿค” ์ž ๊น, ๋จผ์ € ์ƒ๊ฐํ•ด ๋ด
์•ฑ์—์„œ ์“ฐ์ด๋Š” ๋ชจ๋“  ์ƒํƒœ๋ฅผ ์ œ์ผ ๊ผญ๋Œ€๊ธฐ์ธ App ์ปดํฌ๋„ŒํŠธ ํ•˜๋‚˜์— ๋‹ค ๋ชฐ์•„๋„ฃ๊ณ  ์ž์‹๋“ค์—๊ฒŒ ๋‚˜๋ˆ ์ฃผ๋ฉด ๊ด€๋ฆฌ๊ฐ€ ํŽธํ•˜์ง€ ์•Š์„๊นŒ?

// โŒ ์˜์ฒ ์ด์˜ ํญํƒ„ ์„ค๊ณ„ (Naive Approach)
function App() {
  const [theme, setTheme] = useState('light');
  const [currentUser, setCurrentUser] = useState(null);
  
  // ๐Ÿ’ฃ ์ด ์•ฑ์˜ ์ˆ˜์ฒœ ๊ฐœ ๋Œ“๊ธ€ ์ค‘ "๋‹จ ํ•˜๋‚˜"์˜ ์ข‹์•„์š” ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ์“ฐ์ด๋Š” ์ƒํƒœ
  const [commentLikes, setCommentLikes] = useState({}); 
 
  const handleLike = (commentId) => {
    setCommentLikes(prev => ({ ...prev, [commentId]: prev[commentId] + 1 }));
  };
 
  return (
    <div className={`app ${theme}`}>
      <CommunityHeader user={currentUser} />
      <Sidebar />
      {/* ๐Ÿ’ฅ ํ”„๋กญ์Šค ๋“œ๋ฆด๋ง์˜ ์‹œ์ž‘ */}
      <Feed commentLikes={commentLikes} onLike={handleLike} />
    </div>
  );
}

์˜์ฒ ์ด์˜ ์ฝ”๋“œ๋Š” ๊ฒ‰๋ณด๊ธฐ์—” ์ž‘๋™ํ•ด. ํ•˜์ง€๋งŒ ์‚ฌ์šฉ์ž๊ฐ€ ํ”ผ๋“œ ๋งจ ์•„๋ž˜์— ์ˆจ๊ฒจ์ง„ ๋Œ“๊ธ€์˜ '์ข‹์•„์š”' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋Š” ์ˆœ๊ฐ„ ์•ฑ ์ „์ฒด์— ๋”์ฐํ•œ ์žฌ์•™์ด ์‹œ์ž‘๋ผ.


๐Ÿ—๏ธ ๋น„์œ ๋กœ ๋จผ์ € ์ดํ•ดํ•˜๊ธฐ

๐Ÿง’ 5์‚ด์—๊ฒŒ ์„ค๋ช…ํ•œ๋‹ค๋ฉด?
์šฐ๋ฆฌ ์ง‘์— ์•„๋น , ์•„๋“ค, ์†์ž๊ฐ€ ์‚ด๊ณ  ์žˆ์–ด.
์†์ž๊ฐ€ ์ž๊ธฐ ์žฅ๋‚œ๊ฐ ๋กœ๋ด‡์˜ ์ƒ‰๊น”์„ ํŒŒ๋ž€์ƒ‰์—์„œ ๋นจ๊ฐ„์ƒ‰์œผ๋กœ ์น ํ–ˆ์–ด.
์ด ์‚ฌ์‹ค์„ ์ง‘์•ˆ์˜ ์ตœ๊ณ  ๋Œ€์žฅ(์•„๋น ) ์—๊ฒŒ ๋ณด๊ณ (App์— ์ƒํƒœ ๋‘๊ธฐ)ํ–ˆ์ง€.
๊ทธ๋Ÿฌ์ž ์•„๋น ๋Š” ํ™•์„ฑ๊ธฐ๋ฅผ ๋“ค๊ณ  ์˜จ ์ง‘์•ˆ์— ์†Œ๋ฆฌ์ณค์–ด!
"๋น„์ƒ! ์šฐ๋ฆฌ ์ง‘ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค! ์˜จ ๊ฐ€์กฑ ๊ตฌ์„ฑ์›์€ ํ•˜๋˜ ์ผ์„ ๋ฉˆ์ถ”๊ณ  ๊ฐ์ž์˜ ๋ฐฉ์„ ์‹น ๋‹ค ์ธํ…Œ๋ฆฌ์–ด(๋ฆฌ๋ Œ๋”๋ง) ๋‹ค์‹œ ํ•ด๋ผ!"
๋กœ๋ด‡ ์ƒ‰์น  ํ•˜๋‚˜ ํ–ˆ์„ ๋ฟ์ธ๋ฐ, ํ™”์žฅ์‹ค์— ์žˆ๋˜ ์•„๋น ๋„, ์ฃผ๋ฐฉ์— ์žˆ๋˜ ์‚ผ์ดŒ๋„, ์˜†๋ฐฉ์˜ ๋ˆ„๋‚˜๋„ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ž๊ธฐ ๋ฐฉ์„ ํ—ˆ๋ฌผ๊ณ  ๋‹ค์‹œ ์ง“๊ฒŒ ๋œ ์…ˆ์ด์•ผ.

โœ… ํ•ต์‹ฌ ์›๋ฆฌ:
React์˜ ์ ˆ๋Œ€ ๊ทœ์น™: "๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ(State)๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด, ๊ทธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ’ˆ๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋“ค์€ ๊ฐ•์ œ๋กœ ๋ฆฌ๋ Œ๋”๋ง๋œ๋‹ค."
์ƒํƒœ๋ฅผ ์ตœ์ƒ๋‹จ(App์ด๋‚˜ ์ตœ์ƒ์œ„ Context)์œผ๋กœ ๋ฌด์ง€์„ฑ์œผ๋กœ ๋Œ์–ด์˜ฌ๋ฆฌ๋ฉด, ๋‹จ๋ง ๋…ธ๋“œ(๋ฆฌํ”„)์—์„œ ์ผ์–ด๋‚œ ์กฐ๊ทธ๋งˆํ•œ ์ƒํ˜ธ์ž‘์šฉ ํ•˜๋‚˜๊ฐ€ ์•ฑ ์ „์ฒด ํŠธ๋ฆฌ๋ฅผ ๋ชจ์กฐ๋ฆฌ ๋‹ค์‹œ ๊ณ„์‚ฐ(Diffing)ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด ์„ฑ๋Šฅ์„ ์™„์ „ํžˆ ๋ฐ•์‚ด ๋ƒ…๋‹ˆ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ๊ทธ ์ƒํƒœ์™€ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ์ค‘๊ฐ„์— ๊ปด์žˆ๋Š” ์ˆ˜๋งŽ์€ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์“ฐ์ง€๋„ ์•Š์„ props๋ฅผ ์ฃผ๋ ์ฃผ๋  ๋‹ฌ๊ณ  ๋„˜๊ฒจ์ฃผ๊ฒŒ ๋˜์ฃ . ์ด๋ฅผ Props Drilling์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿงฉ State Colocation: ์ƒํƒœ๋Š” ์ž๊ธฐ ์ž๋ฆฌ์— ๋‘์–ด๋ผ

์ด ์žฌ์•™์„ ๋ง‰๊ธฐ ์œ„ํ•ด 5๋…„ ์ฐจ ์‹œ๋‹ˆ์–ด๋“ค์ด ๊ฐ€์žฅ ๋จผ์ € ์ฒดํฌํ•˜๋Š” ์„ค๊ณ„ ์›์น™์ด ๋ฐ”๋กœ State Colocation(์ƒํƒœ์˜ ์ ์†Œ ๋ฐฐ์น˜) ์ด์•ผ.
"์ƒํƒœ๋Š” ๊ทธ๊ฒƒ์„ ํ•„์š”๋กœ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ์˜ ์ตœ๋Œ€ํ•œ ๊ฐ€๊นŒ์šด ๊ณณ(์ตœํ•˜์œ„ ๊ณ„์ธต)์— ๋‘์–ด๋ผ" ๋ผ๋Š” ๋œป์ด์ง€.

โœ… ์˜ํ˜ธ์˜ ๋ฆฌํŒฉํ† ๋ง: ์ƒํƒœ๋ฅผ ๋‚˜๋ฝ์œผ๋กœ ๋–จ์–ด๋œจ๋ฆฌ๊ธฐ

๋Œ“๊ธ€์˜ '์ข‹์•„์š”' ์ƒํƒœ๋Š” App์ด๋‚˜ Feed ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•Œ ํ•„์š”๊ฐ€ ์ „ํ˜€ ์—†์–ด. ์˜ค๋กœ์ง€ ๊ทธ ๋Œ“๊ธ€ ์ปดํฌ๋„ŒํŠธ ์Šค์Šค๋กœ๋งŒ ์•Œ๊ณ  ์žˆ์œผ๋ฉด ๋ผ!

// โœ… ์šฐ์•„ํ•œ ์„ค๊ณ„ (Pro Approach: State Colocation)
 
// 1. App์€ ๊ฐ€๋ฒผ์›Œ์กŒ๋‹ค.
function App() {
  const [theme, setTheme] = useState('light');
  return (
    <div className={`app ${theme}`}>
      <CommunityHeader />
      <Sidebar />
      <Feed /> {/* props drilling์ด ์‚ฌ๋ผ์ง! */}
    </div>
  );
}
 
// 2. ์ƒํƒœ๋ฅผ ์ง„์งœ ํ•„์š”ํ•œ ์ตœ๋ง๋‹จ ์ปดํฌ๋„ŒํŠธ ์•ˆ์œผ๋กœ ์ง‘์–ด๋„ฃ๋Š”๋‹ค.
function CommentItem({ commentData }) {
  // ๐ŸŽฏ ์ด ๋Œ“๊ธ€๋งŒ์˜ ๋…์ž์ ์ธ(Local) ์ƒํƒœ!
  const [likes, setLikes] = useState(commentData.initialLikes);
 
  return (
    <div className="comment">
      <p>{commentData.text}</p>
      <button onClick={() => setLikes(likes + 1)}>
        ์ข‹์•„์š” {likes}
      </button>
    </div>
  );
}

์ด์ œ ํŠน์ • ๋Œ“๊ธ€์˜ ์ข‹์•„์š” ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋„, ๊ทธ ๋Œ“๊ธ€ ํ•˜๋‚˜(CommentItem)๋งŒ ๋ฆฌ๋ Œ๋”๋ง๋ผ. App์ด๋‚˜ ํ˜•์ œ ์ปดํฌ๋„ŒํŠธ๋“ค์€ ์•„๋ฌด๋Ÿฐ ํƒ€๊ฒฉ์„ ๋ฐ›์ง€ ์•Š์ง€. ์ด๊ฒƒ์ด ๋ฐ”๋กœ ์•„ํ‚คํ…์ฒ˜ ๋‹จ์œ„์˜ ๊ฐ€์žฅ ๊ณต์งœ๊ณ  ์™„๋ฒฝํ•œ ๋ Œ๋”๋ง ์ตœ์ ํ™”์•ผ.


๐Ÿ’ฅ ์—๋Ÿฌ ํ•ด๊ฒฐ ์นดํƒˆ๋กœ๊ทธ

โŒ ๋ฌด์ง€์„ฑ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ ๋„๊ตฌ(Zustand, Redux) ๋‚จ์šฉ

์ƒํ™ฉ: ์˜์ฒ ์ด๊ฐ€ "์•„! ํ”„๋กญ์Šค ๋“œ๋ฆด๋ง์ด ๋„ˆ๋ฌด ๊ท€์ฐฎ์•„! ๋ชจ๋“  ์ƒํƒœ๋ฅผ ์ „๋ถ€ Redux๋‚˜ Zustand ์ „์—ญ ์Šคํ† ์–ด(Global Store)์— ๋ฐ•์•„๋‘๊ณ  ์–ด๋””์„œ๋“  ๊ฐ€์ ธ๋‹ค ์“ฐ์ž!" ๋ผ๊ณ  ์ฃผ์žฅํ•œ๋‹ค.

์›์ธ: ์ƒํƒœ๋ฅผ ์ปดํฌ๋„ŒํŠธ ๋ฐ–(Store)์œผ๋กœ ๋นผ๋ƒˆ๋‹ค๊ณ  ํ•ด์„œ ์ƒํƒœ๊ฐ€ ์ข‹์•„์ง€๋Š” ๊ฒŒ ์•„๋‹ˆ์•ผ.
์ „์—ญ ์Šคํ† ์–ด์— ์ƒํƒœ๋ฅผ ๋‘๋Š” ์ˆœ๊ฐ„, ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋Š” ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋ฐ•์‚ด ๋‚˜. ๋‚˜์ค‘์— ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ ์ด ํšŒ์›๊ฐ€์ž… ํผ์„ ๊ทธ๋Œ€๋กœ ๋–ผ์–ด๋‹ค ์“ฐ๊ณ  ์‹ถ์€๋ฐ, Zustand ์Šคํ† ์–ด์™€ ๊ฒฐํ•ฉ(Coupling)๋˜์–ด ์žˆ์–ด์„œ ๋–ผ๊ฐˆ ์ˆ˜๊ฐ€ ์—†์–ด์ง€๋Š” ์œ ์ง€๋ณด์ˆ˜ ์ŠคํŒŒ๊ฒŒํ‹ฐ๊ฐ€ ๋˜์–ด๋ฒ„๋ฆฌ์ง€.

ํ•ด๊ฒฐ์ฑ…:
์ „์—ญ ์ƒํƒœ๋Š” "์ •๋ง๋กœ ์•ฑ์˜ ๋ชจ๋“  ๊ตฌ์„์—์„œ(Header, Sidebar, Mypage ๋“ฑ) ๋™์ผํ•˜๊ฒŒ ์ณ๋‹ค๋ด์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ(์˜ˆ: ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ์œ ์ € ์ •๋ณด, ๋‹คํฌ ๋ชจ๋“œ ํ…Œ๋งˆ, ์–ธ์–ด ์„ค์ •)" ์— ํ•œํ•ด์„œ๋งŒ ์ œํ•œ์ ์œผ๋กœ ์จ์•ผ ํ•ด.
์ž…๋ ฅ ํผ์˜ ๋ชจ๋‹ฌ ํ™œ์„ฑํ™” ์—ฌ๋ถ€๋‚˜, ๊ฒŒ์‹œ๊ธ€ ํ•˜๋‚˜์˜ ์ ‘๊ธฐ/ํŽผ์น˜๊ธฐ ๋ฒ„ํŠผ ์ƒํƒœ๋Š” ์ฒ ์ €ํ•˜๊ฒŒ ์ง€์—ญ ์ƒํƒœ(useState)๋กœ ๊ณ ๋ฆฝ(Isolate)์‹œ์ผœ์•ผ ํ•ด.


๐Ÿ ์ด๋ฒˆ์— ๋ฐฐ์šด ๋‚ด์šฉ ์ด์ •๋ฆฌ

์ƒํƒœ์˜ ์œ„์น˜โŒ ๋‚˜์œ ์„ค๊ณ„ ์˜ˆ์‹œโœ… ์ข‹์€ ์„ค๊ณ„ ์˜ˆ์‹œ
๋ชจ๋‹ฌ์ฐฝ Open ์ƒํƒœRedux ์Šคํ† ์–ด์— isModalOpen ๋ฐ•๊ธฐ<ModalWrap> ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— useState
๋Œ“๊ธ€ ์ž…๋ ฅ์ฐฝ ๋‚ด์šฉ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ text ์ƒํƒœ ๋งŒ๋“ค๊ณ  ๋‚ด๋ฆฌ๊ธฐ<CommentInput> ๋‚ด๋ถ€์— useState
๋‹คํฌ/๋ผ์ดํŠธ ํ…Œ๋งˆ<ThemeToggler> ์ง€์—ญ ์ƒํƒœ์•ฑ ์ตœ์ƒ์œ„ Context/์ „์—ญ ์ƒํƒœ (์ด๊ฑด ๋Œ์–ด์˜ฌ๋ ค์•ผ ํ•จ)

๐Ÿ’ก ํ•œ ์ค„๋กœ ๊ธฐ์–ตํ•˜๊ธฐ
์ตœ๋Œ€ํ•œ ๋Šฆ๊ฒŒ, ์ตœ๋Œ€ํ•œ ๋‚ฎ๊ฒŒ(๋ฐฉ๊ตฌ์„์—) ์ƒํƒœ๋ฅผ ์„ ์–ธํ•˜๋ผ. ๊ทธ๊ฒƒ์„ ํ•„์š”๋กœ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค๋งŒ์˜ '์ตœ์†Œ ๊ณตํ†ต ๋ถ€๋ชจ'๊นŒ์ง€๋งŒ ์ƒํƒœ๋ฅผ ๋Œ์–ด์˜ฌ๋ฆฌ๋Š” ๊ฒƒ์ด ํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜์˜ ์ „๋ถ€๋‹ค.


๐Ÿฃ ์˜์ฒ ์ด์˜ ํ‡ด๊ทผ ์ผ๊ธฐ

๋‚ด๊ฐ€ ์ง  ๋Œ“๊ธ€ ์ข‹์•„์š” ๋ฒ„ํŠผ ๋•Œ๋ฌธ์— ์ปค๋ฎค๋‹ˆํ‹ฐ ์‚ฌ์ดํŠธ ์ „์ฒด๊ฐ€ ์žฌ๋ Œ๋”๋ง๋˜๊ณ  ์žˆ์—ˆ๋‹ค๋‹ˆ ๋ถ€๋„๋Ÿฌ์›Œ์„œ ์ฅ๊ตฌ๋ฉ์—๋ผ๋„ ์ˆจ๊ณ  ์‹ถ๋‹ค. ๋ฌด์กฐ๊ฑด ์œ„๋กœ ๋Œ์–ด์˜ฌ๋ฆฌ๋ผ๋Š” ์˜›๋‚  ๋ธ”๋กœ๊ทธ ๊ธ€๋งŒ ๋ฏฟ์—ˆ๋˜ ๋‚ด ํƒ“์ด๋‹ค.

๐Ÿ’ก "์ƒํƒœ๋Š” ์ง„์งœ ํ•„์š”ํ•œ ์ตœ๋ง๋‹จ ๋ฐฉ๊ตฌ์„์— ๊ณ ๋ฆฝ(Colocation) ์‹œํ‚ค์ž. ๋ถˆํ•„์š”ํ•œ ์ „์—ญ ์ƒํƒœ๋Š” ์œ ์ง€๋ณด์ˆ˜ ์ŠคํŒŒ๊ฒŒํ‹ฐ์˜ ์›ํ‰์ด๋‹ค!"

๊ฐ€์กฑ ๋น„์œ ๋ฅผ ๋“ค์œผ๋‹ˆ๊นŒ ํ™• ์™€๋‹ฟ๋Š”๋‹ค. ์•„๋ฌด๋ฆฌ Redux, Zustand๊ฐ€ ํŽธํ•ด๋„ ๋‚จ์šฉํ•˜์ง€ ๋ง์•„์•ผ๊ฒ ๋‹ค๋Š” ๋‹ค์ง์„ ํ•ด๋ณธ๋‹ค. ์ƒํƒœ๋Š” ํ•„์š”ํ•  ๋•Œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ๋ถ€๋ชจ๊นŒ์ง€๋งŒ ์˜ฌ๋ฆฌ๋Š” ๊ฒŒ ์ง„์งœ ํ”„๋กœํŽ˜์…”๋„ํ•œ ์•„ํ‚คํ…์ฒ˜๊ตฌ๋‚˜. ์ง‘์— ๊ฐ€์„œ ๋‚ด ์ทจ์—…์šฉ ํฌํด ์ฝ”๋“œ ์ข€ ๊นŒ๋ณด๊ณ  ๋ถˆํ•„์š”ํ•œ ์ „์—ญ ์ƒํƒœ ๋‚ ๋ ค๋ฒ„๋ ค์•ผ์ง€. ๋ฟŒ๋“ฏํ•œ ํ•˜๋ฃจ๋‹ค.


๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ ํ€ด์ฆˆ

Q1. ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŽผ์นจ ๋ฉ”๋‰ด(Accordion)๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์กฐ๊ฑด: "๋‹จ ํ•˜๋‚˜์˜ ๋ฉ”๋‰ด๋งŒ ์—ด๋ ค ์žˆ์–ด์•ผ ํ•˜๋ฉฐ, ๋‹ค๋ฅธ ๋ฉ”๋‰ด๋ฅผ ํด๋ฆญํ•˜๋ฉด ๊ธฐ์กด ๊ฑด ๋‹ซํ˜€์•ผ ํ•œ๋‹ค." ์ด ๊ฒฝ์šฐ isOpen ์ƒํƒœ๋Š” ์ตœ์ ์˜ State Colocation ์›์น™์— ๋”ฐ๋ผ ์–ด๋””์— ๋ฐฐ์น˜ํ•ด์•ผ ํ• ๊นŒ์š”?

  • A) ๊ฐ ๋‹จ์ผ AccordionItem ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€ (useState(false))
  • B) ์•ฑ์˜ ์ตœ์ƒ๋‹จ ์ปดํฌ๋„ŒํŠธ App.tsx
  • C) ๋ชจ๋“  AccordionItem์„ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ๋ฐ”๋กœ ์œ„ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ (AccordionList)
  • D) Redux / Zustand ์Šคํ† ์–ด

โœ… ์ •๋‹ต: C

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค: ์•„์ฃผ ํ›Œ๋ฅญํ•œ ๋”œ๋ ˆ๋งˆ์ž…๋‹ˆ๋‹ค! ๋งŒ์•ฝ "๊ฐ๊ฐ์˜ ๋ฉ”๋‰ด๊ฐ€ ์„œ๋กœ ๋…๋ฆฝ์ ์œผ๋กœ ์—ด๋ฆฌ๊ณ  ๋‹ซํž ์ˆ˜ ์žˆ๋‹ค"๋ฉด ์ •๋‹ต์€ A(๊ฐ๊ฐ์˜ ์•„์ดํ…œ ๋‚ด๋ถ€)์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฌธ์ œ์˜ ์กฐ๊ฑด์€ "์„œ๋กœ๊ฐ€ ์„œ๋กœ์˜ ์˜ํ–ฅ์„ ๋ฐ›์•„์•ผ ํ•œ๋‹ค(ํ•˜๋‚˜๊ฐ€ ๋‹ซํ˜€์•ผ ํ•˜๋‚˜๊ฐ€ ์—ด๋ฆผ)" ์ž…๋‹ˆ๋‹ค. ํ˜•์ œ ์ปดํฌ๋„ŒํŠธ๋ผ๋ฆฌ ์†Œํ†ตํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์ด ์ƒํƒœ๋“ค์„ ๋™์‹œ์— ์ปจํŠธ๋กคํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ์†Œ ๊ณตํ†ต ๋ถ€๋ชจ์ธ AccordionList ๋กœ ์ƒํƒœ๋ฅผ ๋Œ์–ด์˜ฌ๋ฆฌ๋Š”(Lifting State Up) ๊ฒƒ์ด ์™„๋ฒฝํ•œ ์ •๋‹ต์ž…๋‹ˆ๋‹ค. ๋ถ€๋ชจ์— activeItemIndex ๊ฐ™์€ ์ƒํƒœ๋ฅผ ๋‘ฌ์•ผ ํ•˜์ฃ . (B, D๋Š” ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋„ˆ๋ฌด ๋งŽ์ด ๋Œ์–ด์˜ฌ๋ฆฐ ์˜ค๋‹ต์ž…๋‹ˆ๋‹ค.)

Q2. ์ž์‹ ์ปดํฌ๋„ŒํŠธ A, B, C๋ฅผ ๊ฑฐ์ณ ์ € ๋ฐ‘์˜ D ์ปดํฌ๋„ŒํŠธ๋กœ ํ•จ์ˆ˜์˜ ํ”„๋กญ์Šค(Props Drilling)๋ฅผ 4๋‹จ๊ณ„๋‚˜ ๋šซ๊ณ  ๋„˜๊ฒจ์ฃผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. A, B, C๋Š” ์ด ํ”„๋กญ์Šค๋ฅผ ์ „ํ˜€ ์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ํ•ฉ์„ฑ(Composition) ์ „๋žต์˜ ํ•ต์‹ฌ ๋ฌธ๋ฒ•์€ ๋ฌด์—‡์ธ๊ฐ€์š”?

  • A) React.memo ์‚ฌ์šฉ
  • B) children prop ์‚ฌ์šฉ (<A><B><C><D/></C></B></A> ํ˜•ํƒœ๋กœ ์กฐ๋ฆฝ)
  • C) useEffect ์‚ฌ์šฉ
  • D) useRef ์‚ฌ์šฉ

โœ… ์ •๋‹ต: B

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค: ํ”„๋กญ์Šค ๋“œ๋ฆด๋ง์„ ํ•ด๊ฒฐํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ๊ฐ•๋ ฅํ•œ ๋ฌด๊ธฐ์ž…๋‹ˆ๋‹ค.
์ตœ์ƒ์œ„ ๋ถ€๋ชจ์—์„œ ๊ตฌ๋ฉ์„ ๋šซ์–ด ๋ฐ์ดํ„ฐ๋ฅผ ์ธต์ธต์ด ๋„˜๊ฒจ์ฃผ๋Š” ๋Œ€์‹ , ์•„์˜ˆ ์ตœ์ƒ์œ„์—์„œ D ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ง์ ‘ ์กฐ๋ฆฝํ•œ ๋’ค ์ƒŒ๋“œ์œ„์น˜์˜ ๋‚ด์šฉ๋ฌผ์ธ children์œผ๋กœ ๊ฝ‚์•„ ๋„ฃ๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
์ค‘๊ฐ„์˜ A, B, C ์ปดํฌ๋„ŒํŠธ๋Š” ์ž์‹ ์ด ์–ด๋–ค children ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ›์•˜๋Š”์ง€ ์•Œ ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ ํ”„๋กญ์Šค๋ฅผ ํŒจ์Šคํ•  ํ•„์š”๋„ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
(10๋ฒˆ ์งธ ๊ฐ€์ด๋“œ์—์„œ ์ง‘์ค‘์ ์œผ๋กœ ํŒŒํ—ค์น  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค!)

Q3. ์˜์ฒ ์ด๊ฐ€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ฆ‰์‹œ ์•ฑ์˜ ์–ธ์–ด๊ฐ€ 'ํ•œ๊ตญ์–ด'์—์„œ '์˜์–ด'๋กœ ๋ฐ”๋€Œ๊ฒŒ ๋งŒ๋“ค๊ณ  ์‹ถ์–ด ํ•ฉ๋‹ˆ๋‹ค. ์˜์ฒ ์ด๋Š” State Colocation ์›์น™์„ ๋งน์‹ ํ•˜์—ฌ, ์–ธ์–ด ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—๋งŒ ์ง€์—ญ ์ƒํƒœ const [lang, setLang] = useState('ko')๋ฅผ ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ํ™”๋ฉด ์ „์ฒด์˜ ๊ธ€์ž๋“ค์ด ์˜์–ด๋กœ ๋ฐ”๋€Œ์—ˆ์„๊นŒ์š”? ์›๋ฆฌ์™€ ํ•จ๊ป˜ ์„ค๋ช…ํ•ด ๋ณด์„ธ์š”.

โœ… ์ •๋‹ต ๋ฐ ์ฃผ๊ด€์‹ ํ•ด์„ค:

์ ˆ๋Œ€ ๋ฐ”๋€Œ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์–ธ์–ด ์„ค์ •(๋‹ค๊ตญ์–ด) ๋ฐ์ดํ„ฐ๋Š” ๋ฒ„ํŠผ ํ•˜๋‚˜๋งŒ ํ•„์š”ํ•œ ๊ฒŒ ์•„๋‹ˆ๋ผ, ํ™”๋ฉด์— ์กด์žฌํ•˜๋Š” Header, Footer, ์ฝ˜ํ…์ธ  ์˜์—ญ ๋“ฑ ์•ฑ ๋‚ด์˜ ๊ฑฐ์˜ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋™์‹œ์— ๊ตฌ๋…ํ•˜๊ณ  ๊ณต์œ ํ•ด์•ผ ํ•˜๋Š” ์ฒ ์ €ํ•œ '์ „์—ญ ์ƒํƒœ(Global State)' ์ž…๋‹ˆ๋‹ค.
์˜์ฒ ์ด๊ฐ€ ๋ฒ„ํŠผ ๋‚ด๋ถ€์— ์ง€์—ญ ๋ณ€์ˆ˜๋กœ ๊ณ ๋ฆฝ์‹œ์ผœ ๋ฒ„๋ ธ๊ธฐ ๋•Œ๋ฌธ์—, ๋ฒ„ํŠผ๋งŒ ์˜์–ด๊ฐ€ ๋˜์—ˆ์„ ๋ฟ ์™ธ๋ถ€์— ์žˆ๋Š” ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋“ค์€ ๊ทธ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€ํ•œ ์‚ฌ์‹ค์กฐ์ฐจ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค
(์ƒํƒœ๋ฅผ ๋„˜๊ฒจ๋ฐ›์„ ๊ฒฝ๋กœ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๋ฆฌ๋ Œ๋”๋ง๋„ ํŠธ๋ฆฌ๊ฑฐ๋˜์ง€ ์•Š์Œ).

  • ๊ฒฐ๋ก : ์ด๋Ÿฐ ์„ฑ๊ฒฉ์˜ ํ…Œ๋งˆ, ์–ธ์–ด์„ค์ •, ์œ ์ € ๋กœ๊ทธ์ธ ์ •๋ณด ๋“ฑ์€ ์˜ˆ์™ธ์ ์œผ๋กœ ์ตœ์ƒ๋‹จ(Context Provider๋‚˜ ์ „์—ญ ์Šคํ† ์–ด)์œผ๋กœ ๊ณผ๊ฐํ•˜๊ฒŒ ๋Œ์–ด์˜ฌ๋ ค์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ ์ž…๋‹ˆ๋‹ค. Colocation์˜ ์˜ˆ์™ธ ์ผ€์ด์Šค์ธ ์…ˆ์ด์ฃ .