VDOM

V-DOM ( Virtual DOM )

시작하기 전 앞서, 현대 Front-end 프레임워크에서 많이 사용하고 있는 V-DOM 에 대해서 알아봅시다.

DOM : Document Object Model

위에 보시는 것 처럼, DOM 이란놈이 우리가 사용하는 HTML문서에 대하여 구조적인 표현방법을 제공합니다.
DOM은,

  • Cross-Platform, Cross-Browser
  • Web page 구조 쉽게
  • Control 할 수 있는 API 제공
  • Manipulation 에서 다소 느리다 라는 특징이 있습니다.

기본적으로 Browser는, reflow나 repaint를 최대한 최적화 하여 동작합니다.
하지만, 다음과 같은 경우에 최적화를 무력화 시키는 경우가 존재합니다.

  • offsetTop, offsetLeft, offsetWidth, offsetHeight
  • scrollTop, clientTop
  • getcomputedStyle(), currentStyle ( IE 에서만 )

즉, DOM이 느린 것이 아니라, DOM Manipulation 할 때 발생하는
rendering calculation이 느린 것 입니다.

V-DOM은, DOM Manipulation의 횟수를 최소화하여 실제 DOM의 조작을 줄이는 것입니다.

자, 그럼 간단한 VDOM 예제를 볼까요?
아래와 같은 HTML Tag가 있습니다.

<ul class="list">
  <li>item1</li>
  <li>item2</li>
</ul>

이 TAG를 JSON으로 치환하면,

{ type: 'ul', props: { 'class': 'list' }, children: [
    { type: 'li', props: {}, children: ['item1'] },
    { type: 'li', props: {}, children: ['item2'] },
]}

이런 식으로 표현될 수 있겠죠?
이것을 다시 javascript Function 으로 사용할 수 있게 표현하면

function h(type, props, ...children) {
  return { type, props, children };
}

이렇게 되고,
JSON을 javascript단에서 이런 식으로 표현할 수 있습니다.

const tg = (
  h('ul', { prop: 'list' },
      h('li', {}, 'item1'),
      h('li', {}, 'item2'),
  );
);

이렇게 해서, DOM Element를 생성한 후에, append 하면 됩니다.

function createElement(node) {
  if (typeof node === 'string') {
    return document.createTextNode(node);
  }
  const $elm = document.createElement(node.type);
  node.children.map(createElement).forEach($elm.appendChild.bind($elm));
  return $elm;
}

const tg = (
  h('ul', { prop: 'list' },
      h('li', {}, 'item1'),
      h('li', {}, 'item2'),
  );
);

const $rootelm = document.getElementById('root');
$rootelm.appendChild(createElement(tg));

위 처럼 function으로 사용하는 경우도, React처럼 JSX 포맷에 맞추어 사용하는 경우도 있습니다.

하지만, 미리 계산해 놓는다는 특징 때문에, 정말로 신경써서 사용하지 않으면 메모리 이슈가 있을 수 있습니다.

VDOM이 항상 기존의 DOM과 비교하여 빠른 것은 아닙니다.

Comments