[TECH-QA] λ¦¬μ•‘νŠΈμ—μ„œ map μ‚¬μš©μ‹œ keyλ₯Ό μ‚¬μš©ν•˜λŠ” 이유

κ΄€λ ¨ ν‚€μ›Œλ“œ

μ„±λŠ₯ μ΅œμ ν™”

λ¦¬λ Œλ”λ§ κ΄€λ ¨ λ°©μ§€ 문제

λ¦¬μ•‘νŠΈμ—μ„œ map을 μ‚¬μš©ν•  λ•Œ 각 ν•­λͺ©μ— κ³ μœ ν•œ ν‚€(key)λ₯Ό μ œκ³΅ν•΄μ•Ό ν•˜λŠ” μ΄μœ λŠ” μ„±λŠ₯ μ΅œμ ν™”μ™€ λ¦¬λ Œλ”λ§ κ΄€λ ¨ 문제λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•¨μž…λ‹ˆλ‹€.

κ³ μœ ν•œ ν‚€λ₯Ό μ œκ³΅ν•˜λ©΄ λ¦¬μ•‘νŠΈκ°€ 가상 DOM(Virtual DOM)μ—μ„œ 각 ν•­λͺ©μ„ μ •ν™•νžˆ 식별할 수 μžˆμ–΄, λ°μ΄ν„°μ˜ λ³€κ²½ 사항을 효율적으둜 λΉ„κ΅ν•˜κ³  μ—…λ°μ΄νŠΈν•  수 μžˆμŠ΅λ‹ˆλ‹€. 즉, λ³€κ²½λœ μš”μ†Œλ§Œ λ‹€μ‹œ λ Œλ”λ§ν•˜κ³  λ‚˜λ¨Έμ§€ μš”μ†ŒλŠ” κ·ΈλŒ€λ‘œ μœ μ§€ν•˜μ—¬ λΆˆν•„μš”ν•œ λ¦¬λ Œλ”λ§μ„ μ€„μž…λ‹ˆλ‹€.

반면, ν‚€λ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠμœΌλ©΄ λ¦¬μ•‘νŠΈλŠ” 기본적으둜 λ°°μ—΄μ˜ 인덱슀λ₯Ό ν‚€λ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€. ν•˜μ§€λ§Œ 인덱슀λ₯Ό ν‚€λ‘œ μ‚¬μš©ν•˜λŠ” 것은 리슀트의 μˆœμ„œκ°€ λ³€κ²½λ˜κ±°λ‚˜ ν•­λͺ©μ΄ μΆ”κ°€/μ‚­μ œλ  λ•Œ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλŠ”λ° 예λ₯Ό λ“€μ–΄, ν•­λͺ©μ˜ μˆœμ„œκ°€ λ°”λ€Œλ©΄ μΈλ±μŠ€κ°€ ν•΄λ‹Ή ν•­λͺ©μ˜ κ³ μœ μ„±μ„ 보μž₯ν•˜μ§€ λͺ»ν•΄ λ¦¬μ•‘νŠΈκ°€ 잘λͺ»λœ μš”μ†Œλ₯Ό μ—…λ°μ΄νŠΈν•˜κ±°λ‚˜ 전체 λͺ©λ‘μ„ λ‹€μ‹œ λ Œλ”λ§ν•˜κ²Œ 될 κ°€λŠ₯성이 λ†’μ•„μ§‘λ‹ˆλ‹€.

μ΄λŠ” μ„±λŠ₯ μ €ν•˜λΏλ§Œ μ•„λ‹ˆλΌ UI의 일관성을 ν•΄μΉ  수 μžˆλŠ” 버그λ₯Ό μœ λ°œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ ν‚€(Key)λ‘œλŠ” 리슀트 λ‚΄μ—μ„œ κ³ μœ ν•˜κ³  μ•ˆμ •μ μΈ κ°’(예: λ°μ΄ν„°λ² μ΄μŠ€μ˜ IDλ‚˜ UUID)을 μ‚¬μš©ν•˜λŠ” 것이 ꢌμž₯λ©λ‹ˆλ‹€. μž„μ‹œλ‘œ μƒμ„±λœ κ°’μ΄λ‚˜ 변동성이 높은 값은 ν”Όν•΄μ•Ό ν•˜λ©°, ν‚€κ°€ κ³ μœ ν•˜μ§€ μ•ŠμœΌλ©΄ λ¦¬μ•‘νŠΈκ°€ κ²½κ³ λ₯Ό 좜λ ₯ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 λ¦¬μ•‘νŠΈμ˜ μž¬μ‘°μ •(reconciliation) 과정이 μ΅œμ ν™”λ˜κ³ , μ‚¬μš©μž κ²½ν—˜κ³Ό μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„±λŠ₯이 ν–₯μƒλ©λ‹ˆλ‹€.

