DOM이란 Document Object Model의 약자로, 문서 객체 모델을 말한다. 웹 페이지에 나타나는 HTML 문서 전체를 객체로 표현한 것으로 생각하면 된다. 이때 각 객체를 노드(Node)라는 용어로 표현하고, 태그는 요소 노드, 문자는 텍스트 노드로 구분된다.
HTML의 계층 구조는 DOM에서도 반영되는데 이러한 계층구조를 나무에 비유해서 DOM 트리라고 부른다. 각 노드 간의 관계는 부모, 자식, 형제라는 용어로 표현한다.
Virtual DOM (VDOM)은 UI의 이상적인 또는 “가상”적인 표현을 메모리에 저장하고 ReactDOM과 같은 라이브러리에 의해 “실제” DOM과 동기화하는 프로그래밍 개념이다. 이 과정을 재조정(Reconciliation)이라고 한다.
이 접근방식이 React의 선언적 API를 가능하게 한다. React에게 원하는 UI의 상태를 알려주면 DOM이 그 상태와 일치하도록 한다. 이러한 방식은 앱 구축에 사용해야 하는 어트리뷰트 조작, 이벤트 처리, 수동 DOM 업데이트를 추상화한다.
virtual DOM은 특정 기술이라기보다는 패턴에 가깝기 때문에 사람들마다 의미하는 바가 다르다. React의 세계에서 “virtual DOM”이라는 용어는 보통 사용자 인터페이스를 나타내는 객체이기 때문에 React elements와 연관된다.
기존 웹페이지에서 서버와 통신하며 요청을 주고 받으면, 받은 데이터를 DOM 객체에 속성값들을 변화시키거나 DOM을 추가 또는 제거하도록 만들었다. 그리고 이러한 변경이 있을 때마다 DOM 객체의 변경에 대한 코드를 만들어줘야 했다. 뿐만 아니라 DOM 객체에 대한 연산이 많아질수록 reflow, repaint 연산이 많아지면서 브라우저가 컴퓨팅 자원을 많이 사용해야 했다.
reflow란 화면구조가 변경되었을 때 문서의 일부 또는 전체를 다시 렌더링하기 위해 문서에서 요소의 위치와 크기등의 형상을 다시 계산하는 것을 의미한다. 대표적으로 화면의 크기 변화, 페이지 초기 렌더링, DOM의 동적 변화가 있는 경우 reflow가 발생한다. 또한 경우에 따라서 문서의 단일 요소를 reflow하려면 상위 요소와 그 뒤에 오는 모든 요소를 reflow해야 할 수 도 있다.
repaint란 요소의 보이는 것에 영향을 주지만 레이아웃에는 영향을 주지 않는 요소 변경으로 화면에 다시 그려주는 작업이다. reflow가 발생하면 변경된 렌더 트리를 화면에 다시 그려야해서 repaint가 발생한다. 또한 레이아웃에 영향을 주지 않지만 color, background-color, visibility 등과 같은 스타일 속성의 변경에는 reflow는 발생하지 않고, repaint만 발생한다.
reflow, repaint가 많이 일어날수록 하드웨어에 많은 부담을 주게 되고, 그 결과 사용자 경험이 나빠질 수 있다.
이를 해결하기 위해 리액트는 Virtual DOM을 활용해 UI의 이상적인 “가상”적인 표현을 메모리에 저장하고 ReactDOM과 같은 라이브러리에 의해 “실제” DOM과 동기화 한다. 이 과정을 재조정(Reconciliation)이라고 한다.
이렇게 연산이 끝난 뒤 최종적인 변화를 실제 DOM에 반영해서 여러 번 reflow, repaint가 발생할 수 있는 작업을 한번으로 줄여준다. 또한, Virtual DOM은 변화에 대한 관리를 자동화하고 추상화해서 작업의 편의성을 제공한다.
Virtual DOM은 메모리 상에서만 동작하며, 실제 DOM 조작을 최소화하여 성능을 향상시키게 된다. 변경된 부분만 실제 DOM에 적용함으로써 렌더링 성능을 향상시킨다.
Virtual DOM은 상태 변화를 추적하고, 적절한 타이밍에 변경 사항을 적용함으로써 렌더링 일관성을 유지하게 된다.
비교적 규모가 큰 애플리케이션에서 UI를 관리하기 위해 컴포넌트 기반 아키텍처를 사용하게 되는데, Virtual DOM은 이를 가장 효과적, 효율적으로 관리할 수 있게 해준다.
Virtual DOM은 브라우저 독립적인 방식으로 동작하므로, React Native와 같은 플랫폼에서도 활용될 수 있다.
다른 기술과 함께 사용할 수 있으며, 다양한 환경에서 렌더링 할 수 있도록 해준다.
Virtual DOM은 메모리 상에 DOM과 완전히 동일한 구조의 메모리를 유지하게 되기 때문에 추가적인 메모리를 사용하게 된다.
개발자가 애플리케이션의 뷰(View)와 상태(State)를 동기화하기 위해 추가적인 추상화 계층을 사용해야 한다. 이로 인해 애플리케이션의 복잡성이 증가할 수 있다.
모든 상황에 완벽하게 적합하지 않을 수 있다. 정말 간단한 UI나 작은 규모의 애플리케이션에서는 불필요한 오버헤드일 수 있다.