๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ—‚ WIL

React์˜ ํƒ€์ž… ๋น„๊ต์™€ key์˜ ์—ญํ• 

by nalong 2025. 6. 22.

์š”์ฆ˜ ๋‹ค์‹œ Advanced React๋ฅผ ์ฝ์œผ๋ฉฐ, React์—์„œ key๊ฐ€ DOM ์žฌ์‚ฌ์šฉ ์—ฌ๋ถ€๋ฅผ ์–ด๋–ป๊ฒŒ ๊ฒฐ์ •์ง“๋Š”์ง€์— ๋Œ€ํ•œ ๋‚ด์šฉ์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด๋ณด์•˜๋‹ค. 

ํƒ€์ž… ๋น„๊ต๋Š” "DOM ์žฌ์‚ฌ์šฉ" ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค.

const App = () => {
  const [isMarketMember, setIsMarketMember] = useState(false);
  ....
  return (
    <>
      {isMarketMember ? (
        <Input
          id="market-id"
          placeholder="Enter your Market ID"
          onChange={handleMarketIdChange}
        />
      ) : (
        <Input
          id="user-name"
          placeholder="Enter your Name"
          onChange={handleNameChange}
        />
      )}
    </>
  );
};

 

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด isMarketMember ๊ฐ’์— ๋”ฐ๋ผ <Input /> ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฐ”๋€Œ๋Š” ๋™์ž‘์„ ๋‹น์—ฐํžˆ ๊ธฐ๋Œ€ํ•˜์ง€๋งŒ, ์‹ค์ œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์—์„œ๋Š” ์ž…๋ ฅ๊ฐ’์ด ์œ ์ง€๋œ๋‹ค. ์ฆ‰, Market ID๋ฅผ ์ž…๋ ฅํ•œ ๋’ค ์ฒดํฌ๋ฐ•์Šค๋ฅผ ํ•ด์ œํ•˜๋ฉด Name ์ž…๋ ฅ์ฐฝ์ด ๋‚˜์˜ค๋Š”๋ฐ, ๋ฐฉ๊ธˆ ์ „ Market ID ํ•„๋“œ์— ์ž…๋ ฅํ–ˆ๋˜ ๊ฐ’์ด ๊ทธ๋Œ€๋กœ ๋ณด์ธ๋‹ค.

์™œ ์ž…๋ ฅ๊ฐ’์ด ์œ ์ง€๋ ๊นŒ?

์ด ํ˜„์ƒ์€ React๊ฐ€ ๋‘ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ™์€ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
์ฆ‰, ๋ฆฌ๋ Œ๋”๋ง์€ ์ผ์–ด๋‚ฌ์ง€๋งŒ ๊ธฐ์กด DOM ๋…ธ๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— input์˜ ๋‚ด๋ถ€ ์ƒํƒœ๊ฐ€ ๊ทธ๋Œ€๋กœ ๋‚จ์•„์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

๋ฆฌ์•กํŠธ ๋™์ž‘์„ ์‚ดํŽด๋ณด์ž.

 

React๋Š” JSX๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.

<Input
  id="market-id"
  placeholder="Enter your Market ID"
  onChange={handleMarketIdChange}
/>

 

์œ„ ์ฝ”๋“œ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ๋‹ค์Œ์ฒ˜๋Ÿผ ๋ณ€ํ™˜๋œ๋‹ค.

React.createElement(Input, {
  id: 'market-id',
  placeholder: 'Enter your Market ID',
  onChange: handleMarketIdChange,
});

 

์ฆ‰, JSX๋Š” ๊ฒฐ๊ตญ React.createElement(type, props)๋กœ ๋ณ€ํ™˜๋˜๋ฉฐ, React๋Š” ์ด type ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ "๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ์ธ์ง€"๋ฅผ ํŒ๋‹จํ•œ๋‹ค.

  • ํƒ€์ž…์ด ๊ฐ™๋‹ค๋ฉด = ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ
  • ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋ผ๋ฉด = ๊ธฐ์กด DOM ๋…ธ๋“œ๋ฅผ ์žฌ์‚ฌ์šฉ
  • props๋งŒ ๋ฐ”๋€Œ์—ˆ๋‹ค๋ฉด = DOM์€ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ๋ณ€๊ฒฝ๋งŒ ์ ์šฉ

๊ฒฐ๊ณผ์ ์œผ๋กœ, <Input />์ด JSX ์•ˆ์—์„œ ์กฐ๊ฑด๋ฌธ์œผ๋กœ ๊ฐ์‹ธ์กŒ๋”๋ผ๋„ React ์ž…์žฅ์—์„œ๋Š” ๋งค๋ฒˆ ๋™์ผํ•œ Input ํƒ€์ž…์ด๋ฏ€๋กœ, ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋ผ๊ณ  ๊ฐ„์ฃผํ•˜์—ฌ ๊ธฐ์กด DOM์„ ์žฌ์‚ฌ์šฉํ•˜๊ณ , ๋‚ด๋ถ€ ์ƒํƒœ๋„ ๊ทธ๋Œ€๋กœ ์œ ์ง€๋˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ?

key๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. React์—๊ฒŒ ๋‘ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์™„์ „ํžˆ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์ž„์„ ์•Œ๋ ค์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด, ๊ณ ์œ ํ•œ key ๊ฐ’์„ ์ง€์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

{isMarketMember ? (
  <Input
    key="market"
    id="market-id"
    placeholder="Enter your Market ID"
    onChange={handleMarketIdChange}
  />
) : (
  <Input
    key="personal"
    id="user-name"
    placeholder="Enter your Name"
    onChange={handleNameChange}
  />
)}

 

์ด๋ ‡๊ฒŒ key๊ฐ€ ๋‹ค๋ฅด๋ฉด React๋Š” ์ด์ „์— ๋ Œ๋”๋ง ๋œ DOM ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ , ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๋”ฐ๋ผ์„œ <Input key="market" />์™€ <Input key="personal" /> ์€ ๋™์ผํ•œ ์œ„์น˜์— ์žˆ๋”๋ผ๋„ ์„œ๋กœ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋กœ ์ธ์‹๋œ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ, ์ „ํ™˜์ด ์ผ์–ด๋‚  ๋•Œ ๊ธฐ์กด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์–ธ๋งˆ์šดํŠธ ํ•˜๊ณ , ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งˆ์šดํŠธ ํ•˜๊ฒŒ ๋˜์–ด input value๊ฐ€ ์ดˆ๊ธฐํ™”๋œ๋‹ค.

์ฆ‰, type์ด ๋‹ค๋ฅด๊ฑฐ๋‚˜ key๊ฐ€ ๋‹ค๋ฅด๋ฉด, React๋Š” ๋™์ผํ•œ ์œ„์น˜์— ์žˆ๋”๋ผ๋„ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ฐ„์ฃผํ•˜๊ณ  ๊ธฐ์กด DOM ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•œ ๋’ค ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑํ•œ๋‹ค.

key์—๋Š” ์œ ๋‹ˆํฌํ•œ ๊ฐ’์„ ๋„ฃ์–ด์•ผ ํ•œ๋‹ค.

์ด ๋ง์€ ๋‹จ์ˆœํ•œ ๊ทœ์น™์ด ์•„๋‹ˆ๋ผ, React๊ฐ€ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ๋ฅผ ์ผ๊ด€๋˜๊ฒŒ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ํ•ต์‹ฌ ์›์น™์ด๋‹ค. ํŠนํžˆ ์ •๋ ฌ์ด ๊ฐ€๋Šฅํ•˜๊ฑฐ๋‚˜, ์‚ฌ์šฉ์ž๊ฐ€ ๋“œ๋ž˜๊ทธ๋กœ ๋ฆฌ์ŠคํŠธ์˜ ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๋Š” UI์—์„œ๋Š” ํ•ด๋‹น ์›์น™์ด ๋ฌด๋„ˆ์ง€๋ฉด ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ์™€ ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋’ค์„ž์ด๋Š” ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋ž˜์™€ ๊ฐ™์€ ์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜์ž.

[
  { id: 'member-number', placeholder: 'Enter your member number' },
  { id: 'user-id', placeholder: 'Enter your user ID' },
]

 

์‚ฌ์šฉ์ž๊ฐ€ ํ•„ํ„ฐ๋ฅผ ์ ์šฉํ•˜๊ฑฐ๋‚˜ ๋“œ๋ž˜๊ทธ๋กœ ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๋ฉด, ๋ฆฌ์ŠคํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฐ”๋€” ์ˆ˜ ์žˆ๋‹ค.

[
  { id: 'user-id', placeholder: 'Enter your user ID' },
  { id: 'member-number', placeholder: 'Enter your member number' },
]

 

์ด ์ƒํƒœ์—์„œ ๋ฆฌ์ŠคํŠธ๋ฅผ ์•„๋ž˜์ฒ˜๋Ÿผ index๋ฅผ key๋กœ ์‚ฌ์šฉํ•˜๋ฉด, ์š”์†Œ์˜ ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ๋„ React๋Š” ๋™์ผํ•œ key๋กœ ํŒ๋‹จํ•˜๊ณ  ๊ธฐ์กด DOM ๋…ธ๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•œ๋‹ค. ์ด๋กœ ์ธํ•ด ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ฐ’, ํฌ์ปค์Šค ์ƒํƒœ ๋“ฑ ์ปดํฌ๋„ŒํŠธ์˜ ๋‚ด๋ถ€ ์ƒํƒœ๊ฐ€ ์—‰์ผœ๋ฒ„๋ฆฌ๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

{list.map((item, index) => (
  <Input
    key={index}
    id={item.id}
    placeholder={item.placeholder}
  />
))}

 

 

https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key

 

Rendering Lists – React

The library for web and native user interfaces

react.dev