📢 어렵고 정석적인 개념 설명보다는 저같은 초보자도 이해하기 쉽게 정리하는 것을 원칙으로 포스팅하고 있습니다. 😄

[React] 가상 돔(Virtual DOM)이란?

DOM(Document Object Model)이란?

DOM이란 문서 객체 모델이라는 뜻으로 브라우저가 HTML 파일의 코드를 읽고 각 요소들을 트리 모양으로 구조화한 객체를 말한다. 쉽게 말하면 우리가 HTML로 만든 코드를 주문서라고 한다면, 브라우저가 이 주문서를 바탕으로 만들어내는 게 DOM인 것이다. 

 

간혹 사람들이 헷갈려하는 게 "HTML === DOM"이라고 착각하는 경우가 많다.

하지만 둘은 다른 개념이다. DOM이라는 것은 코드가 아니라 HTML 코드를 파싱하여 만들어지는 객체 모델이다. 반면 HTML은 코드 자체를 의미한다. 우리가 웹을 만들 때 HTML을 이용하여 전체적인 레이아웃을 잡는다. 그리고 이 HTML 코드를 브라우저가 읽고 DOM을 생성한다.

 

이때, HTML의 각 엘리먼트들은 노드(Node)가 된다. 예를 들어, head 노드 밑에 title 노드가 있고 body 노드 밑에 h1 노드가 있는 것처럼 말이다. 이러한 노드들은 트리 모양으로 이어져 있으며, 이것을 우리는 DOM 트리라고 한다.

 

이러한 노드들은 자바스크립트로 제어할 수 있다는 특징을 가지는데, 이것은 DOM에서 노드를 제어할 수 있는 API를 제공해 주기 때문이다. 우리가 appendChild()로 특정 엘리먼트를 선택할 수 있는 것, addEventListener()로 해당 요소의 이벤트 타겟을 잡을 수 있는 것 모두 DOM에서 API을 제공해 주기 때문인 것이다. 또한, 이것이 브라우저가 DOM을 생성하는 이유이기도 하다.

 

브라우저는 HTML 코드를 읽어서 노드로 이루어진 DOM 트리를 만들어내는데, 이게 문서에 수정사항이 생기게 되면 다시 처음부터 HTML 코드를 읽고 DOM 트리를 만들어내는 과정을 반복하게 된다. 수정이 있을 때마다 전체 페이지를 다시 처음부터 렌더링하는 과정(계속 DOM을 생성하는 것)은 상당히 비효율적인 방식이었고, 이러한 문제를 해결하고자 가상 DOM이 나오게 되었다.

 

(가상 DOM의 원리 - 출처 : https://www.oreilly.com/library/view/learning-react-native/9781491929049/ch02.html)

위 이미지는 DOM의 리렌더링 과정을 잘 설명해주는 대표적인 이미지로 가상 DOM을 공부하려고 검색하다 보면 가장 많이 보게 되는 그림일 것이다. 빨간색 부분이 상태가 변경된 부분이며, 상태가 변경되었을 때 DOM이 어떻게 리렌더링 되는지에 대한 과정을 설명하고 있다. 

 

DOM이 리렌더링이 될 때 바로 실제 브라우저 DOM이 리렌더링되는 것이 아니다. 위 그림처럼 먼저 가상 DOM에서 리렌더링을 하고, 이전 가상 DOM과 새로운 가상 DOM을 비교하여 변경된 부분만 실제 브라우저 DOM에 적용한다.

🚩 엘리먼트(elements)의 두 가지 종류
우리가 HTML에서 div와 같은 요소를 '엘리먼트'라고 불러왔다. 하지만, 엘리먼트에도 2가지가 있다.
리액트에서의 React Elements와 DOM에서의 DOM Elements이다. 위 그림의 Virtual DOM에서의 요소들이
바로 React Elements라고 할 수 있고, Browser DOM에서의 요소들이 DOM Elements라고 할 수 있다.
쉽게 말해, React Elements는 DOM Elements의 가상 표현이라고 할 수 있다.

DOM Elements는 React Elements에 비해 많은 정보를 담고 있기 때문에 더 무거우며, 이러한 이유로 리렌더링 시
DOM Elements가 바로 렌더링되는 것이 아니라 React Elements에서 먼저 렌더링이 된 후 바뀐 부분만 DOM에서
리렌더링되는 것이라고 할 수 있다.

 

가상 돔(Virtual DOM)이란?

가상 DOM의 가장 큰 특징은 페이지의 수정 사항이 생겼을 때, 이전 상태 값과 비교해서 달라진 부분만 DOM에게 전달하여 딱 한 번만 렌더링을 진행한다는 점이다. 즉, DOM을 바로 렌더링하는 게 아니라 가상 DOM을 거쳐서 한 번에 실제 DOM에 반영한다. 가상 DOM은 실제 DOM을 분석하여 만든 자바스크립트 객체라고 할 수 있다.

 

가상 DOM을 이용하는 대표적인 라이브러리가 바로 리액트이다. 리액트는 렌더링 할 때마다 새로운 가상 DOM을 만들고 이전 가상 DOM과 어떤 부분이 바뀌었는지를 검색한다. 그리고 바뀐 부분을 실제 DOM에 반영한다.

변경 사항이 생길 때마다 DOM을 매번 렌더링하는 것이 아니라 바뀐 부분만 찾아서 렌더링하기 때문에 더 효율적인 방식이라고 할 수 있으며, 이것이 가능한 이유 역시 가상 DOM을 이용하기 때문이다.

 

정리하자면, 가상 DOM을 쓰는 이유는 실제 DOM에서 변경 사항이 발생할 때마다 리렌더링되는 데, 변경 사항이 만약 100가지일 경우 DOM은 100번 리렌더링하게 된다. 이런 비효율적인 방식을 해결하기 위해 가상 DOM이 등장했고, 변경 사항이 생기면 먼저 가상 DOM을 리렌더링하고 이전 가상 DOM과 비교하여 변경된 부분만 실제 DOM에 적용하게 된다.

(결론적으로 변경 사항이 많더라도 실제 DOM의 렌더링은 1번)

 

1. DOM이란 브라우저가 HTML 코드를 읽고 엘리먼트들을 노드화하여 트리 모양으로 만든 문서 객체
    => 브라우저가 HTML 문서를 자바스크립트가 접근할 수 있도록 객체화한 것.
2. 변경 사항이 있을 때마다 DOM을 다시 로드해야된다는 문제점이 있음
3. 이를 극복하고자 가상 DOM을 사용하는데, 이것은 변경 사항이 있을 때 실제 DOM을 바로 렌더링하는 게 아니라
    우선 가상 DOM에 변경 사항을 렌더링하고 이전 DOM과 비교한 다음 변경된 부분만 실제 DOM에 렌더링하는 방식임