리액트에서 `index`를 key로 사용하는 것은 권장되지 않는 이유는 배열의 요소들이 추가되거나 삭제될 때, 배열의 순서가 바뀌는 경우 문제가 발생할 수 있기 때문입니다.
리액트에서 `key`를 통해 리스트에서 어떤 요소가 변경, 추가, 삭제됐는지를 추적합니다. 그러나 index를 key로 사용하면 배열의 순서가 변경될 때 리액트가 요소들을 잘못 인식할 수 있습니다. 예를 들어 배열에 새로운 요소가 중간에 추가되면 그 뒤에 있는 요소들의 인덱스가 모두 변경되게 된다. 리액트는 이를 새로운 요소로 인식해 불필요하게 재렌더링을 하거나, 요소의 상태를 잘못 처리할 수 있습니다.
// 초기 상태의 할일 목록
const todos = [
{ text: '운동하기' }, // index: 0
{ text: '공부하기' }, // index: 1
{ text: '청소하기' } // index: 2
];
// '독서하기'를 첫 번째로 추가하면
const newTodos = [
{ text: '독서하기' }, // index: 0 (새로운 항목)
{ text: '운동하기' }, // index: 1 (기존 index 0)
{ text: '공부하기' }, // index: 2 (기존 index 1)
{ text: '청소하기' } // index: 3 (기존 index 2)
];
이로 인해 성능 문제가 발생하거나, 사용자 입력 상태 같은 요소가 의도치 않게 초기화되는 등 예기치 않은 버그가 생길 수 있습니다. 그래서 배열의 순서나 요소 변경에 영향을 받지 않는 고유한 값을 key로 사용하는 것이 좋습니다.
상태 관리 문제
const items = ['A', 'B', 'C'];
items.map((item, index) => (
<input key={index} defaultValue={item} />
));
// 'B'가 삭제되면 'C'의 index가 1로 변경되어
// 이전 'B'의 input 상태를 물려받게 됨
성능 저하
- 순서 변경 시 모든 컴포넌트가 재렌더링
- Virtual DOM 비교 작업 증가
- 애니메이션/트랜지션 오작동 → key가 바뀌면서 의도하지 않은 애니메이션 발생
대안
key는 데이터의 유일성을 보장하고 변하지 않는 값을 사용하는 것이 중요합니다. 서버의 데이터 베이스에서 제공하는 고유 ID를 사용하는 것이 일반적입니다. 또한 `UUID` 같이 전역적으로 고유한 ID를 생성이 가능한 라이브러리를 사용할 수 있습니다.
// 고유 ID 사용
items.map(item => (
<Component key={item.id} />
));
// 안정적인 값 조합
items.map(item => (
<Component key={`${item.category}-${item.name}`} />
));
리액트에서 index
를 key로 사용하는 것은 권장되지 않는 이유는 배열의 요소들이 추가되거나 삭제될 때, 배열의 순서가 바뀌는 경우 문제가 발생할 수 있기 때문입니다.
리액트에서 key
를 통해 리스트에서 어떤 요소가 변경, 추가, 삭제됐는지를 추적합니다. 그러나 index를 key로 사용하면 배열의 순서가 변경될 때 리액트가 요소들을 잘못 인식할 수 있습니다. 예를 들어 배열에 새로운 요소가 중간에 추가되면 그 뒤에 있는 요소들의 인덱스가 모두 변경되게 된다. 리액트는 이를 새로운 요소로 인식해 불필요하게 재렌더링을 하거나, 요소의 상태를 잘못 처리할 수 있습니다.
// 초기 상태의 할일 목록
const todos = [
{ text: '운동하기' }, // index: 0
{ text: '공부하기' }, // index: 1
{ text: '청소하기' } // index: 2
];
// '독서하기'를 첫 번째로 추가하면
const newTodos = [
{ text: '독서하기' }, // index: 0 (새로운 항목)
{ text: '운동하기' }, // index: 1 (기존 index 0)
{ text: '공부하기' }, // index: 2 (기존 index 1)
{ text: '청소하기' } // index: 3 (기존 index 2)
];
이로 인해 성능 문제가 발생하거나, 사용자 입력 상태 같은 요소가 의도치 않게 초기화되는 등 예기치 않은 버그가 생길 수 있습니다. 그래서 배열의 순서나 요소 변경에 영향을 받지 않는 고유한 값을 key로 사용하는 것이 좋습니다.
상태 관리 문제
const items = ['A', 'B', 'C'];
items.map((item, index) => (
<input key={index} defaultValue={item} />
));
// 'B'가 삭제되면 'C'의 index가 1로 변경되어
// 이전 'B'의 input 상태를 물려받게 됨
성능 저하
- 순서 변경 시 모든 컴포넌트가 재렌더링
- Virtual DOM 비교 작업 증가
- 애니메이션/트랜지션 오작동 → key가 바뀌면서 의도하지 않은 애니메이션 발생
대안
key는 데이터의 유일성을 보장하고 변하지 않는 값을 사용하는 것이 중요합니다. 서버의 데이터 베이스에서 제공하는 고유 ID를 사용하는 것이 일반적입니다. 또한 UUID
같이 전역적으로 고유한 ID를 생성이 가능한 라이브러리를 사용할 수 있습니다.
// 고유 ID 사용
items.map(item => (
<Component key={item.id} />
));
// 안정적인 값 조합
items.map(item => (
<Component key={`${item.category}-${item.name}`} />
));