가상돔(Virtual DOM) 이해하기

기술노트

가상돔(Virtual DOM) 이해하기

우선 DOM이란 무엇인가 ?

Dom이란 Document Object Model(문서객체모델)의 약자이다.

여기서 문서 객체란, 웹 브라우저 안에서 HTML 문서에 JavaScript 가 접근할 수 있도록 <html태그>를 객체(object)이다.

![1](https://blog.kakaocdn.net/dn/bDqgkW/btrEnRjNfa1/Hu8CR9Su4ciTS0gmMzsCtk/img.webp)


HTML의 계층구조를 Tree로 나타내며, DOM이 존재함으로써 JS를 이용하여 요소를 추가, 수정, 삭제할 수 있게 된다. (문서 구조, 스타일, 내용 등을 변경할 수 있게 돕는 역할)

하지만 HTML 문서 안에 자바스크립트는 어떻게 접근할 수 있을까?

그건 바로 DOM 이라는 객체를 통해 인식 가능하다고 생각한다.

기존 렌더링 방식은

1. 브라우저느 서버가 보내준 HTML 파일을 해석(Parsing)하여 DOM 트리를 만든다. 2. 브라우저는 서버가 보내준 CSS 파일을 해석하여 CSSOM 트리도 만든다. 3. DOM 트리 + CSSOM 트리를 결합해 렌더트리를 만든다. 4. 렌더트리로 각 노드의 위치와 크기를 계산한 레이아웃을 만든다. 뷰포트(Viewport) 내에서 각 노드들의 위치와 크기를 계산한다 5. Layout 계산이 완료되면 이제 요소들을 실제 화면에 그리는 페인트(paint)를 한다.

  • 레이아웃 재구성: 각 노드들이 어디에 나타나야 할 지 스크린 좌표 계산
  • 페인트(Paint): 렌더링된 요소에 색을 입히는 과정

DOM의 문제점

DOM은 새로운 요청이나 변경사항이 있을 때마다 매번 리렌더링을 한다. 한글자만 수정해도 리렌더가 일어나는 것이다.

DOM 자체는 빠르더라도 요소의 개수가 수백개,수천개로 늘어날 경우에는 당연히 느려질 수 밖에 없다. 매번 새롭게 구성하기 때문에, 렌더할 양이 많으면 속도가 느려지게 된다.

해결책은 바로 가상돔

위와 같은 성능(속도) 이슈에 대한 문제점을 해결해주기 위해서 DOM을 최소한으로 조작할 수 있는 가상돔이 등장 하게된 것이다.

React는 가상 DOM을 도입하여, HTML 마크업을 시각적인 형태로 변환하는 시간(css가 적용되고 수정되어 반영되는 시간)을 최소한의 DOM 조작을 통해 작업을 처리하여 개선하고자 하였다.

가상돔은 지우개로 고칠 부분만 고치는 것과 비슷한 개념이다.

Virtual DOM은

![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/79029eb8-d1de-4683-a489-2df400d75056/Untitled.png)

DOM의 구조를 흉내낸 트리구조의 JavaScript 객체이다. 실제 DOM을 조작하는 게 아닌, 메모리에 DOM을 추상화한 자바스크립트 객체를 구상해 사용하는 것이다.

필요한 부분만 골라집으므로, Reflow, Repaint가 필요한 것들을 한번에 묶어서 DOM에 전달한다.

따라서 처리되는 Reflow, Repaint의 규모가 커질 수 있지만, 한번만 연산을 수행하게 되므로 반복적인 부분이 줄어들어 성능이 개선된다.

작은 규모의 레이아웃이 여러번 발생하는 것보다 큰 규모의 레이아웃이 한번 발생하는 것은 성능상의 큰 차이를 나타낼 수 있다.

리액트가 가상돔을 반영하는 절차

![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9b4203b3-fe95-4a29-b857-7ab7e6aa3430/Untitled.png)

1. 데이터를 업데이트하면 전체 UI를 가상돔에 리렌더링 한다. 2. 가상돔끼리 비교하고 (이전 가상돔에 있던 내용과 현재 내용 비교) 3. 바뀐 부분만 실제 DOM에 적용한다. (레이아웃 계산은 한번만 한다.)

각 컴포넌트가 반환하는 엘리먼트를 이전에 반환했던 엘리먼트와 비교하고 다른 경우에만 해당하는 DOM 노드에 작업을 수행하는 것이다.

그렇다면 정말 가상돔은 빠를까?

결론부터 말하자면 아니라고 할 수 있다.

리액트 공식 레퍼런스에서 지속적으로 데이터가 변화하는 대규모 애플리케이션 구축하기 라는 문장이 있다. 즉, 간단한 작업(단순한 라우팅 작업 같은)일 경우에는 리액트를 사용하지 않는 편이 더 효과적일 때도 있다는 말이다. 또한 코드 최적화를 열심히 한다면 속도 문제를 개선할 수 있을 것이다.

정리

리액트는 컴포넌트의 상태값의 변경되면, UI를 자동 업데이트 해주는 자바스크립트 UI 라이브러리

리액트가 가상돔을 사용하여 실제 DOM에 접근하여 조작하는 대신, 이를 추상화한 자바스크립트 객체를 구성하여 사용하여 DOM 처리 횟수를 최소화하고 효율적으로 진행시킨다.

즉 state, props, redux store 등의 상태값이 변경되면

리액트가 해당 컴포넌트 함수를 자동으로 재호출하여 재랜더링 해준다.

결론

이렇게 작은 규모의 레이아웃이 여러번 발생하는 것보다 큰 큐모의 레이아웃이 한 번 발생하는 것이 성능상의 큰 차이를 나타는 것 같다. 리액트는 가상돔으로 얕은 비교와 일괄 돔 업데이트 방식을 이용하여 성능 향상을 이끌어 내는 것이라 생각한다. 그렇지만 무조건적으로 리액트를 사용하는 것이 아닌 항상 기술적 타당성을 검토하며 개발하는 자세가 필요하다.


참고문헌

[2](https://devbirdfeet.tistory.com/219) [3](https://dev-cini.tistory.com/10) [4](https://dev-cini.tistory.com/11) [5](https://hello-bryan.tistory.com/326)