Virtual DOM을 사용하는 이유

가상 돔을 왜 쓸까? => 리얼 돔이 비효율적이기 때문에

애초에 DOM은 서버에 의해 렌더링되는 정적인 UI를 염두에 두고 설계되었다. 리얼 돔에서 다음과 같은 스크립트를 통해 DOM에 변경을 가하는 경우를 보자.

document.getElementById('elementId').innerHTML = "New Value"
  1. 브라우저가 HTML을 파싱
  2. elementId의 child element 제거
  3. DOM을 New Value로 업데이트
  4. 부모, 자식 노드의 CSS를 재계산
  5. 레이아웃 업데이트
  6. 렌더 트리를 다시 생성하고 브라우저 디스플레이에 페인트

돔 트리를 다시 그리는 것 외에도 이와 같은 과정이 수반되기 때문에 현대의 웹사이트처럼 사용자와의 잦은 인터렉션이 수반되는 환경에서는 리얼 돔의 조작은 속도의 저하를 불러오게 된다.

변화가 일어날 때마다 돔을 재생성하지 않고 변화가 일어난 곳만 업데이트 한다면?

  • 더티 체킹(Dirth Checking,AngularJS 1 버젼에 사용됨) — 일정 간격마다 노드를 훑으면서 변화가 일어났는지 아닌지 판단한다. 모든 노드를 훑어야하기 때문에 비효율적이라고 간주된다.
  • 오브저버블(Observable, 리액트에 사용됨) — ‘상태’가 존재하여 업데이트가 발생하면 컴포넌트가 이벤트를 통해 이를 알아차린다. 그리고 UI를 리렌더한다.

Virtual DOM

가상 돔은 리얼 DOM의 한결 추상화된 버젼이다. 리얼 돔에 영향을 주지 않고 업데이트 될 수 있다. 매번 렌더링이 될 때마다 새로 그려지며 순수한 js파일로 가볍기 때문에 속도와 효율 면에서 우월하다.

리액트에서 가상 돔이 작동하는 방법

  • 처음 로드가 시작될 때 ReactDOM.render() 가 가상돔 트리와 리얼돔 트리를 형성한다.
  • 오브저버블 패턴에 의해 이벤트가 발생하면 가상돔 트리의 노드가 props 변화를 알아차리게 되고 변화가 발생한 노드들에 한해 업데이트가 진행된다.
  • 리액트의 ReactDOM 라이브러리가 업데이트된 가상돔 업데이트 이전 가상돔을 비교하고 업데이트된 요소들을 파악한다. 이러한 과정을 diffing이라고 한다. 그리고 변경된 사항이 있다면 이를 리얼돔에 반영한다. 이러한 프로세스를 재조정Reconciliation이라고 일컫는다. diffing과정에서 두 돔 사이의 변화가 없다면 DOM 조작을 일어나지 않는다.
  • 업데이트된 리얼돔이 브라우저에 페인트된다.

참고: https://medium.com/devinder/react-virtual-dom-vs-real-dom-23749ff7adc9