μ™œ 인덱슀λ₯Ό ν‚€λ‘œ μ‚¬μš©ν•˜λ©΄ λ¬Έμ œκ°€ μƒκΈ°λŠ”κ°€?

Reactμ—μ„œ map으둜 리슀트λ₯Ό λ Œλ”λ§ν•  λ•Œ 각 ν•­λͺ©μ— ν‚€λ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠμœΌλ©΄, ReactλŠ” 기본적으둜 λ°°μ—΄μ˜ 인덱슀(0, 1, 2, ...)λ₯Ό ν‚€λ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€. 이 μΈλ±μŠ€λŠ” 리슀트의 μœ„μΉ˜λ₯Ό λ‚˜νƒ€λ‚΄λ―€λ‘œ, 리슀트의 ν•­λͺ©μ΄ κ³ μ •λ˜μ–΄ 있고 μˆœμ„œκ°€ μ ˆλŒ€ λ³€ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ λ¬Έμ œκ°€ 없을 수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ λ¦¬μŠ€νŠΈμ— ν•­λͺ©μ΄ μΆ”κ°€λ˜κ±°λ‚˜ μ‚­μ œλ˜κ±°λ‚˜ μˆœμ„œκ°€ 변경될 λ•Œ, μΈλ±μŠ€λŠ” 더 이상 ν•΄λ‹Ή ν•­λͺ©μ˜ κ³ μœ μ„±μ„ 보μž₯ν•˜μ§€ λͺ»ν•˜κ²Œ λ©λ‹ˆλ‹€. μ΄λŠ” React의 μž¬μ‘°μ •(reconciliation) κ³Όμ •μ—μ„œ ν˜Όλž€μ„ μΌμœΌν‚΅λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, [A, B, C]λΌλŠ” λ¦¬μŠ€νŠΈκ°€ μžˆλ‹€κ³  κ°€μ •ν•˜κ³ , 각 ν•­λͺ©μ˜ ν‚€κ°€ 인덱슀인 경우: A(key=0), B(key=1), C(key=2). μ—¬κΈ°μ„œ Bκ°€ μ‚­μ œλ˜λ©΄ λ¦¬μŠ€νŠΈλŠ” [A, C]κ°€ 되고, ν‚€λŠ” A(key=0), C(key=1)둜 λ°”λ€λ‹ˆλ‹€. μ›λž˜ C의 ν‚€λŠ” 2μ˜€λŠ”λ°, 이제 1둜 λ°”λ€Œμ—ˆμŠ΅λ‹ˆλ‹€. ReactλŠ” ν‚€λ₯Ό κΈ°μ€€μœΌλ‘œ ν•­λͺ©μ„ μ‹λ³„ν•˜λ―€λ‘œ, Cκ°€ μƒˆλ‘œμš΄ ν•­λͺ©μΈμ§€, κΈ°μ‘΄ ν•­λͺ©μΈμ§€ ν˜Όλž€μŠ€λŸ¬μ›Œν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이둜 인해 λΆˆν•„μš”ν•œ λ¦¬λ Œλ”λ§μ΄ λ°œμƒν•˜κ±°λ‚˜ μƒνƒœ(state)κ°€ μ—‰λš±ν•œ ν•­λͺ©μ— 연결될 수 μžˆμŠ΅λ‹ˆλ‹€.

