DOM을 직접 바꾸지 않는 이유: Virtual DOM

hogu__giriboy·2026년 3월 21일

위클리

목록 보기
10/10

1. 렌더링 이후에 남는 문제

이전 글에서 살펴봤듯이
React에서 렌더링은 컴포넌트 함수가 다시 실행되는 과정이고,
이 자체는 생각보다 큰 비용이 들지 않는 작업이다.

그렇다면 여기서 자연스럽게 하나의 질문이 생긴다.

그럼 실제로 성능에 영향을 주는 건 무엇일까?

핵심은 렌더링 자체가 아니라,
렌더링 이후 실제 화면을 업데이트하는 과정,
DOM을 다루는 작업이다.

DOM이 왜 문제일까

JavaScript에서 변수 하나 바꾸는 건 가볍다.
하지만 DOM은 다르다.

DOM을 변경하는 순간 브라우저는 단순히 값만 바꾸는 게 아니라
화면을 다시 계산하는 과정을 거친다.

예를 들어 생각해보면 이런 느낌이다.

  • JS 연산 → 계산만 하고 끝
  • DOM 변경 → 계산 + 화면 다시 그리기

즉 DOM을 건드린다는 것은 단순히 값을 바꾸는 것이 아니라,
브라우저에게 화면을 다시 계산하고 그리도록 요청하는 것과 같다.

그래서 생기는 문제

만약 DOM을 계속 직접 조작하게 되면 어떻게 될까?

element.textContent = "A";
element.textContent = "B";
element.textContent = "C";

이렇게 여러 번 바꾸면
브라우저는 그때마다 화면을 다시 계산하려고 한다.

결과적으로 불필요한 작업이 계속 발생한다.

그럼 단순하게 DOM을 덜 건드리면 되는 게 아닌가 싶은 생각이 들 수 있다.
그래서 이 지점에서 React의 방식이 등장한다.


2. 그래서 등장한: Virtual DOM

앞에서 본 것처럼
문제는 렌더링이 아니라 DOM을 직접 자주 변경하는 것이었다.

그렇다면 해결 방법은 단순하다.

DOM을 바로 건드리지 말고, 한 번 모아서 처리하자

이 아이디어에서 등장한 것이 바로 Virtual DOM이다.

Virtual DOM?

Virtual DOM은 말 그대로
실제 DOM이 아니라, 메모리 위에 만들어진 DOM의 표현(추상화된 구조)다.

React는 상태가 변경되면
새로운 Virtual DOM을 생성하고 이전 Virtual DOM과 비교하여 변경 사항을 계산한다.

구조를 보면 다음과 같다.

  1. 컴포넌트 실행
  2. 새로운 Virtual DOM 생성
  3. 이전 Virtual DOM과 비교
  4. 바뀐 부분만 실제 DOM에 반영

이 구조의 존재 가치

핵심은 하나다.

비싼 작업은 최소화하고, 싼 작업은 여러 번 해도 된다

  • Virtual DOM 비교 → JS 연산 (가벼움)
  • 실제 DOM 변경 → 브라우저 작업 (무거움)

그래서 React는 Virtual DOM을 통해 변경 사항을 여러 번 계산하고
실제 DOM 변경은 필요한 부분에만 최소한으로 적용하는 방식을 선택한 것이다.

이번에도 공사로 비유할 수 있다.

직접 DOM을 건드리는 방식은 수정할 때마다 바로 공사하는 느낌이다.
벽 하나 바뀌면 공사, 창문 하나 바뀌면 또 공사하는 방식이라면,

Virtual DOM은 설계도를 먼저 수정한 뒤, 필요한 부분만 실제 공사에 반영하는 방식이다.
설계도에서 바뀐 부분을 정리하고 실제 공사는 필요한 부분만 진행하는 방식이다.

즉 Virtual DOM은 화면을 그리기 위한 것이 아니라,
변경 사항을 계산하기 위한 중간 단계라고 볼 수 있다.


3. React는 어떻게 최적화하는가

Virtual DOM을 쓴다는 건 알았다.
그럼 중요한 건 이거다.

어떻게 비교하고, 어떻게 최소 변경만 반영할까?

이전 결과 vs 새로운 결과

React는 상태(state)나 props가 변경되어 렌더링이 발생할 때
새로운 Virtual DOM을 만든다.

그리고 그 이전 Virtual DOM과 새로운 Virtual DOM을
비교해서 달라진 부분을 찾는다.

이 과정을 보통 diffing이라고 한다.

diffing?

비교 과정에서 React는 단순히 전체를 바꾸지 않고,
어디가 바뀌었는지를 찾는다.

예를 들어

<h1>Hello</h1>

에서

<h1>Hello World</h1>

로 바뀌었다면

<h1> 요소 자체를 교체하는 것이 아니라
내용만 변경한다고 판단한다.

실제 DOM 반영 (Reconciliation)

diffing으로 변경된 부분을 찾았으면
이제 그걸 실제 DOM에 반영한다.

이 과정을 Reconciliation이라고 한다.

핵심은 필요한 부분만 업데이트한다는 것이다.
요소 타입이 같으면 내부 내용과 속성을 업데이트하고,
요소 타입이 다르면 기존 요소를 제거하고 새로 생성한다.

이 방식 때문에 React는
전체를 다시 그리지 않고 필요한 부분만 변경한다.

즉 다음과 같은 구조가 된다.

  1. 렌더링 (계산)
  2. Virtual DOM 비교
  3. 변경된 부분만 실제 DOM 반영

이게 가능한 이유는
렌더링 과정은 대부분 JavaScript 계산 작업으로 비교적 가볍고,
실제 DOM 변경은 브라우저의 레이아웃과 화면 업데이트 과정이 포함되어
비용이 크기 때문이다.

그래서 React는 렌더링을 다시 수행하여 Virtual DOM을 만들고
변경 사항을 비교하는 과정은 여러 번 수행하되,
실제 DOM 변경은 필요한 부분에만 최소한으로 적용하는 전략을 선택했다.

결국 React는 화면을 바로 변경하는 방식이 아니라,
먼저 Virtual DOM을 통해 변경 사항을 계산하고,
이전 결과와 비교하여 바뀐 부분만 실제 DOM에 반영하는 방식으로
화면을 업데이트한다.

즉 React의 렌더링 구조는
렌더링 → 비교 → 실제 DOM 반영
이라는 단계로 이루어져 있다고 볼 수 있다.


4. 핵심 정리

  • DOM을 직접 자주 변경하면 브라우저가 레이아웃 계산과 화면 업데이트를 반복하게 되어 성능 비용이 커진다.
  • React는 실제 DOM을 바로 수정하지 않고, Virtual DOM이라는 메모리 위의 DOM 구조를 사용해 변경 사항을 먼저 계산한다.
  • 상태(state)나 props가 변경되면 새로운 Virtual DOM이 생성되고, 이전 Virtual DOM과 비교하여 달라진 부분을 찾는다.
  • 이 비교 과정은 diffing, 변경된 부분을 실제 DOM에 반영하는 과정은 reconciliation이라고 한다.
  • React는 전체 화면을 다시 그리는 것이 아니라 변경된 부분만 실제 DOM에 반영하는 방식으로 동작한다.
  • React의 핵심 전략은 렌더링 계산은 여러 번 수행하되, 실제 DOM 변경은 최소화하는 것이다.
  • 정리하면 React의 화면 업데이트 과정은 렌더링 → Virtual DOM 비교 → 실제 DOM 반영 단계로 이루어진다.

0개의 댓글