[TIL] Reconciliation (재조정)

Solmin Seo·2021년 6월 14일
0

https://ko.reactjs.org/docs/reconciliation.html

React 만의 diff 알고리즘을 활용한 비교 후 rendering까지의 과정

리액트를 활용하여 개발을 할 때 "리액트는 SPA이고 변경 되는 컴포넌트만 변경이 된다" 정도만 알고있었고 어느 시점에서, 또는 어떤 정확한 기준에서 변경이 되는지 정확히 알지는 못했었다.

비교 알고리즘

React는 Real DOM 과 virtual DOM을 가지고 root에서부터 비교를 시작한다. 비교 알고리즘을 돌면서 각 태그를 검사한다.

Case 1

  • DOM 엘리먼트의 타입이 다른 경우 (파괴)
  • 두 루트 엘리먼트의 타입이 다르면, React는 이전 트리를 버리고 완전히 새로운 트리를 구축합니다.
    <div>
      <Counter />
    </div>

    // change to -> 

    <span>
      <Counter />
    </span>

Case 2

  • DOM 엘리먼트의 타입이 같은 경우 (갱신)

  • React는 현재 DOM 노드 상에 className만 수정합니다. (classNameattribute node 에 속해있습니다.)

    <div style={{color: 'red', fontWeight: 'bold'}} />
    
    <div style={{color: 'green', fontWeight: 'bold'}} 

자식에 대한 재귀적 처리

DOM 노드의 자식들을 재귀적으로 처리할 때, React는 기본적으로 동시에 두 리스트를 순회하고 차이점이 있으면 변경을 생성합니다.

Case 1

  • 기존 Dom 트리의 하위로 추가하는 경우
    <ul>
      <li>first</li>
      <li>second</li>
    </ul>

    <ul>
      <li>first</li>
      <li>second</li>
      **<li>third</li>**
    </ul>

React는 기존 트리에 하위로 추가 된 경우 first, second는 변경이 없고 third 만 추가 되었다 인식하여 third만 트리에 추가합니다.

Case 2

  • 기존 Dom 트리의 상위로 추가하는 경우
    <ul>
      <li>Duke</li>
      <li>Villanova</li>
    </ul>

    <ul>
      <li>Connecticut</li>
      <li>Duke</li>
      <li>Villanova</li>
    </ul>

위와 같이 마지막에 덧 붙히는 것 이 아닌 다른 위치에 변경이 발생되면 변경된 요소로 부터 트리를 파괴하고 다시 그리게 된다. 비효율적이다.

위와 같은 경우를 위해서 tag에 key 값을 추가 할 수 있다. 자식들이 key 를 가지고 있다면 위치와 상관없이 key를 우선 비교하여 realDOM 자식과 virtualDOM의 자식이 일치하는지 확인한다.

key는 전역으로 관리할 필요가 없이 형제 관계에서만 식별할 수 있으면 된다.

    <ul>
      <li key="11">Duke</li>
      <li key="12">Villanova</li>
    </ul>

    <ul>
      <li key="11">Connecticut</li>
      <li key="12">Duke</li>
      <li key="13">Villanova</li>
    </ul>

자주쓰는 코드 중 Array.map()에서 keyindex로 전달해주는 경우가 간혹 있는데, 해당 부분은 이미 eslint 에서도 막지만 마지막에 추가 되는 것이 아닌 다른 위치에 새로운 데이터가 추가되는 경우 key로 인해 버그가 생길 수도 있다.

    SampleArray.map((item, index) => <div key={index}>{item.name}</div>)

고려 사항

render의 결과물이 비슷한 컴포넌트들의 경우 타입을 유사하게 만들어 하나로 만드는것이 불필요한 DOM 노드의 재생성을 막을 수 있다.

key는 항상 변경되지 않고, 고유하며, 속해있는 자식 관계에서 유일해야합니다. Math.random()같이 변경되는 값을 사용하면 불필요한 DOM을 재생성하여 성능이 나빠질 수 있습니다.

profile
코린이

0개의 댓글