document에 작성한 html파일은 웹에 표현되기 전까지 string에 불과하다. 이 string을 브라우저가 읽고 해석하기 위해 객체형태인 노드 트리 DOM으로 표현되어야 한다.
또한, DOM은 자바스크립트로에서 노드를 변경하고 이벤트 처리를 가능하게 해주는 API를 제공해준다. (createElement, removeElement, appendChild, addEventListener 등)
즉, HTML과 자바스크립트가 서로 소통할 수 있도록 객체로 변환된 것이 DOM이다.
(Document Object Model)
이유가 무엇일까 ?
DOM이 브라우저에 동작되기까지 과정을 간단하게 훑어보면...
HTML파일을 파싱 => DOM 트리 생성
CSS파일 파싱=>CSSOM 생성
DOM에 CSSOM의 확장된 스타일을 반영해 렌더트리 생성
페이지 레이아웃이 반영된 레이아웃 트리 생성(reflow)
페인팅(화면 출력)
화면의 DOM이 수정될 때마다 브라우저는 전체 DOM트리의 변경사항을 수정하며
처음부터 위의 작업을 반복해야한다. (글자하나, 위치px 하나 모두 계산해야하므로 비용이 큰 작업이다.) 작은 변화에도 처음부터 동일한 작업을 반복하는 것이 비효율적이고 페이지의 규모가 커질 수록 렌더링의 부담이 커져 VirtualDOM이 이를 해결하게 되었다.
사진에서 이해할 수 있듯, VirtualDOM이 있고 RealDOM이 있다.
버츄얼 돔은 말 그대로 '가상돔'인데 html에서 실제로 변경된 사항을 렌더링하지 않는 가상돔과 비교하여 차이점을 파악하고 해당 차이점만 실제 돔에 전달하여 해당부분만 변경되도록 하는 방법이다.
(diff 알고리즘
을 사용하고 Reconciliation
작업이라고 한다.)
직접 DOM에 접근하여 속성을 변경하는 것이 DOM트리생성부터 페인팅 작업까지 모두 반복하기 때문에 고 비용이 드는 작업이라고 했었다. 하지만 이와 같은 고비용작업이 DOM을 변경하지 않아도 발생될 때가 있는데 이런 상황을 강제동기레이아웃
이라고 한다. 예를들면, DOM엘리먼트 속성을 읽기만해도 처음부터 렌더링작업을 하게 된다. 그리고 이 강제동기 레이아웃이 고반복되어 렌더링이 매우 빈번하게 발생하는 경우를 레이아웃 스레싱
이라고 한다.
이를 피하는 방법은 DOM에 접근하는 값을 캐싱하여 사용하는 것이다.
// bad
document.getElementById('my').style.top = "10px";
document.getElementById('my').style.left = "10px";
document.getElementById('my').style.color = "#dad";
// better
var mysty = document.getElementById('my').style;
mysty.top = "10px";
mysty.left = "20px";
mysty.color = "#dad";
// better
var csstext = "; top: 10px; left: 10px; color: #dad;";
document.getElementById('my').style.cssText += csstext
Mitigating the problem - don't touch the DOM
레이아웃스레싱을 초래하는 css속성들
리액트가 이 가상돔을 적용하고 있는데,
직접 엘리먼트를 지정하고 상태값, 스타일 값 변경을 명시하지 않아도
상태가 변경되면 알아서 바뀐 엘리먼트만 변경되니 사용상의 편리한 장점과 렌더링이 작게 일어나 전체 화면의 깜빡거림(렌더링)이 일어나지 않는다 장점이 있다.