본문 바로가기
더조은컴퓨터아카데미 리액트 주말반

리액트 주말반 네번째 수업 (React Virtual DOM에 대하여)

by 오렌지코딩 2025. 7. 20.

🔹 1. DOM이란?

DOM(Document Object Model)은 브라우저가 HTML 문서를 객체로 표현한 구조입니다.

 

🔹 2. Virtual DOM이란?

Virtual DOM은 실제 DOM의 가벼운 자바스크립트 객체 복제본입니다.

React는 UI 변경이 필요할 때 실제 DOM을 직접 수정하지 않고, 먼저 Virtual DOM에서 그 변경을 시뮬레이션합니다.

 

🔹 3. Virtual DOM 작동 방식

  1. 초기 렌더링:
    •   컴포넌트가 처음 렌더링될 때, React는 Virtual DOM을 생성하고 실제 DOM에 반영합니다.
  2. 업데이트 발생 (setState, props 변경 등):
    •   변경이 생기면 React는 새로운 Virtual DOM을 생성합니다.
    •   이전 Virtual DOM과 비교(diffing)하여 어떤 부분이 변경되었는지 찾습니다.
  3. DOM 패치 (Reconciliation):
    •   변경된 부분만 실제 DOM에 반영합니다.

 

🔹 4. 왜 Virtual DOM이 빠를까?

  • 전체 DOM이 아니라 변경된 부분만 갱신하기 때문입니다.
  • Batch 업데이트: 여러 변경사항을 모아서 한 번에 처리합니다.
  • 최적화된 diffing 알고리즘 덕분에 빠르게 비교하고 렌더링을 최소화합니다.

 

🔹 정리

항목                                        실제 DOM                                 Virtual DOM
위치 브라우저 내부 메모리 상의 JS 객체
업데이트 속도 느림 빠름
사용 목적 화면 렌더링 효율적인 변경 추적 및 렌더링 최적화

 

 

그렇다면 실제코드 예시를 통해 리액트의 Virtual DOM이 어떻게 실제 DOM조작에 비해 성능을 최적화 하는지 알아봅시다.

 

✅ 1. 순수 JavaScript로 직접 DOM 조작 (비효율적 방식)

<!-- index.html -->
<button id="increment">Increment</button>
<div id="count">0</div>
// vanilla.js
let count = 0;
document.getElementById("increment").addEventListener("click", () => {
  count++;
  document.getElementById("count").textContent = count;
});

🧠 이 방식은 간단해 보이지만, 복잡한 DOM 구조에서는 다음 문제가 있습니다:

  • DOM을 직접 조작하기 때문에 전체 DOM 트리를 다시 렌더링하는 경우가 많음
  • 성능이 저하되기 쉬움 (특히 애니메이션, 리스트 등)

 

 

✅ 2. React로 구현 (Virtual DOM 사용)

// App.jsx (React)
import React, { useState } from "react";

function App() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <div>{count}</div>
    </div>
  );
}

export default App;

🧠 React는 어떻게 다를까요?

  • 버튼 클릭 시 setCount로 상태가 변경되면,
  • 새로운 Virtual DOM이 생성됨
  • 이전 Virtual DOM과 비교(diffing)
  • 바뀐 부분 (<div>{count}</div>)만 실제 DOM에 반영됨

 

✅ 3. 성능 비교 실험 예시

리스트를 10,000개 렌더링하면서 숫자를 업데이트하는 예제를 비교해 보겠습니다.

 

📦 3-1. 직접 DOM 조작 (비효율 예)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vanilla JS Render Test</title>
  </head>
  <body>
    <button id="increment">Increment</button>
    <div id="root"></div>

    <script>
      const root = document.getElementById('root');

      const render = (count) => {
        //alert(count);
        root.innerHTML = '';
        const ul = document.createElement('ul');
        for (let i = 0; i < 10000; i++) {
          const li = document.createElement('li');
          li.textContent = `Item ${i} - Count: ${count}`;
          ul.appendChild(li);
        }
        root.appendChild(ul);
      };

      let count = 0;
      document.getElementById('increment').onclick = () => {
        count++;
        render(count);
      };

      // 초기 렌더링
      render(count);
    </script>
  </body>
</html>

(그대로 index.html 복사후에 실행해 보면 잘 실행됩니다)

 

  • 👎 innerHTML과 DOM 조작으로 전체 노드를 계속 재생성
  • 렌더링 시간이 길어짐
  • UI가 버벅거릴 수 있음

📦 3-2. React 사용 (효율적 예)

// App.jsx
import React, { useState } from "react";

function App() {
  const [count, setCount] = useState(0);

  const items = Array.from({ length: 10000 }, (_, i) => (
    <li key={i}>Item {i} - Count: {count}</li>
  ));

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <ul>{items}</ul>
    </div>
  );
}

export default App;

 

  • 👍 React는 변경된 count만 반영하여 diff → patch
  • 전체 노드를 재생성하지 않고 DOM 최소 업데이트
  • 퍼포먼스가 더 좋고 UI가 부드러움

⏱️ 성능 측정 팁

브라우저 개발자 도구(F12) > Performance 탭을 이용해서:

  • React와 Vanilla JS 비교 실험 가능
  • Recalculate Style, Layout, Paint 시간 비교 가능

✅ 결론

항목                                                      Vanilla JS                                                      React (Virtual DOM)
전체 DOM 재생성 있음 없음 (부분 업데이트)
렌더링 속도 느림 (특히 많은 노드) 빠름
개발자 관리 직접 DOM 조작 필요 선언적 UI, 상태 기반
유지보수 어렵고 오류 가능성 큼 효율적, 구조적

 

출처: chatGpt