Virtual DOM

MODAC·2023년 1월 29일

Virtual DOM

DOM(Document Object Model)은 자바스크립트가 접근하고 탐색하기 쉽도록 브라우저가 HTML,CSS 요소를 객체화시킨 모델입니다. 트리구조로 형성된 DOM은 트리구조의 특성 상 접근 및 탐색속도가 빠르지만 변경사항을 반영하기 위해 변경 사항 외의 모든 요소를 재랜더링하게 됩니다. 이 과정에서 브라우저는 리플로우되어 변경사항 외의 불필요한 연산을 사용합니다.

좀 더 효율적인 랜더링

기존 DOM의 단점을 보완하고자 바뀐 부분만 비교해서 그 부분만 렌더링을 하기 위해 REACT는 Virtual DOM을 사용합니다. REACT는 새로운 요소를 트리구조로 표현하여 가상의 DOM을 그려내고 변경사항을 새로운 가상의 DOM으로 만듭니다. 이 후 두 가상의 DOM을 비교한 후 실제 DOM에 적용 가능한 최적화된 작업을 수행합니다. 즉 Virtual DOM은 계획 단계이며 Real DOM은 수행 단계로 수행 단계에 사용될 브라우저의 불필요한 연산을 줄일 수 있게 됩니다.

Virtual DOM의 구조

가상 DOM은 추상화된 자바스크립트 객체의 형태를 가지고 있습니다.

const virtualDom = {
    tagName: "html",
    children: [
        { tagName: "head" },
        { tagName: "body",
            children: [
                tagName: "ul",
                attributes: { "class": "list"},
                children: [
                    {
                        tagName: "li",
                        attributes: { "class": "list_item" },
                        textContent: "List item"
                    }
                ]
            ]
        }
    ]
}

자바스크립트로 표현한 가상 돔입니다. HTML 문서 객체를 기반으로 합니다. 또한 추상화만 되었을 뿐 평범한 자바스크립트 객체이므로 실제 DOM을 건드리지 않고도 필요한 만큼 자유롭게 조작할 수 있습니다.

Virtual DOM의 탐색 방법

React는 기존의 가상 DOM 트리와 새롭게 변경된 가상 DOM 트리를 비교할 때, 트리의 레벨 순서대로 순회하는 방식(BFS: 너비 우선 탐색)으로 탐색합니다.

  • 태그가 달라질 때

    HTML 규칙에 따라 부모 태그가 Ul일 때 자식 태그는 Li가 와야 합니다. 부모 태그와 자식 태그 사용이 제한되어 있는 규칙으로 인해 REACT는 부모 태그가 변경되면 자식 노드를 어마운트, 즉 파괴하며 규칙에 맞는지 확인한 후 새로운 트리를 구축합니다.
    ```js
    <div>
      <Counter />
    </div>
    //부모 태그가 div에서 span으로 바뀝니다.  
    ```
  • 태그가 동일할 때

    수정할 타입이 없다면 React는 불필요한 랜더링을 없애기 위해 최소한의 변경사항만 반영합니다.
//className이 before인 컴포넌트
<div style={{color: 'red', fontWeight: 'bold"}} title="stuff" />

//className이 after인 컴포넌트
<div style={{color: 'green', fontWeight: 'bold"}} title="stuff" />
  • 자식 노드의 재귀적 처리

    REACT의 탐색은 위에서 아래로 비교하며 흐르기 떄문에 추가된 자식 노드로 인해 순서가 밀리면 변경할 필요가 없는 기존 자식 노드도 어마운트됩니다. 이러한 비효율을 막기 위해 Key 속성을 지원하여 Key를 이용해 리랜더링이 필요없는 노드를 인식하고 변경된 부분만 추가가 가능합니다.
<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

//key가 2014인 자식 엘리먼트를 처음에 추가합니다.
<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

0개의 댓글