먼저 DOM이란 무엇일까
프론트엔드 공부를 하다보면 DOM이라는 말을 꾸준히 듣게 되는 것 같은데 이 기회에 제대로 짚고 넘어가면 좋을 것 같다.
DOM(Document Object Model)은 웹페이지(HTML, XML 등)의 구조를 프로그래밍 언어가 접근하고 조작할 수 있도록 객체 기반으로 표현하는 모델이다.
모든 서비스는 웹 브라우저를 바탕으로 실행되는데 이 브라우저와 관련된 객체들의 집합을 브라우저 객체 모델(BOM: Browser Object Model)이라고 한다. BOM을 이용해서 Browser와 관련된 기능들을 구성한다. DOM은 BOM중 하나이다.
DOM에서 Document Object, 즉 문서 객체는 무엇일까? 문서 객체란 이나 같은 html 문서의 태그들을 JavaScript가 이용할 수 있는 객체(object)로 만들면 그것을 문서 객체라고 한다.
결국 DOM은 넓은 의미로 웹 브라우저가 HTML 페이지를 인식하는 방법을 의미하고, 좁은 의미로는 document 객체와 관련된 객체의 집합을 의미할 수도 있다.

DOM은 위와 같이 트리 형태의 자료구조로 나타난다.
문서 객체가 생성되는 방식은 두 가지가 있다.
웹 브라우저가 HTML 페이지에 적혀있는 태그를 읽으면 생성하는 것이다. 이런 과정을 저적으로 문서 객체를 생성한다고 말한다. 단순히 적혀져 있는 그대로 문서 객체가 생성되는 것을 표현한 것이다.
반대로 원래 HTML 페이지에 없던 문서 객체를 JavaScript를 이용해서 생성할 수 있다. 이런 과정을 동적으로 문서 객체를 생성한다고 한다. 따라서 JavaScript로 문서 객체를 생성한다는 것은 처음에는 HTML 페이지에 없던 문서 객체를 동적으로 생성하는 것이 된다.
아래 코드는 JavaScript를 사용해서 동적으로 문서 객체를 생성하는 예시이다.
<!DOCTYPE html>
<html>
<head>
<title>동적 DOM 생성 예제</title>
</head>
<body>
<h1>JavaScript 동적 요소 생성</h1>
<button id="addBtn">문단 추가</button>
<div id="container"></div>
<script>
const button = document.getElementById('addBtn');
button.addEventListener('click', () => {
const newParagraph = document.createElement('p');
newParagraph.textContent = '이것은 동적으로 추가된 문단입니다.';
newParagraph.style.color = 'blue';
newParagraph.style.fontWeight = 'bold';
const container = document.getElementById('container');
container.appendChild(newParagraph);
});
</script>
</body>
</html>
실행 결과
여기에서 JavaScript를 통해 동적으로 문서 객체를 생성해보자
var header = document.createElement('h2');
document 객체에 접근해서 'h2' 태그 생성
var textNode = document.createTextNode('Hello DOM');
document 객체에 접근해서 Textnode를 생성하고 ‘Hello DOM’ 이라는 스트링을 넣음
header.appendChild(textNode);
생성한 'h2' 태그에 자식 노드를 추가
document.body.appendChild(header);
이제 document 객체를 통해서 boby 객체에 접근
Virtual DOM은 React에서 사용되는 핵심 개념으로, 실제 DOM을 JS 객체 형태로 복제한 가벼운 사본이라고 할 수 있다. 브라우저의 DOM은 구조적으로 복잡하고, 이를 직접 조작하는 작업은 성능 비용이 상당히 높다. Virtual DOM은 이를 개선하여 웹 애플리케이션의 성능을 최적화하기 위해 등장했다.
Virtual DOM의 핵심 아이디어는 상태 변경이 발생할 때 마다 전체 UI를 Virtual DOM에 반영하고, 이를 이전 상태와 비교하여 필요한 부분에 한해서 최소한의 DOM 업데이트를 수행하는 것이다. Virtual DOM을 업데이트하고 비교하는 일은 실제 DOM을 조작하지 않고 메모리 상에서 업데이트와 비교가 이루어지기 때문에 가볍고 빠르게 수행된다.
React에서 Virtual DOM이 활용되는 구체적인 과정은 다음과 같다
Virtual DOM은 이처럼 DOM 업데이트의 비용을 줄이고, 브라우저 렌더링 성능을 개선한다.
React는 O(n³)의 복잡도를 가질 수 있는 트리 비교 문제를, 휴리스틱을 통해 O(n)으로 최적화했다.
휴리스틱 알고리즘은 크게 두 가지 가정을 두고 있다.
DOM 요소의 타입이 다르면(ex. <div> → <span>) 비교를 수행하지 않고, 해당 요소와 그 자식들을 모두 새로 생성한다. 자식 요소들의 내용이 같더라도 이전의 트리를 모두 버리고 완전히 새로 만든다.
이는 비효율적으로 보일 수 있지만, 실제 애플리케이션에서 타입이 다른 경우는 보통 완전히 다른 컴포넌트로 교체되는 상황이 많기 때문에 이 가정이 대부분의 경우 효율적이다.
만약 동일한 타입의 요소라면, 동일한 내역은 유지하고 변경된 속성만 갱신힌다.
<div className="before" title="stuff" /><div className="after" title="stuff" />
예를 들어, 이 예시에서는 className만 수정한다.
같은 레벨의 자식들을 비교할 때 개발자가 입력한 key prop을 사용하여 요소를 식별한다. 이를 통해 리스트 내역의 일부가 수정됐을 때 모든 아이템 요소들을 불필요하게 갱신하지 않고, 실제 변경된 요소만 감지하여 효율적으로 갱신한다.
동적으로 작동한다는게 필요한 부분만 고친다는 말인가?
DOM은 이벤트가 발생했을 때 페이지 전체를 다시 그려야해서 비효율적이다. 그래서 나온게 Virtual DOM이고 이 Virtual DOM은 바뀐 부분에 대해서만 다시 그려서 띄운다는 것 같다.
DOM이 중요한 이유?
Virtual DOM의 작동 방식 (React 기준)