Virtual DOM?

김하영·2022년 12월 11일
0

React

목록 보기
3/7
post-thumbnail

DOM이란?

Virtua DOM을 이해하기 전에 우선 DOM에 대해서 알아보자.
앞선 포스팅에서도 정리했지만 DOM(Document Object Model)은 문서 객체 모델이라고 하는데 결국은 브라우저에서 다룰 HTML 문서를 파싱하여 '문서의 구성요소들을 객체로 구조화하여 나타낸 것'이다.

DOM은 애플린케이션의 전체 UI를 나타내며 트리 데이터 구조로 표현된다. 여기에는 Web Document에 있는 각 UI 요소에 대한 노드가 포함된다. 웹 개발자가 JavaScript를 통해 콘텐츠를 수정할 수 있기 때문에 매우 유용하다. 또한 구조화된 형식으로 되어 있어 특정 대상을 선택할 수 있고, 모든 코드 작업이 훨씬 쉬워지기 때문에 많은 도움이 된다.

DOM의 문제점

DOM은 트리 구조로 되어 있어서 이해하기 쉽지만, 노드의 수가 많아질 수록 속도가 느려지고, DOM 업데이트에 잦은 오류를 발생시킬 수 있다.

또한, 최근 모던 웹은 SPA(Single Page Application)을 사용한다. 하나의 웹 페이지를 어플리케이션처럼 구성하는 SPA에서는 HTML 문서 자체가 하나이며, 여러 동적인 기능이 들어가기 때문에 안그래도 리소스가 모두 합쳐진 무거운 HTML 문서를 지속적으로 재랜더링 해줘야한다는 문제점이 발생하게 되었다.

JavaScript를 공부한 적이 있다면, 'getElementById()' 또는 'getElementByClass()' 메서드를 사용하여 DOM의 내용을 수정할 수 있다는 것을 알고 있을 것이다.

// example

document.getElementById('some-id').innerValue = 'updated value';

콘솔이나 JavaScript 파일에 위와 같은 코드가 실행될 때 아래와 같은 과정이 일어난다.

  • 브라우저는 HTML을 구문 분석하여 이 ID를 가진 노드를 찾는다.

  • 이 특정 요소의 자식 요소를 제거한다.

  • 'updated value'으로 요소(DOM)을 업데이트한다.

  • 부모 및 자식 노드에 대한 CSS를 다시 계산한다.

  • 마지막으로 브라우저 디스플레이에 페인팅된다.

따라서 DOM을 업데이트하는 것은 콘텐츠 변경을 포함할 뿐만이 아니라 훨씬 더 많은 작업들이 요구된다. 또한 CSS를 다시 계산하고 레이아웃을 변경하려면 복잡한 알고리즘이 필요하며 성능에 영향을 미친다.

이처럼 기존에는 화면의 변경사항을 DOM을 직접 조작하여 브라우저에 반영하였다. 하지만, 이 방법의 가장 큰 단점은 DOM 트리가 수정될 때마다 렌더 트리가 계속해서 실시간으로 갱신된다는 점이다.
즉, 화면에서 10개의 수정사항이 발생하면 수정할 때마다 새로운 랜더 트리가 10번 수정되면서 새롭게 만들어지게 되는 것이다.

Virtual DOM(가상 DOM)

가상 DOM이란 DOM을 가볍게 만든 JavaScript 표현이라고 할 수 있고 주로 React, Vue.js 등에 사용된다. 가상 DOM은 실제로 스크린에 랜더링하는 것이 아니기 때문에 DOM을 직접 업데이트하는 것보다 상대적으로 빠르다.

가상 DOM은 실제 DOM에서 처리하는 방식이 아닌 Virtual DOM과 메모리에서 미리 처리하고 저장한 후 실제 DOM과 동기화하는 프로그래밍 개념이다. 해당 DOM을 컴포넌트 단위로 쪼개어 마치, HTML 컴포넌트 조립품처럼 다루는 개념이다.

DOM과 Virtual DOM의 비교

DOMVirtual DOM
업데이트느리다빠르다
HTML 업데이트 방식HTML을 직접적으로 업데이트HTML을 직접적으로 업데이트 하지 않음
새로운 element 업데이트 방식새로운 element가 업데이트된 경우 새로운 DOM 생성새로운 가상 DOM 생성 후 이전 DOM과 비교 후 차이점 DOM만 업데이트
메모리메모리 낭비가 심함메모리 낭비가 덜함

DOM 코드

<ul class="fruits">
	<li>Apple</li>
	<li>Orange</li>
	<li>Banana</li>
</ul>

Virtual DOM식으로 표현된 코드

{
	type: "ul",
    props: {
    	"class": "fruits"
    },
    children: [
    	{
        	type: "li",
            props: null,
            children: [
            	"Apple"
            ]
        },
        {
        	type: "li",
            props: null,
            children: [
            	"Orange"
            ]
        },
        {
        	type: "li",
            props: null,
            children: [
            	"Banana"
            ]
        }
    ]
}

Virtual DOM의 3 Steps

Step 1

데이터가 업데이트 되었을 때, 전체 UI가 Virtual DOM에서 리랜더링 된다.

Step 2

이전 DOM과 새로운 Virtual DOM의 차이가 계산된다.

Step 3

계산이 끝난 후, DOM은 변경된 부분만을 변화시킨다.


결론 :

기존에는 실제 DOM을 조작하여 DOM 트리가 수정될 때마다 렌더 트리가 그때마다 계속해서 갱신이 되었다면, Virtual DOM을 이용하여 중간 단계로 Virtual DOM을 수정하고 변경 내역을 한 번에 모아 실제 DOM과 변경된 Virtual DOM의 차이를 판단한 후, 구성 요소의 변경이 필요한 부분만 찾아 변경하고 그에 따른 렌더링의 수를 줄일 수 있게 되었다. 이로써, 브라우저 내에서 발생하는 연산의 양을 줄이면서 성능을 개선할 수 있는 것이다.


++ 추가 정리

  1. 리액트의 가상돔은 실제 DOM과 같은 내용을 담고 있는 복사본이다.
    그리고 이 복사본은 자바스크립트 객체 형태로 메모리상에 저장되어 있다.
  1. 리액트는 항상 두 개의 가상돔을 갖고 있다.
    첫 번째 가상돔은 변경 이전의 내용을 담고 있고,
    두 번째 가상돔은 변경 이후에 보여질 내용을 담고 있다.

  2. 변경된 내용이 화면에 새롭게 그려지기 이전, 곧 실제 DOM이 변경되기 이전에 리액트는 두 개의 가상돔을 비교해서 정확히 어떤 부분이 바뀌었는지 효율적으로 비교하여 파악한다. 그리고 이러한 과정을 Diffing이라고 부른다.

  3. Diffing을 통해서 변경된 부분들을 파악한 이후에, 리액트는 Batch Update를 수행함으로 실제 DOM에 한번에 적용시켜 준다. 그리고 이러한 과정을 Reconsilliation, 재조정이라고 한다.

profile
호기심 많은 프론트엔드 주니어 💡

0개의 댓글