같은 리슀트 [A, B, C]μ—μ„œ μˆœμ„œκ°€ [B, A, C]둜 λ°”λ€Œμ—ˆλ‹€κ³  ν•΄λ΄…μ‹œλ‹€.
인덱슀λ₯Ό ν‚€λ‘œ μ‚¬μš©ν•˜λ©΄: μ›λž˜λŠ” A(key=0), B(key=1), C(key=2)μ˜€μ§€λ§Œ, 이제 B(key=0), A(key=1), C(key=2)κ°€ λ©λ‹ˆλ‹€.
React μž…μž₯μ—μ„œλŠ” ν‚€ 0이 Aμ—μ„œ B둜, ν‚€ 1이 Bμ—μ„œ A둜 바뀐 κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€. μ΄λŠ” ν•­λͺ© μžμ²΄κ°€ λ°”λ€Œμ§€ μ•Šμ•˜μŒμ—λ„ λΆˆκ΅¬ν•˜κ³  Reactκ°€ 이λ₯Ό μƒˆλ‘œμš΄ ν•­λͺ©μœΌλ‘œ μ˜€ν•΄ν•˜κ²Œ λ§Œλ“€μ–΄, DOM을 λΆˆν•„μš”ν•˜κ²Œ μ—…λ°μ΄νŠΈν•˜κ±°λ‚˜ μ»΄ν¬λ„ŒνŠΈμ˜ μƒνƒœ(예: μž…λ ₯ ν•„λ“œ κ°’)λ₯Ό 잘λͺ»λœ ν•­λͺ©μ— μ—°κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

리슀트 ν•­λͺ©μ΄ μƒνƒœ(예: μ²΄ν¬λ°•μŠ€ 선택 μ—¬λΆ€)λ₯Ό κ°€μ§€κ³  μžˆλ‹€λ©΄, 인덱슀λ₯Ό ν‚€λ‘œ μ‚¬μš©ν•˜λ©΄ ν•­λͺ©μ˜ μœ„μΉ˜κ°€ λ°”λ€” λ•Œ μƒνƒœκ°€ μ—‰λš±ν•œ ν•­λͺ©μ— 뢙을 수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, A에 체크가 λ˜μ–΄ μžˆμ—ˆλŠ”λ° μˆœμ„œκ°€ λ°”λ€Œλ©΄ 체크가 B둜 μ΄λ™ν•΄λ²„λ¦¬λŠ” λ¬Έμ œκ°€ 생길 수 μžˆμŠ΅λ‹ˆλ‹€.

인덱슀λ₯Ό ν‚€λ‘œ μ‚¬μš©ν•˜λ©΄ 리슀트의 ν•­λͺ©μ΄ μΆ”κ°€λ˜κ±°λ‚˜ μ‚­μ œλ  λ•Œ ν‚€ 값이 λ‹€μ‹œ λ³€κ²½λ˜κΈ° λ•Œλ¬Έμ— λ¬Έμ œκ°€ λ°œμƒν•©λ‹ˆλ‹€. μΈλ±μŠ€λŠ” ν•­λͺ©μ˜ 본질적인 κ³ μœ μ„±μ„ λ‚˜νƒ€λ‚΄λŠ” 것이 μ•„λ‹ˆλΌ λ‹¨μˆœνžˆ 리슀트 λ‚΄μ—μ„œμ˜ μœ„μΉ˜λ§Œμ„ λ‚˜νƒ€λ‚΄κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.
ReactλŠ” ν‚€λ₯Ό 톡해 "이 ν•­λͺ©μ΄ 이전과 λ™μΌν•œ ν•­λͺ©μΈκ°€?"λ₯Ό νŒλ‹¨ν•˜λŠ”λ°, μΈλ±μŠ€λŠ” κ·Έ κΈ°μ€€μœΌλ‘œ λΆ€μ ν•©ν•©λ‹ˆλ‹€.

이 문제λ₯Ό ν”Όν•˜λ €λ©΄ 리슀트 λ‚΄μ—μ„œ κ³ μœ ν•˜κ³  μ•ˆμ •μ μΈ κ°’(예: λ°μ΄ν„°λ² μ΄μŠ€μ˜ ID, UUID λ“±)을 ν‚€λ‘œ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.
const items = [
  { id: "a1", name: "A" },
  { id: "b2", name: "B" },
  { id: "c3", name: "C" }
];

return (
  <ul>
    {items.map(item => (
      <li key={item.id}>{item.name}</li>
    ))}
  </ul>
);
μ΄λ ‡κ²Œ ν•˜λ©΄ μˆœμ„œκ°€ λ°”λ€Œκ±°λ‚˜ ν•­λͺ©μ΄ μΆ”κ°€/μ‚­μ œλ˜μ–΄λ„ idλŠ” λ³€ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ Reactκ°€ 각 ν•­λͺ©μ„ μ •ν™•νžˆ 좔적할 수 μžˆμŠ΅λ‹ˆλ‹€.