Virtual DOM

Heechang Jeong·2023년 5월 21일
0

브라우저의 렌더링 과정

브라우저는 렌더링 과정에서 DOM 트리와 CSSOM 트리를 토대로 Render 트리를 생성하고 각 요소가 배치될 공간을 계산(Layout)한 뒤 화면에 그려낸다.(Paint)

DOM이 변경되면 업데이트된 요소와 그에 해당하는 자식 요소들에 의해 DOM 트리를 재구축한다.
이 과정에서 변화가 필요 없는 부분도 변경되면서 잦은 리플로우 발생으로 인해 성능을 떨어뜨리는 문제가 발생한다.

DOM 조작이 많아질수록 이에 대한 리플로우가 발생하므로 DOM 업데이트 비용이 커진다.



Real DOM

Real DOM을 조작하는 경우, 변화가 필요하지 않은 요소도 변경될 수 있다.
예시로 많은 양의 DOM 조작이 이루어지는 경우 리플로우로 인한 비효율적인 업데이트가 자주 발생할 가능성이 있다.

"바뀐 부분만 비교해서 그 부분만 렌더링할 수 는 없을까?"

Virtual DOM

JavaScript 객체로 이루어진 가상의 DOM 트리를 사용하여, 실제 DOM 조작을 최소화하고 성능을 최적화하는 기술

가상 DOM은 실제 DOM과 동기화되어, 상태가 변경될 때마다 가상 DOM을 새로 생성하여 이전 상태와 비교한다. 그리고 변경이 필요한 부분만 실제 DOM에 반영하여 업데이트하므로, 전체 UI를 다시 그리지 않아도 된다.

가상 DOM 객체는 말 그대로 가상이기 때문에 비교를 위해 사용되며, 실제 DOM 객체처럼 화면에 표시되는 내용을 직접 변경하는 것은 아니다.

  • Virtual DOM의 동작 과정

    diffing 알고리즘을 통해 이전 상태와 현재 상태의 Virtual DOM을 비교한다.
    React에서 상태를 변경하는 경우에는 diffing 알고리즘에서 이를 감지할 수 있도록 직접 할당이 아닌 setState와 같은 메서드를 활용해 상태를 변경한다.

렌더링 과정에서 발생하는 비용이 크기 때문에, 가상 DOM을 활용하여 실제 DOM 조작을 최소화하는 것이 성능 최적화의 핵심!



비교 알고리즘(Diffing Algorithm)

  1. 각기 서로 다른 두 요소는 다른 트리를 구축할 것이다.
  2. 개발자가 제공하는 key 프로퍼티를 가지고, 여러 번 렌더링을 거쳐도 변경되지 말아야 하는 자식 요소가 무엇인지 알아낼 수 있을 것이다.
  • React가 DOM 트리를 탐색하는 방법

    트리의 레벨 순서대로 순회하는 방식으로 탐색
    = 같은 레벨(위치)끼리 비교한다는 뜻
    = BFS(너비 우선 탐색)

  • 자식 엘리먼트의 재귀적 처리

<ul>
  <li>first</li>
  <li>second</li>
</ul>

//자식 엘리먼트의 끝에 새로운 자식 엘리먼트를 추가했습니다.
<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

React는 위에서 아래로 순차적으로 비교하기 때문에, 이 동작 방식에 대해 고민하지 않고 리스트의 처음에 엘리먼트를 삽입하게 되면 이전의 코드에 비해 훨씬 나쁜 성능을 내게 된다.

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

//자식 엘리먼트를 처음에 추가합니다.
<ul>
  <li>Connecticut</li>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

자식 노드가 서로 다르다고 인지하게 된 React는 리스트 전체가 바뀌었다고 받아들인다.
즉, 새롭게 렌더링을 하며 굉장히 비효율적인 동작 방식이다.
그래서 React는 이 문제를 해결하기 위해 key라는 속성을 지원한다.

0개의 댓글