DOM 노드의 자식들을 재귀적으로 처리할 때, React는 기본적으로 동시에 두 리스트를 순회하고 차이점이 있으면 변경을 생성한다.
<ul>
<li>🍎</li>
<li>🍌</li>
</ul>
<ul>
<li>🍎</li>
<li>🍌</li>
<li>🥕</li>
</ul>
위 예시와 같이 ul 태그 자식으로 끝에 <li>🥕</li>를 추가하는 변경이 있을 경우 <li>🍎</li>, <li>🍌</li>가 일치하는 것을 확인하고, 마지막으로 <li>🥕</li>를 트리에 추가한다.
하지만, 리스트의 맨 앞에 엘리먼트를 추가하는 경우 큰 비효율이 발생한다.
<ul>
<li>🍎</li>
<li>🍌</li>
</ul>
<ul>
<li>🥕</li>
<li>🍎</li>
<li>🍌</li>
</ul>
위 예시와 같이 ul 태그 자식으로 맨 앞에 <li>🥕</li>를 추가하는 변경이 있을 경우 <li>🍎</li>, <li>🍌</li>가 일치함에도 불구하고, 모든 자식을 변경한다. 자식의 개수가 2~3개가 아닌 수백 수천개가 있고, 자식의 요소가 복잡하다면 이러한 비효율은 문제가 될 수 있다.
이러한 비효율의 문제를 해결하기 위해, React는 key 속성을 지원한다. 자식들이 key를 가지고 있다면, React는 key를 통해 기존 트리와 이후 트리의 자식들이 일치하는지 확인한다.
key는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕는다. key는 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정해야 한다.
key는 리스트의 다른 항목들 사이에서 해당 항목을 고유하게 식별할 수 있는 문자열을 사용하는 것이 가장 좋다. 대부분의 경우 데이터의 id를 key로 사용한다.
key를 잘 선택하면 React가 정확히 무슨 일이 일어났는지 추론하고 DOM 트리에 올바르게 업데이트 하는데 도움이 된다.
데이터 소스마다 다른 key 소스를 제공한다.
배열의 map 메소드를 사용하다보면 인덱스를 key로 사용하기 쉬운데, 이 경우 배열이 재배열되면 배열 내부의 엘리먼트에 해당하는 key 값 또한 바뀐다. 컴포넌트는 key를 기반으로 갱신되고 재사용되기 때문에 컴포넌트의 key 값이 바뀌면서 컴포넌트의 state가 꼬이거나 의도하지 않은 방식으로 바뀌는 문제가 발생할 수 있다.
위 세 가지 요건을 모두 만족할 때, 최후의 수단으로 항목의 인덱스를 key로 사용할 수 있다. 그렇지 않은 경우에는 인덱스를 사용하지 않는 것이 좋다.
참조