[React] Virtual DOM은 왜 렌더링이 빠를까?

seohyun Kang·2023년 4월 20일
0

CRP(Critical Rendering Path)

브라우저의 렌더링 과정을 CRP(Critical Rendering Path)라고 하며 CRP는 렌더링 엔진이 처리해야 할 일련의 단계를 나타내는 모델입니다.

CRP의 단계는 아래와 같습니다.

  1. 토큰화 : 브라우저는 웹 페이지의 HTML 코드를 문자열 형태로 읽어들입니다. 그리고 이 문자열을 태그, 속성, 텍스트 등의 토큰으로 분리합니다.

  2. HTML 다운로드 및 파싱: 브라우저는 서버에서 HTML을 다운로드하고 파싱하여 페이지의 DOM(Document Object Model)을 생성합니다.

  3. CSS 다운로드 및 파싱: 브라우저는 서버에서 CSS를 다운로드하고 파싱하여 스타일 규칙을 생성합니다.

  4. Render Tree 생성: 브라우저는 DOM과 스타일 정보를 결합하여 Render Tree를 생성합니다. Render Tree는 렌더링 엔진이 페이지를 렌더링하는 데 필요한 노드의 집합입니다.

  5. 레이아웃: 브라우저는 Render Tree의 노드들을 레이아웃하여 페이지의 레이아웃을 생성합니다.

  6. 페인트: 브라우저는 레이아웃된 페이지를 화면에 그립니다.

DOM Mutation

DOM을 수정하면 변경 사항이 발생할 때마다 렌더링 엔진이 매번 전체 DOM을 다시 계산해야 합니다. DOM은 계층 구조로 이루어져 있으므로 모든 하위 노드를 재귀적으로 확인해야 하며, 이는 큰 규모의 애플리케이션에서 성능 문제를 발생시킬 수 있습니다.

DOM Tree에 변경사항이 발생하면 렌더링 엔진은 아래와 같은 단계를 수행합니다.

  1. DOM 수정(DOM Mutation): JavaScript 코드를 실행하여 DOM 트리의 일부를 수정하면, 브라우저는 해당 변경 내용을 기록합니다.

  2. 스타일링(Styling): DOM 수정이 일어나면, 브라우저는 해당 변경 내용에 따라 CSS 스타일을 다시 계산합니다.

  3. 레이아웃(Layout): CSS 스타일이 변경되면, 브라우저는 뷰포트 내에서 요소의 위치와 크기를 다시 계산합니다.

  4. 페인팅(Painting): 브라우저는 변경된 내용을 기반으로 요소를 다시 그리고, 최종적으로 뷰포트에 렌더링합니다.

Virtual DOM

The Virtual DOM (VDOM) is a programming concept where an ideal, or “virtual”, representation of a UI is kept in memory and synced with the “real” DOM by a library such as ReactDOM. This process is called reconciliation.

A. Diffing

Virtual DOM의 Diffing은 이전 Virtual DOM과 새로운 Virtual DOM 간의 차이점을 찾아내는 과정입니다.

Diffing 알고리즘은 다음과 같은 과정을 거칩니다.

  1. 이전 Virtual DOM과 새로운 Virtual DOM의 루트 노드를 비교합니다.
  2. 루트 노드가 동일하면, 해당 노드의 자식 노드들을 비교합니다.
  3. 자식 노드들을 비교하면서, 이전 Virtual DOM과 새로운 Virtual DOM에서 동일한 위치에 있는 노드를 찾습니다.
  4. 동일한 위치에 있는 노드가 다르면, 해당 노드를 업데이트합니다.
  5. 만약 동일한 위치에 있는 노드가 없다면, 해당 위치에 새로운 노드를 추가합니다.
  6. 만약 새로운 Virtual DOM에서 이전 Virtual DOM에 없는 노드가 있다면, 해당 노드를 추가합니다.

Diffing 알고리즘은 이전 Virtual DOM과 새로운 Virtual DOM 간의 차이점을 효율적으로 찾아내기 위해, 노드를 순회하면서 가능한한 빠르게 비교합니다. 이를 통해 최소한의 DOM 조작만을 수행하여 렌더링 속도를 향상시킬 수 있습니다.

B. Reconsiliation

Reconciliation은 변경된 부분에 대해서만 DOM 조작을 수행하는 과정입니다. Diffing 후에 변경된 부분을 기반으로 DOM 조작을 수행하기 때문에, 불필요한 DOM 조작을 최소화하여 렌더링 성능을 향상시킵니다.

Reconciliation은 다음과 같은 알고리즘을 사용하여 수행됩니다.

  1. 동일한 컴포넌트 비교
    이전 Virtual DOM과 새로운 Virtual DOM에서 동일한 컴포넌트를 비교합니다. 만약 컴포넌트가 동일하면, 해당 컴포넌트의 자식 컴포넌트들도 비교합니다.

  2. 다른 컴포넌트 비교
    이전 Virtual DOM과 새로운 Virtual DOM에서 다른 컴포넌트를 비교합니다. 이 경우, 해당 컴포넌트를 다시 생성하여 새로운 Virtual DOM을 만듭니다.

  3. 키(Key)를 사용한 비교
    이전 Virtual DOM과 새로운 Virtual DOM에서 키(Key)를 사용하여 비교합니다. 키(Key)는 각각의 요소를 고유하게 식별하는 값으로, 이를 사용하여 각각의 요소를 비교합니다. 만약 동일한 키를 가진 요소가 있으면, 해당 요소의 props와 자식 요소를 비교합니다. 그렇지 않은 경우, 해당 요소를 다시 생성하여 새로운 Virtual DOM을 만듭니다.

결론

직접 DOM을 조작하면 변경 사항이 발생할 때마다 렌더링 엔진이 매번 전체 DOM을 다시 계산해야 합니다. DOM은 계층 구조로 이루어져 있으므로 모든 하위 노드를 재귀적으로 확인하는 과정에서 성능저하가 발생하게 됩니다.

반면에, Virtual DOM을 사용하는 경우 Memory 상에서 Diffing을 통해 이전 Virtual DOM과 새로운 Virtual DOM의 차이점을 찾아내고 Reconsiliation을 통해 변경된 부분에 대해서 아래와 같은 작업을 수행합니다.

  1. 변경된 부분에 대해서만 DOM 조작을 수행합니다.
  2. 변경된 컴포넌트의 라이프사이클 메소드를 호출합니다.
  3. 변경된 부분과 연관된 이벤트 리스너를 등록합니다.
  4. 변경된 컴포넌트의 자식 컴포넌트에 대해서도 Diffing과 Reconciliation 과정을 수행합니다.

결과적으로 Virtual DOM을 사용하면 변경된 부분만 렌더링이 가능하기 때문에 성능이 좋아집니다.


Reference :
1. CRP(Critical Rendering Path)
2. React Virtual DOM

1개의 댓글

comment-user-thumbnail
2023년 10월 23일

와 정말 도움이 되는 글이에요

답글 달기