In React, displaying 1000 elements would require in the order of one billion comparisons. This is far too expensive. Instead, React implements a heuristic O(n) algorithm based on two assumptions:
1. Two elements of different types will produce different trees.
2. The developer can hint at which child elements may be stable across different renders with a key prop.
리액트 공식 문서에 나와있는 Diffing Algorithm에 대한 설명이다.
요소를 일일히 하나하나 바꾸다보면 수없이 많은 비교가 이루어져야하고, 이 작업이 굉장히 무겁다.
그래서 리액트는 두 개의 돔 트리(Virtual DOM tree)가 나온다는 점과 모든 개발자들이 key props를 통해 바뀌었다는 것을 명시할 수 있다는 점으로 해당 문제를 해결하고자 했다.
리액트는 기존의 가상 톰 트리와 새롭게 변경된 가상 돔 트리를 비교할 때, 트리의 레벨 순서대로 순회하는 방식으로 탐색한다. 즉, 같은 위치끼리 비교한다는 뜻이다.
동일선상에 있는 노드를 파악한 뒤 다음 자식의 노드를 순차적으로 파악한다.
<div>
<Counter/>
</div>
// 부모 태그가 div >> span 으로 변경
<span>
<Counter/>
</span>
돔 트리는 각 html 태그마다 각각의 규칙이 존재해 그 아래 들어가는 자식 태그가 한정적이라는 특징이 있다.
(예를 들어, <ul>
태그 안에는 <li>
태그만 존재할 수 있다, <p>
태그 안에는 <p>
태그가 존재하지 못한다. 등등)
자식 태그의 부모 태그 또한 정해져 있다는 특징이 있기 때문에, 부모 태그가 달라지게 된다면, 리액트는 이전의 트리를 버리고 새로운 트리를 구축한다.
<div className="before" title="stuff" />
// 기존 엘리먼트의 태그는 유지, className만 변경
<div className="after" title="stuff" />
반대로 타입이 바뀌지 않는다면 리액트는 최대한 렌더링을 하지 않는 방향으로, 최소한의 변경사항만 업데이트하게 된다.
업데이트할 내용이 생기게 되면 Virtual DOM 내부의 Props만 수정하게 되고, 모든 노드에 걸쳐 업데이트가 끝나면 그 때 실제 DOM의 렌더링을 시도하게 된다.