본 글은 원문을 번역한 벨로퍼트님의 글을 참고했습니다.
VirtualDOM을 이해하기 위해서, 브라우저의 워크 플로우가 어떻게 이루어지는지 살펴보고 DOM 조작 후 어떤일이 일어나는지 알아보자.
브라우저가 HTML을 전달받으면, 브라우저의 렌더 엔진이 이를 파싱하고 DOM노드(Node)로 이뤄진 트리를 만든다. 각 노드는 각 HTML 엘리먼트들과 연관되어 있다.
그리고, 외부 CSS파일과 각 엘리먼트의 inLine스타일을 파싱한다. 스타일 정보를 사용해 DOM트리에 따라 새로운 트리, 렌더트리를 만든다.
webkit에서는 노드의 스타일을 처리하는 과정을 attachment라고 부른다. DOM트리의 모든 노드들을 attach라는 메소드가 있다. 이 메소드는 스타일 정보를 계산해서 객체형태로 반환한다.
이 과정을 동기적(synchronous) 작업이다. DOM트리에 새로운 노드가 추가되면 그 노드의 attach 메소드가 실행된다.
렌더트리를 만드는 과정에서 각 요소들의 스타일이 계산이 되고, 이렇게 계산되는 과정에서 다른 요소들의 스타일 속성들을 참조한다.
렌더 트리가 다 만들어지고 나면, 레이아웃 과정을 거친다. 각 노드들은 스크린의 좌표가 주어지고 정확히 어디에 나타나야 할지 위치가 주어진다.
그 다음 작업은 렌더링된 요소들에 색을 입히는 과정이다. 트리의 각 노드들을 거쳐가면서 Paint()메소드를 호출한다. 그러고나면, 스크린에 원하는 정보가 나타난다.
DOM에 변화생기면, 렌더트리를 재생성하고 (모든 요소들의 스타일이 다시 계산된다) 레이아웃을 만들고 페인팅을 하는 과정이 다시 반복된다.
DOM조작의 실제 문제는 각 조작이 레이아웃 변화, 트리 변화와 렌더링을 일으킨다는 것이다. 그래서 예를 들어 30개의 노드를 하나 하나 수정하면, 그 뜻은 30번의 (잠재적인) 레이아웃 재계산과 30번의(잠재적인) 리랜더링을 초래한다는 것이다.
복잡한 SPA(싱글 페이지 어플리케이션)에서는 DOM 조작이 많이 발생한다. 그 뜻은 그 변화를 적용하기 위해 브라우저가 많이 연산을 해야하고, 전체적인 프로세스를 비효율적으로 만든다.
Virtual DOM은 뷰에 변화가 있다면, 그 변화는 실제 DOM에 적용되기 전에 가상의 DOM에 먼저 적요시키고 그 최종적인 결과를 실제 DOM으로 전달해준다. 이로써, 브라우저 내에서 발생하는 연산의 양을 줄이면서 성능이 개선되는 것이다.
Virtual DOM은 변화가 일어나면 그걸 오프라인 DOM 트리에 적용시킨다. 이 DOM 트리는 렌더링도 되지 않고, 연산이 끝나고 나면 최종적인 변화를 실제 DOM에 던져준다.
모든 변화를 하나로 묶기 때문에 레이아웃 계산과 리렌더링의 규모는 커지겠지만, 딱 한번만 일어나기 때문에 연산의 횟수를 줄여준다.
Virtual DOMdms DOM fragment를 관리하는 과정을 수동으로 하나하나 작업할 필요 없이, 자동화하고 추상화해준다. 어떤게 바뀌었는지, 어떤게 바뀌지 않았는게 알아내주는 편리함이 있다.