03. DOM & VDOM

Taesoo Kim·2023년 3월 1일
0

React101

목록 보기
4/8

지금까지 미뤄왔던, 간단하지만 중요한 내용인 DOM에 관한 얘기를 해보려 합니다. DOM의 필요성과, 한계 그리고 VDOM의 등장, 마지막으로 리액트가 VDOM을 사용하는 방법에대해 탐구해 볼게요. 지루한 얘기지만, 최대한 간단하고 쉽게 설명해 보겠습니다!

Document Object Model (DOM)

인터넷이 보급화되고 웹페이지가 발전하면서, 웹페이지가 그냥 정보를 담고 있는것에서, 유저와 상호작용을 하며 더 많은 정보와 경험을 제공하는 방향으로 발전하였습니다. 이런 발전 과정에서 처음으로 웹페이지가 유저의 반응을 처리하기 위해서 도입된 방식이 DOM인데요, 비유하자면 티비의 리모컨과 비슷하게 작동합니다.
예를들어, 우리가 채널을 바꾼다던가, 볼륨을 높인다던가 할때 무엇을 사용하나요? 우리는 직접 회로를 건들이면서 티비를 조작하지 않고, 리모컨을 가지고 조작을 합니다. 즉, 리모컨이 티비와 우리간의 다리 역할을 하면서 상호작용을 하게 만드는 물건인 셈이죠.
마찬가지로 DOM도 유저와 웹페이지간의 상호작용을 위해 존재합니다. DOM 안에는 유저의 액션을 받을 수 있는 EventListener 같은 메서드가 있고, 또 이 메서드가 html 문서에 접근할 수 있도록 트리 형태의 태그 묶음이 있습니다. 만약 유저가 무언가를 변화시키면, DOM이 html을 건드리고, 또 그렇게 만들어진 html에서 새로운 DOM을 생성합니다. 하지만 DOM이 있다고 바로 웹페이지를 만들 수 있는것은 아니고, 몇가지 과정을 더 거치면서 웹페이지가 완성이됩니다.

Rendering Engine and its Workflow


보통의 웹브라우저는 각각의 랜더링 엔진이라는 것이 있는데, 이 엔진이 DOM에 CSS을 적용시켜 Render Tree를 만들고, Painting 하는 과정을 거치게 됩니다. 문제는 DOM이 변경되면, 이 일련의 거대한 흐름이 다시 돌아간다는 겁니다. 단순히 어떤 태그안에 텍스트만 변경하면 성능에 신경 쓸 일이 없겠지만, 요즘같은 큰 데이터를 다루고, 컴포넌트 사이 의존성이 많은 웹페이지에서는 한곳의 변화가 다른 수많은 곳의 변화를 또 일으킵니다. DOM에서는 한 클릭에서 비롯되는 수많은 변화를 모아서 Reflow하지 않고, 계속 변화를 줄때마다 새로운 DOM을 만들고, 페인팅을 다시 하고 랜더링을 한다는 거죠. 굉장히 비효율적인 작업으로 보입니다. 이런 비효율성을 개선하기 위해 도입된 방법이 바로 VDOM이 되겠습니다.

VDOM

Virtual Document Object Model(VDOM)은 랜더링 엔진에서 먹히지 않는, 메모리 상에서만 존재하는, 하지만 실제 DOM과 똑같은 DOM입니다. 리액트는 평소에 VDOM을 메모리에 올려두고 있다가, 컴포넌트에 변화를 감지했을때 똑같은 VDOM을 하나를 더 만들어 여기에 변화를 입힙니다. 그 후, Diffing 이라는 과정을 통해 어떤 변화가 있었는지 확인하고, 그 변화를 실제 DOM에 patching합니다. 기존의 방식이 매 변화에 새로운 DOM을 만든 형식이라면, VDOM은 변화를 최대한 모아서 한번에 DOM에 전달하려는 방식입니다.

Key props

Diffing Algorithm은 현재로도 O(n^3) 정도의 성능을 낸다고 알려져 있습니다. 하지만 컴포넌트 구성시 몇가지 룰만 따라준다면, 실질적으로 O(n)정도의 성능을 낼 수 있는데요, 그 중 하나가 Key prop입니다. Key는 컴포넌트들의 List를 구성하는데 필수적인 요소인데요, 이 Key 값을 가지고 리액트는 리스트를 정렬한다고 볼 수 있겠습니다. 그럼 지금부터 어떻게 Key값이 Diffing을 수월하게 하는지 간단한 예시를 통해 알아보겠습니다.

//1. Original List
<ul> 
  <li>item 3</li>
  <li>item 4</li>
  <li>item 5</li>
</ul>

//2. An element appended at the end of list
<ul> 
  <li>item 3</li>
  <li>item 4</li>
  <li>item 5</li>
  <li>item 6</li>
</ul>

//3. An element appended at the front of list
<ul> 
  <li>item 2</li>
  <li>item 3</li>
  <li>item 4</li>
  <li>item 5</li>
</ul>

1번 리스트가 2번과 3번으로 변했다고 하겠습니다. 1에서 2로는 크게 문제가 되지 않습니다. 그저 리스트 뒤에 더해주는 것이니까요. 하지만 1에서 3은 얘기가 조금 다릅니다. 리액트는 이런경우 item 3에 변화가 생겼다고 인지합니다. 그 아래도 다 마찬가지구요. 즉, 처음 아이템부터 끝까지 새로 랜더되는것과 다름없습니다. 정말 최악의 케이스가 되는 셈이죠. 이런 경우를 방지하기위해서 key값으로 아이템을 확인하는 겁니다.

<ul> 
  <li key="3">item 3</li>
  <li key="4">item 4</li>
  <li key="5">item 5</li>
</ul>

<ul> 
  <li key="2">item 2</li>
  <li key="3">item 3</li>
  <li key="4">item 4</li>
  <li key="5">item 5</li>
  <li key="6">item 6</li>
</ul>

이렇게 Key값을 주면 리스트 중간이건, 처음이건, 마지막이건 새로 들어간 아이템만 리액트가 식별해서 랜더하게 됩니다. 그래서 리스트에서는 Key값이 중요한것이구요.

Conclusion

이번에는 DOM의 간략한 유래와, 작동방식, 한계점 그리고 그걸 개선하려 나온 VDOM까지 알아보았습니다. VDOM을 한줄로 정리하자면, '최대한의 변화를 한번에 업데이트 하겠다' 가 될거 같습니다!
항상 주제에 넘게 많은 내용을 가져와서 횡설수설 하는 것 같습니다. 하지만, 저도 꼬리를 무는 Drilling을 하다보니 본 주제도 깊게 알아가고, 부수적인 CS 지식도 얻어가는 것 같습니다. 읽어주셔서 감사합니다!

Reference

https://www.youtube.com/watch?v=6rDBqVHSbgM
https://blog.logrocket.com/virtual-dom-react/#comparison-chart-real-virtual-shadow-dom
https://medium.com/technogise/dom-manipulation-in-browser-59b793bee559
https://betterprogramming.pub/the-history-of-dom-manipulation-performance-in-a-nutshell-701247c19e83
https://shuvamk.medium.com/why-exactly-do-we-need-a-virtual-dom-7e6821d2b17d

profile
뭔 생각을 해. 그냥 하는 거지 뭐

0개의 댓글