VDOM

담당
황찬우
완료
완료
유형
React
비고

요약


Virtual DOM(가상 DOM)
Virtual DOM은 웹 애플리케이션의 성능을 개선하기 위한 개념으로, 실제 DOM에 직접 접근하지 않고 추상화된 자바스크립트 객체를 이용하여 DOM 조작을 수행합니다. 이를 통해 DOM 조작이 많이 발생하는 복잡한 웹 애플리케이션에서 성능을 향상시킬 수 있습니다. 데이터가 변하면 변경된 부분만 추상화된 가상 DOM에 적용하고, 이후에 한 번에 실제 DOM에 업데이트하여 불필요한 계산과 렌더링을 줄입니다.
 
React Diffing Algorithm
React에서는 Virtual DOM을 이용하여 DOM 업데이트를 최적화하는데, 이를 위해 변경 사항을 효율적으로 파악하는 알고리즘
  1. 엘리먼트의 타입이 다른 경우: 두 엘리먼트를 완전히 새로 구축하여 업데이트합니다.
  1. DOM 엘리먼트의 타입이 같은 경우: 속성을 비교하고 변경된 부분만 갱신합니다.
  1. 같은 타입의 컴포넌트 엘리먼트: 인스턴스는 유지하며 props만 갱신합니다.
  1. 자식 엘리먼트 재귀적 처리: 자식 엘리먼트들을 순차적으로 비교하고 갱신합니다. 이때 키(Key)를 활용하여 변경된 부분을 파악합니다.
 
 

Virtual DOM(가상 DOM)


Virtual DOM을 사용하면 실제 DOM에 접근하여 조작하는 대신, 이를 추상화한 자바스크립트 객체를 구성하여 사용합니다.
 
DOM에 변화가 생기면, 렌더트리를 재생성하고 레이아웃을 만들고 페인팅을 하는 과정이 반복됩니다. 복잡한 웹 어플리케이션에서는 DOM 조작이 많이 발생합니다. 그 변화를 적용하기 위해 브라우저가 많이 연산을 해야되므로 전체적인 성능을 비효율적으로 만듭니다.
여기서 VDOM을 사용하면 뷰에 변화가 있을 때 그 변화를 실제 DOM에 적용하기 전에 가상 DOM에 먼저 적용시키고, 그 최종적인 결과를 실제 DOM에 전달해줍니다, 그 결과 브라우저 내에서 발생하는 연산의 양을 줄이면서 성능이 개선되는 효과가 발생합니다.
 

리액트에서 데이터가 변하여 웹 브라우저에 실제 DOM을 업데이트하는 과정

notion image
  1. 데이터를 업데이트하면 전체 UI를 Virtual DOM에 리렌더링합니다.
  1. 이전 가상 DOM과 변경된 새로운 가상 DOM을 비교합니다.
  1. 재조정(Reconciliation)을 통해 변경된 부분만 실제 DOM에 업데이트합니다.
  1. 일괄 업데이트(Batch Update)로 여러 개의 상태 변경이 일어날 때 이를 한 번에 업데이트합니다.
 

Virtual DOM 장점

  • Diffing 알고리즘을 통해 변경 사항만 업데이트하므로 전체 DOM 리렌더링보다 효율적입니다.
  • 변경 사항을 최소화하므로 불필요한 계산과 렌더링을 줄일 수 있습니다 (Reflow, Repaint, Composite 같은 변화를 한번에 처리해주기 때문에 렌더링 횟수를 줄여준다)
 
 

React Diffing Algorithm


 
React가 DOM 트리를 탐색하는 방법
React는 만약 이전 가상 DOM과 새로운 가상 DOM의 엘리먼트 타입이 다르다면, React는 이전 트리를 버리고 새로운 트리를 구성하여 전체 엘리먼트를 다시 렌더링합니다. 트리의 레벨 순서대로 순회하는 방식으로 탐색, 즉 같은 레벨(위치)끼리 비교합니다. 이는 너비 우선 탐색(BFS)의 일종이라고 볼 수 있습니다.
 

Diffing Algorithm

  1. 엘리먼트의 타입이 다른 경우
      • 두 루트 엘리먼트의 타입이 다르면, React는 이전 트리를 버리고 완전히 새로운 트리를 구축합니다.
      • 트리를 버릴 때 이전 DOM 노드들은 모두 파괴합니다. 루트 엘리먼트 아래의 모든 컴포넌트도 언마운트되고 그 state도 사라집니다.
  1. DOM 엘리먼트의 타입이 같은 경우
      • 같은 타입의 두 React DOM 엘리먼트를 비교할 때, React DOM 엘리먼트의 속성을 확인하여, 동일한 내역은 유지하고 변경된 속성들만 갱신합니다.
      • DOM 노드의 처리가 끝나면, React는 이어서 해당 노드의 자식들을 재귀적으로 처리합니다,
  1. 같은 타입의 컴포넌트 엘리먼트
      • 컴포넌트가 갱신되면 인스턴스는 동일하게 유지되어 렌더링 간 state가 유지됩니다.
      • React는 새로운 엘리먼트의 내용을 반영하기 위해 현재 컴포넌트 인스턴스의 props를 갱신합니다.
  1. 자식 엘리먼트 재귀적 처리
      • 만약 엘리먼트의 자식 요소가 변경되었다면, React는 이전 자식 노드와 새로운 자식 노드를 순차적으로 위에서부터 아래로 비교합니다.
      • 이때, 만약 자식 엘리먼트의 순서가 바뀌었더라도, React는 각각의 엘리먼트를 고유한 key 값으로 식별하여 올바른 업데이트를 수행합니다.
  1. 키(Key)의 활용
      • 키(Key)는 엘리먼트를 고유하게 식별하는 데 사용되며, 형제 엘리먼트 간에만 유일하면 됩니다.
      • React는 키를 통해 이전과 새로운 가상 DOM에서 동일한 엘리먼트인지 식별하여 효율적인 업데이트를 수행합니다.
      • 인덱스를 key로 사용하면 항목들이 재배열되는 경우 비효율적으로 동작할 것입니다. 항목의 순서가 바뀌었을 때 key 또한 바뀔것이므로, 컴포넌트의 state가 엉망이 되거나 의도하지 않은 방식으로 바뀔 수도 있습니다,
 

참고 자료


리액트를 다루는 기술