Javascript/react

DOM과 가상DOM

브라더 코드 2021. 7. 31. 19:51

유투브에서 40년 동안 소프트웨어 개발을 해오신 분을 봤다.

오랜 세월 동안 개발을 하신 것이 대단해보였고 정말 개발 자체를 좋아하신다는 느낌을 받았다.

그분이 강조하신게 표준이다. 표준은 기본에서 조금 발전된 것이고 많은 시간을 통해 만들어졌다. 그리고 표준은 기술 축적이 된다. 웹 표준. 그 중에 하나가 DOM이다. 

 

DOM은 Document Object Model, 문서객체모델이다. 

 

웹 브라우저에서 HTML이나 XML같은 문서의 요소(태그)들을 조작 가능하도록 객체화시킨 것이다.

예를 들면 <html>이나 <body>를 자바스크립트가 이용할 수 있는 객체(object)로 만든 것이다.

 

조금 어렵게 말하면 DOM은 화면의 구성요소(HTML 태그)들을 조작할 수 있는 '인터페이스'이다.

인터페이스는 '어떤 기능을 사용하기 위한 방법을 정의'해놓은 것이다. 

즉, 우리는 DOM을 통해 HTML태그를 생성,수정,삭제할 수 있다. 웹 브라우저에서 자바스크립트라는 언어를 가지고.

 

이러한 DOM은 W3C의 표준 객체 모델이며 트리 구조로 표현된다(W3C : 월드 와이드 웹을 위한 표준을 개발하고 장려하는 조직).

 

출처:tcpschool.com

 

웹 개발하면서 자주 사용하는 document.getElementById("")라는 명령어가 있다. 여기서 document가 위 그림의 최상위에 있는 document객체이다. document객체는 웹 페이지 그 자체를 의미한다. 그러니까 우리는 document라는 문서객체를 통해 HTML요소에 접근할 수 있는 것이다.

 

여기서 한가지 유의할 점. 실무에서 제이쿼리를 자주 사용하는데 jQuery 선택자를 통해 반환된 객체는 jQuery객체이다. DOM이 아니다.

예시를 보자. 아래의 div요소에 접근하고 싶다.

<div id="test"></div>

 jquery는 $("#test") 로 접근하는데 반환하는 것은 jquery 객체이다. 여기서 DOM 객체에 접근하기 위한 방법은 아래와 같다.

1) $("#test")[0]

2) $("#test").get(0)

→ 1), 2) 모두 document.getElementById("test") 와 결과값이 동일.

★ 예시는 선택자가 아이디(1개)라서 0을 쓴 것이고 속성이 class일 경우 개수가 많아질테니 0 또는 index번호를 쓰면 된다.

 

이제 가상DOM을 말해야 하는데 그에 앞서 웹 브라우저 작동과정을 알아보자.

출처:https://www.html5rocks.com

< 브라우저의 workflow >

1. DOM Tree 생성 : 브라우저의 렌더엔진이 HTML을 파싱하여 DOM 트리 생성

2. Render Tree 생성 : css파일과 inline스타일을 파싱, 스타일 정보를 사용해 새로운 트리, 랜더트리 생성

3. Layout : 각 노드들의 위치 결정

4. Painting : 실제 화면에 그리기

 

즉, 하나의 웹 페이지가 나타나기 위해선 위의 과정을 거쳐야 한다.

 

여기서 문제는 어떤 인터렉션에 의해 DOM이 변경되면 Render tree가 그때마다 재생성된다는 것이다.

변화가 발생하면 모든 요소들의 스타일을 다시 계산하고 layout과정을 거치고, painting과정을 거치는 것이다.

작은 변화만 발생해도 전체 노드들이 처음부터 다시 그려진다. 그러니까 불필요한 연산이 많아지게 된다(+성능 저하).

 

웹에서 DOM조작은 중요하지만 시간이 많이 드는 소모적인 과정이다.

더구나 최근에는 SPA를 사용하면서 DOM Tree를 즉각적으로 많이 변경하게 되었다.

 

이에 따라 브라우저 단에서 DOM조작을 더욱 효율적으로 할 수 있게끔 최적화가 필요해졌다.

그래서 등장한 것이 가상DOM이다. 가상DOM은 기존DOM의 추상화 버전으로 생각하면 된다.

(추상화 버전인 이유는 기존DOM과 같은 속성들을 갖고 있지만 같은api를 갖고 있진 않기 때문이다.)

 

 

가상돔의 작동 순서를 알아보자.

1. 데이터가 변경되면 전체UI는 가상DOM에 렌더링된다.

2. 이전 가상DOM에 있던 내용과 현재 내용을 비교한다.

3. 바뀐 부분만 실제DOM에 적용시킨다(갈아끼운다).

 

정리하면,

화면에 변화가 있을 때마다 실시간으로 돔 트리를 수정하지 않고, 변경사항이 모두 반영된 가상 돔을 만들어 실제 DOM에 던져준다. 

결과적으로 브라우저는 한번만 렌더링을 할 수 있게된다.

 

실제 DOM에 접근하여 조작하는 대신 가상 DOM을 활용하여 불필요한 렌더링 횟수를 줄일 수 있다.