흔히 리액트에서 반복문을 사용할 때 map 메서드를 사용하곤 하는데
key값을 지정해주지 않으면 브라우저 콘솔 창에서 key값을 넣으라는 오류 메시지를 만나곤 한다.
should have a unique “key” prop.
리액트를 처음 공부할 때는 단순히 index를 부여하여 오류 메시지를 없앴던 적이 있다.
그리고 얼마 지나지않아 해당 사항이 안티패턴이 될 수 있다는 것을 알게된 이후 index만을 사용한 key를 사용하지 않으려고 신경썼던 기억도 있지만, (정말 유니크하게 부여할 수 없는 경우에만 어쩔수 없이 index를 사용하고자 했다.) 정확히 왜 key에 index를 부여하면 안 되는지에 대해서는 생각해보지 않았던 것 같아 이번 기회에 정리해보고자 한다.
· 순서가 보장되고, 동적으로 변경될 일이 없다면 index를 key 로 사용해도 문제되지 않을 것이다.
💎 리액트에서 map 메서드 사용할 때 key 값이 index면 안되는 이유
map 메서드를 사용하는 배열이 정렬 등으로 인해 변경된다거나, 요소가 추가되거나 삭제될 경우 문제가 발생할 수 있기 때문이다.
리액트는 map 메서드를 사용하여 동적으로 만든 배열 요소는 key 값을 가지고 추론을 한다.
즉, 추론한 key 값을 가지고 DOM을 새롭게 렌더링시키기 때문에 만약 순서가 보장되어있지 않은 요소에 key값을 index로 설정했다면, 예상한 대로 동작하지 않을 수 있을 뿐더러 성능에 문제가 발생할 수 있게 된다.
예를 들어, [아이유], [라일락], [블루밍] 이 순서대로 있다고 가정해보자.
const items = ['아이유', '라일락', '블루밍'];
{items.map((item, index) => (
<div key={index}>{item}</div>
))}
[아이유]가 인덱스 0, [라일락]이 1, [블루밍]이 2로 각각의 key는 index로 설정되어있다.
이제 특정 동작이 발생하여 items 배열의 첫 번째 요소인 [아이유]가 제거되었다고 가정해보자.
그러면 배열은 다음과 같은 형태로 변경될 것이고,
div 요소의 key 값이 현재 index로 설정되어 있으므로 [라일락]이 0번, [블루밍]이 1번 인덱스를 가지도록 변경된다.
const items = ['라일락', '블루밍'];
실제로 요소가 변경(삭제)된 것은 [아이유] 지만, 리액트는 key값을 가지고 변경 사항을 인지한다.
따라서 [라일락] 과 [블루밍] 은 변경되지 않았음에도 불구하고 리렌더링이 발생한다. (리렌더링이 발생할 필요가 없는 요소이다.)
이처럼 추가 또는 삭제될 여지가 있어서 순서가 보장되어 있지 않을 경우 index 키를 사용하게 되면 버그가 생길 수도 있으며, key 값이 변경됨으로 인해 변경사항이 없음에도 불구하고 불필요한 요소까지 리렌더링될 수 있다.
(요약) index를 key 값으로 사용 시 발생할 수 있는 문제점
1. index 값이 고유한 식별자임을 보장하지 않으므로 렌더링 성능에 영향이 있을 수 있음
2. 특정 요소를 추가/삭제 하는 로직이 있다면 원하는 대로 동작하지 않을 수 있음 (버그 발생 가능)
3. 변경이 없는 요소까지 리렌더링 시킬 수 있음 (1번과 비슷한 맥락. key의 index 값이 변경되는 애들 모두 리렌더링 돼서 해당 배열이 어마무시하게 클 경우 성능 이슈 있을듯)
따라서 리액트가 해당 요소를 정확히 식별하기 위해서 key를 사용하는 것이고,
성능 저하 및 원하지 않는 동작 발생을 막기 위해서 key값으로 index는 지양하는 것이 좋겠다.
참고 자료
'오늘의 개발' 카테고리의 다른 글
SSH fatal: Could not read from remote repository. 오류 해결하기 (0) | 2023.08.20 |
---|---|
판교 게임회사 인턴이 만든 첫 브랜드 사이트! 개발 후기 (0) | 2023.08.15 |
TDD 챌린지 3주 차 - 테스트코드 피드백 반영하기 (0) | 2023.06.18 |
TDD 챌린지 2주 차 - 썸네일 생성기 기능 구현 & cypress 테스트 코드 작성 (1) | 2023.06.04 |
TDD 챌린지 1주 차 미션 진행하기 - 핵심 기능 목록 구현과 테스트 명세 작성 (2) | 2023.05.25 |
댓글