Virtual DOM을 쓰면 왜 좋을까?

직접 DOM을 제어하지 않아도 되고, 직접 DOM을 제어하는 것보다 성능 상에서 나을 수 있다

2022-04-21에 씀

React는 SPA(Single Page Application)을 만들 수 있게 해준다. SPA는 HTML 페이지를 하나만 띄워 놓은 다음, 이 페이지를 동적으로 변경시켜 사용자와 소통하는 웹 어플리케이션이다. 그렇기 때문에 DOM 조작이 자주 일어난다.

DOM 조작이 일어나면, DOM Tree에 변경이 생긴다. 이를 CSSOM과 조합해서 렌더 트리를 만들고, 레이아웃을 계산하고, 페인팅을 해야 화면이 다시 그려진다. DOM을 한 번 조작할 때마다 이 과정이 수행된다. DOM을 많이 조작할수록 연산 횟수는 늘어날 것이다.

복잡한 SPA에서는 DOM 조작이 많이 발생한다. 리액트에서는 DOM을 하나하나 조작하는 것보다 Virtual DOM을 사용해서 이 문제를 해결하려고 했다.

리액트 컴포넌트에 변경이 생기면, Virtual DOM을 생성한다. 이 Virtual DOM은 직전에 렌더링했던 Virtual DOM과 비교해서 변경된 부분을 찾는다. 모든 비교가 끝나면 변경된 부분만 DOM에 반영한다.

DOM 조작이 일어날 때마다 레이아웃, 페인팅 등의 연산을 해야 했던 것과 달리, Virtual DOM을 사용하면 수많은 변화를 하나로 묶어서 관리하고 연산 횟수를 줄일 수 있다.


사실 DocumentFragment를 사용해도 DOM 연산 횟수를 줄일 수는 있다.

1var list = document.createElement('ul');
2var numbers = ['one', 'two', 'three'];
3
4numbers.forEach(function (num) {
5 var li = document.createElement('li');
6 li.innerText = num;
7 list.appendChild(li);
8});

위 코드는 리플로우와 렌더링 과정이 3번 일어날 것이다. (최근 브라우저는 최적화가 잘 되어서 이 예시로는 리플로우가 여러번 발생하지 않을 수도 있다.)

1var list = document.createElement('ul');
2var numbers = ['one', 'two', 'three'];
3
4var frag = new DocumentFragment()
5
6numbers.forEach(function (num) {
7 var li = document.createElement('li');
8 li.innerText = num;
9 frag.appendChild(li);
10});
11
12list.appendChild(frag);

이렇게 DocumentFragment를 사용하도록 바꾸면 리플로우와 렌더링 연산이 한 번만 일어나게 바꿀 수 있다. DocumentFragment는 DOM의 일부가 아니고, DOM에 반영하기 전까지는 메모리 상에만 존재한다. 원하는 요소에 fragment를 append 하는 순간, fragment가 가지고 있는 자식 노드들이 한번에 append 된다.

그런데 웹 어플리케이션 내에 컴포넌트의 수가 많고 관리하는 상태의 수가 많다면, 일일이 DOM의 업데이트 여부를 확인하고 수정해 주는 것은 아주 힘들고, 거의 불가능하다. 프레임워크에서 제공하는 Virtual DOM을 사용하면 이를 편하게 관리할 수 있다.

참고

프로필 사진

조예진

이전 포스트
객체지향 프로그래밍이란? - <객체지향의 사실과 오해>
다음 포스트
좋은 프레임워크는 어떤 프레임워크인가? - <프레임워크 없는 프론트엔드 개발>