오늘은 React의 Virtual DOM과 관련된 Reconciliation(재조정) 과정에 대해 알아보고, 이를 토대로 key에 index를 사용하면 안되는 이유까지 알아보겠습니다.

 

React가 DOM 트리를 재구성하는 방법

리액트에서는 Reconcilitation (재조정) 과정을 통해, Actual DOMVirtual DOM의 Diff(차이점)만을 알아내서 새로운 DOM을 리렌더링 과정을 수행합니다.

 

이는, 모든 노드를 렌더링하지 않고 바뀐 State 노드만 변경하여 렌더링 최적화를 이룬 것이라고 볼 수 있습니다.

 

재조정 과정

 

Reconciliation 과정은 총 2단계로 이루어집니다.

  1. Reconciler→ React 내부의 Diffing Algorithm을 사용하여 바뀐 점을 알아낸다.
    • Diffing Algorithm React에서는 O(N3)의 비효율적인 diffing-algorithm을 개선하였다. AI에서 자주 사용하는 Heuristic O(n) 알고리즘을 사용하였다.
    • Current 트리와 작업 중(Work in Progress) 트리의 차이점을 발견하는 역할을 한다.
  2. Renderer
    • Reconciler로부터 전달받은 Diff를 토대로, Current 트리를 바꾸는 역할을 수행한다.

위에서, React의 Reconciler diffing-algorithm은 Heruistic 알고리즘을 사용하여 DOM간의 차이점을 발견하다고 언급하였습니다.

 

바로 이때, key 값이 변경된 사항을 판단하는 용도로 사용됩니다.

 

key값을 index로 사용하면 안되는 이유

React는 특정 노드의 자식들을 재귀적 처리할 때, 두 리스트의 차이점을 순회하여 차이점이 발견되면 이를 반영합니다.

이때, 아닌 key값을 토대로 노드를 비교 · 식별하는 것입니다.

리액트가 바뀐 점을 식별하는 가정 2가지

  1. 타입 (HTML Element)이 다른 두 엘리멘트는 서로 다른 트리를 만들어 낸다.
  2. 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를 사용해야 한다면, 변하지 않는 정적 데이터에만 사용하여 의도치않은 오류를 방지해야 합니다.

+ Recent posts