[자바스크립트] DOM과 Virtual DOM

minidoo·2020년 9월 3일
1
post-thumbnail

DOM

DOM : HTML, XML 문서의 프로그래밍 인터페이스

Virtual DOM(가상돔)을 살펴보기 전에 DOM에 대해 알아보자.

DOM은 HTML 문서의 내용과 구조가 객체 모델로 변화되어 다양한 프로그램에서 사용된다.
HTML이 화면에 보이는 구조를 문서로 만든 단순 텍스트라면, DOMHTML을 이용하여 실제로 화면에 나타내지는 인터페이스라고 한다. DOM의 개체 구조는 노드 트리로 표현한다.

<html>
  <head>
    <title> MY DOM </title>
  </head>
  <body>
    <h1> Welcome to my velog! </h1>
  </body>
</html>

위 코드는 아래와 같은 노드 트리(부모와 자식으로 표현된 트리 구조)로 표현 된다.
(사진)

DOM은 자바스크립트로 수정할 수 있다.

<html>
  <head>
  </head>
  <body>
    <div class="fruit-wrapper">
      <p class="fruit-item">Apple</p>
    </div>
  </body>
</html>

첫 번째 "fruit-item"의 과일을 Orange로 바꾸고, 두 번째에 Melon을 추가해보자.

1. "fruit-item"의 첫 번째 요소 찾기
2. 해당 내용을 Orange로 바꾸기
3. p 태그를 하나 더 만들어 Melon Element 추가하기
// 1. "fruit-item"의 첫 번째 요소 찾기
const fruitItem = document.getElementByClassName("fruit-item")[0];
// 2. 해당 내용을 Orange로 바꾸기
fruitItem.textContent = "Orange";

// 3. p 태그를 하나 더 만들어 Melon Element 추가하기
const Fruit = document.getElementByClassName("fruit-wrapper")[0];
const Melon = document.createElement('p');
Melon.classList.add("fruit-item");
Melon.textContent = "Melon";
Fruit.appendChild(Melon);

간단한 작업이지만 매우 복잡해보인다.

프로젝트 규모가 작을 때는 크게 문제가 없지만 코드가 복잡해지면 성능이 떨어지게 된다. getElementByClassName 메소드로 "fruit-item"이라는 class를 찾고 있다. 예제는 하나의 class만 존재하지만 규모가 커지면 특정 "fruit-itme"을 찾아 업데이트하는 쿼리 비용은 매우 비싸지게 될 것이다.

innerText를 사용하여 문서의 큰 부분을 한 번에 바꾸는 간단한 코드로 변경해보자.

const Fruit = document.getElementByClassName("fruit-wrapper")[0];
Fruit.innerText = `
    <p class="fruit-item">Orange</p>
    <p class="fruit-item">Melon</p>
`;

두 방식 모두 DOM을 업데이트하지만 HTML 문서의 내용을 변경하지는 않는다.

하지만 변화가 일어날때 마다 HTML에 접근하여 레이아웃을 구성하고 Repaint하는 과정은 상당한 시간이 허비될 것이다. 따라서 우리는 Virtual DOM(가상돔)을 이용하여 이런 문제를 해결할 수 있다.


Virtual DOM (가상돔)

Virtual DOM : 실제 DOM에 접근하지 않고, 이를 추상화시킨 자바스크립트 객체를 구성하여 사용

가상돔은 실제 DOM이 아니다.
DOM이 업데이트될 때마다 레이아웃을 다시 구성한다면, Virtual DOM은 DOM의 상태를 메모리에 넣어두고 변경이 있을 때만 업데이트한다. 즉, 화면에 그려지지 않고 아직 메모리에 있는 상태를 말한다.

실제 DOM에 바로 접근하지 않고 Virtual DOM에 먼저 변경 작업을 해주기 때문에 기존 방식보다 많은 양의 연산을 줄일 수 있다. 가상돔은 HTML 객체에 기반하여 자바스크립트 객체로 표현 가능하다.

위에서 사용한 예제 코드를 객체로 바꿔보자.

<html>
  <head>
  </head>
  <body>
    <div class="fruit-wrapper">
      <p class="fruit-item">Apple</p>
    </div>
  </body>
</html>
const virtual_dom = {
  tagName: 'html',
  children : [
    { tagName: 'head' },
    {
      tagName: 'body',
      children: [
        {
          tagName: 'div',
          attributes: { 'class' : 'fruit-wrapper' },
          children: [
           {
             tagName: 'p',
             attributes: { 'class' : 'fruit-item' },
             textContent : 'Apple'
           }
          ]
        }
      ]
    }
  ]
}

Virtual DOM은 하나의 객체가 아닌 내가 작업하는 곳만 작게 쪼개서 작업할 수 있다.
이는 객체이기 때문에 가능한 작업이며, 자유롭게 부분 부분을 업데이트 할 수 있다는 장점이 있다.

const fruit_list = {
  tagName: 'div',
  attributes: { 'class' : 'fruit-wrapper' },
  children: [
    {
      tagName: 'p',
      attributes: { 'class' : 'fruit-item' },
      textContent : 'Apple'
    }
  ]
}

Virtual DOM을 사용하여 첫 번째 "fruit-item"의 과일을 Orange로 바꾸고, 두 번째에 Melon을 추가해보자.

const new_fruit_list = {
  tagName: 'div',
  attributes: { 'class' : 'fruit-wrapper' },
  children: [
    {
      tagName: 'p',
      attributes: { 'class' : 'fruit-item' },
      textContent : 'Orange'
    },
    {
      tagName: 'p',
      attributes: { 'class' : 'fruit-item' },
      textContent : 'Melon'
    }
  ]
}

이제 fruit_list 객체와 new_fruit_list 객체를 비교하여 어디가 달라졌는지 비교하면 된다.
이렇게 하면 변경된 부분만 실제 DOM에 반영되기 때문에 아주 효율적으로 바뀐다.


Reflow와 Repaint

  • Reflow : 생성된 DOM 노드의 레이아웃 수치 변경 시 영향 받는 모든 노드(자신, 부모, 자식 등)의 수치를 다시 계산하여 렌더트리를 재생성하는 과정 ex) width, height ...
  • Repaint : Reflow 과정이 끝난 후 재생성된 렌더트리를 다시 그리는 과정 / 레이아웃 수치 변경과 관련 없는 요소 ex) background-color, outline ...

Reflow는 Repaint의 상위 개념으로 Reflow가 발생하면 Repaint도 발생한다.

하지만, Repaint 단독으로 발생하는 경우도 있다. Reflow는 레이아웃 변화로 일부 또는 전체를 다시 구성하고 그리지만, 만약 레이아웃 변경에 관련 없는 요소의 변화는 Reflow가 발생하지 않고 Repaint만 발생한다.


마무리하며

인기 있는 자바스크립트 라이브러리인 Vue와 React는 가상돔 환경에서 작동한다. 가상돔을 얼핏 들어보긴 했지만 무엇인지? 실제로 어디서 사용되는지는 전혀 알지 못했다.

개념과 작동 방식을 정확히 이해하기란 조금 어려웠지만 앞으로 진행될 프로젝트에서 Virtual DOM으로 레이아웃을 동작하고 있구나! 정도는 알 수 있을 것 같다 :-) 오늘도 뿌듯한 하루~!

1개의 댓글

comment-user-thumbnail
2020년 11월 25일

Reflow와 Repaint 면접질문에 나왔었는데 여기서 개념정리하고 갑니다 : )

답글 달기