오늘은 React의 Virtual DOM과 관련된 Reconciliation(재조정) 과정에 대해 알아보고, 이를 토대로 key에 index를 사용하면 안되는 이유까지 알아보겠습니다.
React가 DOM 트리를 재구성하는 방법
리액트에서는 Reconcilitation (재조정) 과정을 통해, Actual DOM 과 Virtual DOM의 Diff(차이점)만을 알아내서 새로운 DOM을 리렌더링 과정을 수행합니다.
이는, 모든 노드를 렌더링하지 않고 바뀐 State 노드만 변경하여 렌더링 최적화를 이룬 것이라고 볼 수 있습니다.

Reconciliation 과정은 총 2단계로 이루어집니다.
- Reconciler→ React 내부의 Diffing Algorithm을 사용하여 바뀐 점을 알아낸다.
- Diffing Algorithm React에서는 O(N3)의 비효율적인 diffing-algorithm을 개선하였다. AI에서 자주 사용하는 Heuristic O(n) 알고리즘을 사용하였다.
- Current 트리와 작업 중(Work in Progress) 트리의 차이점을 발견하는 역할을 한다.
- Renderer
- Reconciler로부터 전달받은 Diff를 토대로, Current 트리를 바꾸는 역할을 수행한다.
위에서, React의 Reconciler diffing-algorithm은 Heruistic 알고리즘을 사용하여 DOM간의 차이점을 발견하다고 언급하였습니다.
바로 이때, key 값이 변경된 사항을 판단하는 용도로 사용됩니다.
key값을 index로 사용하면 안되는 이유
React는 특정 노드의 자식들을 재귀적 처리할 때, 두 리스트의 차이점을 순회하여 차이점이 발견되면 이를 반영합니다.
이때, 아닌 key값을 토대로 노드를 비교 · 식별하는 것입니다.
리액트가 바뀐 점을 식별하는 가정 2가지
- 타입 (HTML Element)이 다른 두 엘리멘트는 서로 다른 트리를 만들어 낸다.
- key를 통해 어떤 자식 엘리먼트가 변경되지 말아야 할지 표시해 준다.
아래와 같은 코드가 있다고 가정해보겠습니다.
// Index를 Key로 사용
<ul>
<li key="0">first</li>
<li key="1">second</li>
<li key="2">third</li>
</ul>
만약, 개발자가 가운데 second 를 가진 List Element를 삭제하는 버튼을 눌렀다고 가정해보겠습니다.
아래와 같이 되기를 기대할 것입니다
// Index를 Key로 사용
<ul>
<li key="0">first</li>
<li key="1">third</li>
</ul>
하지만, 실제로는 아래와 같이 됩니다.
// Index를 Key로 사용
<ul>
<li key="0">first</li>
<li key="1">Second</li>
</ul>
이를 자세히 살펴보겠습니다.
아래와 같이 기존 DOM에서 key = “1” 에 해당하는 list를 삭제하면 State-Changed Virtual DOM이 탄생합니다.
이때, 바뀐 배열로 인해 key 값은 third가 key = “1”을 차지하게 됨을 명심하세요.
이후, Reconciler는 key값을 토대로 바뀐 Element는 무엇인지 판단한다.
key = “2” 가 사라졌으므로, Reconciler는 “key = “2”를 빼고 렌더링하면 되겠다” 고 Renderer로 전달하여 Renderer는 이를 렌더링합니다.
// 기존 DOM
<ul>
<li key="0">first</li>
<li key="1">second</li>
<li key="2">third</li>
</ul>
// State-Changed Virtual DOM
<ul>
<li key="0">first</li>
<li key="1">third</li>
</ul>
key에 올바른 값을 사용하기
많은 개발자들이 염두하고 있듯이 key 값에는 값을 구분할 수 있는 고유의 값을 사용해야 합니다.
서버에서 제공받는 데이터라면, 대부분 id 값을 토대로 구분할 수 있다.
혹여나 index를 사용해야 한다면, 변하지 않는 정적 데이터에만 사용하여 의도치않은 오류를 방지해야 합니다.