React 를 이용한 웹 개발에서 성능 최적화와 관련해 가장 많이 언급되는 개념 중 하나가 바로 Virtual DOM이다. React를 비롯한 현대 프론트엔드 라이브러리는 이 개념을 활용해 효율적인 렌더링을 구현한다.
1. Virtual DOM이란?

실제 DOM과 달리 Virtual DOM은 메모리 상에 존재하는 가벼운 자바스크립트 객체 사본으로, 상태(state)나 속성(props)이 바뀌면 실제 DOM을 직접 수정하지 않고 먼저 Virtual DOM을 갱신한다. 그 후 이전 Virtual DOM과 비교(diffing)하여 최소한의 변경만 실제 DOM에 반영하는 과정을 중재(또는 조정. Reconciliation)이라고 부른다.
2. Virtual DOM의 작동 원리
1. 컴포넌트 상태 변경 → Virtual DOM 업데이트
React 컴포넌트가 렌더링되면 React는 실제 DOM 구조를 JS 객체 형태로 표현한 Virtual DOM을 만든다. 예를 들어 <div class="my-class">Hello, world!</div> 요소는 Virtual DOM에서는 다음과 같이 표현된다:
{
type: "div",
props: { className: "my-class", children: "Hello, world!" },
key: null,
ref: null,
_owner: null,
_store: {}
}
- key가 같으면 기존 DOM 노드를 재사용하고, 내용(props/children)만 바꾼다.
- key가 바뀌면 React는 기존 노드를 버리고 새 노드를 생성한다.
2. 이전 Virtual DOM과 비교(diffing)
상태가 변경되면 React는 새로운 Virtual DOM을 생성하고 이전 Virtual DOM과 비교(diffing)한다. 변화가 생긴 최소한의 요소만 실제 DOM에 반영해, 불필요한 리플로우(Reflow)와 리페인트(Repaint)를 줄인다.
3. 실제 DOM에서 변경된 부분만 반영
비교 과정에서 발견된 변화만 배치(batch) 단위로 모아서 한 번에 실제 DOM에 적용하므로, 대규모 UI나 복잡한 트리 구조에서도 성능을 안정적으로 유지할 수 있다.
3. Virtual DOM을 사용하는 목적
- 불필요한 DOM 조작 최소화 - 직접 DOM을 자주 수정하면 브라우저가 레이아웃 계산과 페인팅을 반복 수행해야 해 성능이 떨어진다. Virtual DOM은 이를 줄인다.
- 렌더링 효율 증가 - 변경된 부분만 실제 DOM에 반영하므로 브라우저 성능 부담을 줄이고, UI 반응 속도를 높인다.
- 개발 편의성 제공 - 상태 중심의 선언적 프로그래밍이 가능해지고, 복잡한 DOM 조작 로직을 직접 작성할 필요가 없다.
- *Document Fragment와 유사한 최적화 - Virtual DOM은 다수의 DOM 노드를 한 번에 갱신하는 Document Fragment 아이디어를 확장한 개념이다. 여러 변경 사항을 메모리상에서 먼저 적용하고 실제 DOM에는 최소한의 변경만 반영해 효율적이다.
*Document Fragment
DOM 조작 시 성능을 높이기 위해 사용하는 “임시 컨테이너” 객체
1. 정의
DocumentFragment는 웹 문서의 메인 DOM 트리에 포함되지 않는, 가상의 메모리 공간에 존재하는 노드 객체이다. DOM에 직접 추가되기 전까지는 화면에 렌더링되지 않으며, 여러 개의 노드를 메모리 상에서 한 번에 구성할 수 있다.
2. 왜 필요한가?
DOM 조작은 브라우저 렌더링 비용이 비싸기 때문에, 노드를 하나씩 추가·삭제하면 매번 리플로우(reflow)와 리페인트(repaint)가 발생한다. 이때 DocumentFragment를 사용하면 메모리 상의 “가짜 DOM 컨테이너” 안에 먼저 노드들을 다 추가하고, 마지막에 그 Fragment 전체를 실제 DOM에 한 번만 추가할 수 있는 것이다.
즉, 리플로우가 한 번만 일어나기 때문에 훨씬 효율적이다.
3. 예시
// 실제 DOM
const list = document.getElementById('list');
// DocumentFragment 생성
const fragment = document.createDocumentFragment();
// 가상의 DOM 조각 안에서 반복문으로 노드를 만듦
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
// 한 번만 실제 DOM에 추가
list.appendChild(fragment);
4. 결과
- 리스트가 한 번에 렌더링됨
- 중간 렌더링이나 깜빡임 없음
- 퍼포먼스 대폭 개선
5. React Virtual DOM과의 관계
React의 Virtual DOM도 사실상 이 개념을 확장한 것.
| 구분 | 설명 |
| DocumentFragment | 실제 DOM에 반영하기 전, 메모리에서 한 번에 조립하는 “가벼운 컨테이너” |
| Virtual DOM | UI 전체를 메모리에서 가상으로 표현하고, 변경된 부분만 실제 DOM에 반영하는 구조 |
즉, Virtual DOM은 “DocumentFragment로 여러 노드를 한 번에 처리하는 아이디어”를 더 발전시켜 상태 기반 렌더링과 diff 알고리즘까지 도입한 개념이라고 볼 수 있다.
4. Virtual DOM이 중요한 이유
Virtual DOM은 특히 대규모 UI나 복잡한 트리 구조를 가진 애플리케이션에서 그 진가를 발휘한다.
수많은 컴포넌트와 DOM 노드가 있는 환경에서도, React는 변경된 부분만 선택적으로 업데이트하기 때문에 전체 UI 성능을 안정적으로 유지할 수 있다.
여기에 React의 *Fiber 아키텍처와 **Concurrent Mode가 결합되면, 렌더링을 작은 단위로 나눠 처리할 수 있다. 덕분에 사용자 입력이나 애니메이션 등 UI 반응성을 해치지 않고, 자연스럽고 부드러운 경험을 제공할 수 있다.
하지만 Virtual DOM도 완전히 무료는 아니다. 메모리 상에서 diffing과 reconciliation 연산이 수행되므로, 상태를 지나치게 자주 바꾸거나 불필요하게 리렌더링이 발생하면 성능 저하가 발생할 수 있다. 따라서 컴포넌트 구조 최적화, 불필요한 상태 변경 방지, React.memo 같은 최적화 기법 사용이 함께 고려되어야 한다.
결국 Virtual DOM은 DOM 조작 비용을 줄이고, 안정적이고 효율적인 렌더링을 가능하게 하는 핵심 기술이며, 현대 React 개발에서 성능과 사용자 경험을 모두 잡기 위해 반드시 이해해야 하는 개념이다.
*React Fiber 아키텍처
Fiber는 React 16부터 도입된 렌더링 재작성 엔진이다. 핵심 목적은 렌더링 작업을 작은 단위(Unit of Work)로 나누어 효율적으로 처리하는 것.
- 기존 React는 동기 렌더링: 상태 업데이트가 발생하면 전체 Virtual DOM 비교(diffs)와 실제 DOM 업데이트를 한 번에 처리했음 → 큰 트리나 무거운 컴포넌트가 있을 때 UI가 잠시 멈춤(프레임 드롭) 발생
- Fiber는 렌더링 작업을 fiber 단위로 쪼갬:
- 각 컴포넌트마다 Fiber 노드를 만들어 작업 단위를 관리
- 우선순위(priority)를 지정하여 중요한 작업(사용자 입력, 애니메이션 등)을 먼저 처리
- 나머지 작업은 백그라운드로 처리
예시
function App() {
const [count, setCount] = React.useState(0);
// 버튼 클릭 시 UI 업데이트 발생
return (
<div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<HeavyComponent />
</div>
);
}
HeavyComponent가 무거워도 Fiber는 렌더링을 쪼개어, 버튼 클릭에 대한 UI 반응성을 우선 보장할 수 있다.
**Concurrent Mode (동시성 모드)
Concurrent Mode는 Fiber 위에서 동작하는 렌더링 전략으로, React가 렌더링을 중단, 재개, 우선순위 변경할 수 있게 한다.
- 목표: 사용자 경험(UX) 개선
- 특징:
- 긴 렌더링 작업을 쪼개어 브라우저 이벤트(클릭, 입력 등) 처리 중에도 UI를 멈추지 않음
- 낮은 우선순위 업데이트는 백그라운드 처리
- React가 최적의 시점에 렌더링을 커밋
예시
import { createRoot } from 'react-dom/client';
import App from './App';
// Concurrent Mode 활성화
const root = createRoot(document.getElementById('root'));
root.render(<App />);
긴 리스트 렌더링이나 이미지 갤러리 같은 컴포넌트가 있어도, 버튼 클릭과 같은 UI 반응이 끊기지 않는다.
Fiber + Concurrent Mode 결합
- Fiber: 렌더링을 작은 단위로 분할 → 우선순위 관리 가능
- Concurrent Mode: Fiber 단위를 유연하게 스케줄링 → 사용자 입력, 애니메이션 등 우선 처리→ UI가 자연스럽고 부드럽게 동작
Fiber가 렌더링 단위를 쪼개고, Concurrent Mode가 그 단위를 필요에 따라 재배치 및 지연 처리함으로써 큰 UI에서도 반응성을 유지한다.
5. 마무리
Virtual DOM은 React가 빠르고 효율적인 UI 업데이트를 가능하게 하는 핵심 기술이다.
diffing 과 Reconciliation 덕분에 불필요한 DOM 연산을 최소화하고, 대규모 UI에서도 안정적인 성능을 제공한다. 하지만 Virtual DOM도 계산 비용이 있으므로 불필요한 상태 변경이나 리렌더링을 방지하는 최적화 전략이 필요하다. 결국 Virtual DOM은 성능, 유지보수성, 사용자 경험을 동시에 잡을 수 있는 React 개발의 핵심 개념이다.
'Frontend > React' 카테고리의 다른 글
| 상태(stateful) & 비상태(stateless) 컴포넌트 (0) | 2025.10.25 |
|---|---|
| React에서 비동기 처리 최적화하기 (0) | 2025.10.25 |
| useRef 자세히 알아보기 (0) | 2025.10.24 |
| useEffect의 cleanup 함수 알아보기 (0) | 2025.10.24 |
| React 메모이제이션과 최적화 (0) | 2025.10.24 |