티스토리 뷰

안녕하세요, WoodyCode입니다. 🚀

 

지난 포스팅에서 우리는 브라우저와 서버가 대화하는 언어, HTTP에 대해 알아봤습니다. 서버에서 HTML 데이터를 성공적으로 가져왔다면, 이제 브라우저는 그 텍스트를 바탕으로 사용자가 볼 화면을 구성해야 합니다.

이 과정에서 가장 핵심적인 역할을 하는 것이 바로 DOM(Document Object Model)입니다.

"React는 가상 DOM을 써서 빠르다", "Svelte는 가상 DOM이 없어서 더 빠르다"는 논쟁의 중심에는 항상 이 DOM이 있습니다. 도대체 DOM이 무엇이길래 현대 프레임워크들이 이를 두고 성능 전쟁을 벌이는지, 그 속사정을 낱낱이 파헤쳐 보겠습니다.


1. DOM, HTML을 나무(Tree)로 바꾸다

브라우저는 HTML 텍스트를 그대로 화면에 그릴 수 없습니다. 자바스크립트가 이해하고 조작할 수 있는 형태(객체)로 변환해야 하죠.

 

1️⃣ DOM의 정의: HTML의 객체 모델

DOM은 브라우저가 HTML 문서를 트리 구조로 추상화한 것입니다. 각 HTML 태그는 이 트리의 노드(Node)가 되고, 자바스크립트는 이 노드들을 자유롭게 읽고, 수정하고, 삭제하며 화면을 동적으로 변화시킵니다.

HTML

<html>
  <body>
    <h1>안녕하세요!</h1>
    <p>WoodyCode입니다.</p>
  </body>
</html>
HTML 요소 DOM 노드 비유 WoodyCode 인사이트
<html> 뿌리(Root) 전체 DOM 트리의 시작점입니다.
<body>, <h1>, <p> 가지(Element Node) 화면의 골격을 구성하는 노드들입니다.
"안녕하세요!", "WoodyCode입니다." 잎(Text Node) 실제 화면에 표시되는 텍스트 노드입니다.

2. 왜 가상 DOM(Virtual DOM)이 필요했을까?

바닐라 JS로 DOM을 직접 조작하는 것은 직관적이지만, 대규모 서비스에서는 성능 면에서 치명적인 약점이 있습니다. 바로 DOM 조작 비용이 매우 비싸다는 것입니다.

 

1️⃣ 성능 저하의 주범: Reflow와 Repaint

브라우저가 DOM 트리를 수정할 때마다 화면을 다시 그리는 과정이 발생합니다.

  • Reflow: 레이아웃(위치, 크기)을 다시 계산하는 과정입니다. 매우 비싼 연산입니다.
  • Repaint: 변경된 레이아웃을 바탕으로 픽셀을 다시 칠하는 과정입니다.
👉 만약 수십 개의 데이터를 한 번에 업데이트하면서 각 데이터를 DOM에 직접 반영하면, 브라우저는 수십 번의 Reflow/Repaint를 수행하며 화면이 끊기는 현상을 발생시킵니다.

 

 

2️⃣ 가상 DOM: 영리한 업데이트 방식

이 문제를 해결하기 위해 React 같은 프레임워크가 들고 나온 것이 가상 DOM입니다.

가상 DOM은 실제 DOM의 가벼운 복사본입니다. 자바스크립트 객체 형태로 메모리에 존재하죠. 성능 저하 없이 빠르게 수정할 수 있습니다.

  1. 데이터 변경: 상태(State)가 변경됩니다.
  2. 새로운 가상 DOM 생성: 변경된 데이터가 반영된 새로운 가상 DOM 트리를 메모리에 그립니다.
  3. Diffing (비교): 이전 가상 DOM과 새로운 가상 DOM을 비교하여, '진짜' 변경된 부분만 찾아냅니다.
  4. Batch Update (일괄 업데이트): 찾아낸 변경 사항을 한 번에 묶어서 실제 DOM에 반영합니다. (딱 한 번의 Reflow/Repaint 유도)

 

3.[실무 전략] DOM 조작 성능 최적화

우리가 프레임워크를 쓰든 쓰지 않든, DOM 조작 성능을 최적화하는 전략은 동일합니다. 프레임워크는 이 전략을 우리 대신 자동으로 수행해 줄 뿐입니다.

전략 최적화 방법 ❌ 지양해야 할 태도
Reflow/Repaint 최소화 DOM 수정 횟수를 줄입니다. 여러 변경 사항을 한 번에 반영합니다. (Batching) 루프 돌면서 하나씩 DOM 수정하기
레이아웃 정보 읽기/쓰기 분리 레이아웃 정보를 읽는 연산(offsetTop, offsetWidth 등)은 Reflow를 유발합니다. 읽기와 쓰기 연산을 한 데 묶지 마세요. 레이아웃 정보 읽고 바로 DOM 수정하기
CSS 활용 화면 변경 시 DOM 대신 CSS 속성(transform, opacity 등)을 활용하여 Repaint만 유도합니다. 레이아웃 변경하는 CSS 속성(width, margin 등) 남용하기

 

🛠️ 예시) 

여러 개의 노드를 한 번에 추가할 때, DocumentFragment를 활용하여 Reflow 횟수를 줄일 수 있습니다.

JavaScript

// ❌ 지양해야 할 태도: 매 루프마다 DOM 수정 (Reflow 발생)
const listNode = document.getElementById('my-list');
for (let i = 0; i < 100; i++) {
  const liNode = document.createElement('li');
  liNode.textContent = `아이템 ${i}`;
  listNode.appendChild(liNode); 
}

// ⭕ 바람직한 예: DocumentFragment를 활용하여 한 번에 DOM 수정
const listNode = document.getElementById('my-list');
const fragmentNode = document.createDocumentFragment(); // 가상의 노드 저장소

for (let i = 0; i < 100; i++) {
  const liNode = document.createElement('li');
  liNode.textContent = `아이템 ${i}`;
  fragmentNode.appendChild(liNode); // 가상 저장소에 추가 (Reflow 안 함)
}

listNode.appendChild(fragmentNode); // 딱 한 번 실제 DOM에 추가 (Reflow 최소화)

 


📝 3줄 요약

  1. DOM은 브라우저가 HTML을 추상화한 트리 구조로, 자바스크립트가 화면을 조작하는 도구입니다.
  2. DOM 직접 조작은 매우 비싼 Reflow/Repaint 연산을 유발하므로 최소화해야 합니다.
  3. 가상 DOM은 메모리에 가벼운 복사본을 만들어 변경 사항을 한 번에 실제 DOM에 반영하는 영리한 아키텍처입니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함