리스트를 render할 때 React는 render 사이에서 어떤 항목이 어떤 항목인지 알아야 DOM 노드를 올바르게 재사용, 재정렬, 삽입, 삭제할 수 있습니다. **key**가 바로 그 정체성(identity)입니다.
jsx
{users.map(user => (
<Row key={user.id} user={user} /> // 안정적이고 고유한 id
))}
왜 배열 인덱스가 위험한가
인덱스를 key로 사용하면 React에게 "위치 0의 항목은 이전과 동일한 항목이다"라고 말하는 것입니다 — 이는 리스트가 재정렬되거나 앞쪽에서 삽입/제거하는 순간 깨집니다:
jsx
// items: [A, B, C] with keys 0,1,2
// A를 DELETE → [B, C], key는 0,1이 됨
// React는 key 0(이전 A)이 이제 B이고, key 1(이전 B)이 이제 C라고 생각...
// 그래서 잘못된 항목에 잘못된 DOM 상태를 유지합니다.
실제 증상: 입력 필드 리스트에서 한 행에 타이핑한 내용이 삭제/정렬 후 다른 행으로 "점프"하는 경우입니다. React가 잘못된 <input>(그리고 그 내부 값/포커스)을 재사용했기 때문입니다.
규칙
- 데이터에서 안정적이고 고유한 id를 사용하세요(
user.id, slug). - 인덱스는 재정렬, 삽입, 삭제가 절대 없는 정적 리스트에서만 허용됩니다.
- key는 형제 요소 사이에서 고유해야 합니다(전역적으로가 아니라).
key는 reconciliation 알고리즘에 대한 힌트입니다. 올바르게 설정하면 성능과 컴포넌트 state가 모두 올바르게 유지됩니다.
