브라우저 렌더링과 성능

Table of Contents

브라우저 렌더링

성능 최적화를 위해, 브라우저가 어떻게 HTML 문서를 화면에 그리는지 과정에 대해 이해할 필요가 있습니다. 브라우저 렌더링은 아래 사진과 같은 흐름으로 이루어집니다.

Untitled

  • 서버로부터 HTML, CSS, JavaScript 파일을 받아와 HTML → DOM, CSS → CSSOM으로 변환하고 Render Tree를 구성합니다.
  • Render Tree의 노드들에 대한 위치와 크기를 계산합니다. Render Tree의 루트부터 시작하여 모든 노드에 대해 계산을 수행합니다. (Layout)
  • 계산된 결과물을 기반으로 화면에 실제 노드들을 그립니다. (Paint)
  • 사용자의 상호작용이나 스크립트를 통한 제어 등으로 HTML 요소의 크기나 위치의 변경이 일어나면 Reflow라는 과정을 수행합니다.
    • Reflow는 Render Tree 구성부터 모든 작업을 다시 수행합니다.
    • 만약 레이아웃 자체에는 변화가 없고, 색상이나 visibility 등의 변경만 있는 경우에는 Paint 과정만을 다시 수행합니다. (Repaint)
    • 따라서 비용이 큰 Reflow의 발생을 최대한 줄이는 것이 중요합니다.

이거 되게 좋은 내용인 것 같아요 CSS의 will-change를 통헤 불필요한 GPU 점유를 줄이는 방법도 소개하고 있네요!

성능을 최적화하는 방법

DocumentFragment를 사용

앞에 정리한 내용과 같이 브라우저 성능에 가장 영향을 미치는 부분은 Reflow 과정입니다. 즉 Reflow의 발생을 줄이면 큰 성능 향상을 노릴 수 있는 것이다. 보통은 스크립트를 통해 요소의 레이아웃을 제어하는 코드는 한 번에 실행되지 않습니다. 즉 여러 줄에 걸쳐 레이아웃을 수정하는 경우 각 행에 대해 Reflow가 발생합니다. - 브라우저에 따라 일부 최적화가 이루어지는 경우가 있음

따라서 모든 수정이 완료된 후에 최종 결과물에 대해서만 Reflow를 수행할 필요가 있습니다. DocumentFragment가 그 해결책 중 하나인데, DocumentFragment란 React의 버추얼 DOM과 비슷한 개념으로, DOM과 비슷하게 동작하지만 실제 HTML DOM에는 영향을 주지 않는 Document의 가벼운 버전입니다.

DocumentFragment은 렌더링 자체가 이루어지지 않기 때문에 Reflow 걱정 없이 변경이 가능합니다. 따라서 DocumentFragment 내부에서 레이아웃을 변경하고, 최종 결과물을 HTML DOM에 삽입하면 불필요한 Reflow 발생을 막을 수 있습니다. 아래는 간단한 사용 예시입니다.

const documentFragment = new DocumentFragment();
// const documentFragment = document.createDocumentFragment();

const div = document.createElement("div");
// do something...

document.getElementById("parent-to-append").appendChild(documentFragment);

Canvas 사용

일반적으로 페이지 내의 요소가 많아질수록 레이아웃 계산 과정에서의 계산량이 많아집니다. 9개의 div가 3*3으로 나열되어 있다고 하면, 그 중 하나의 div의 크기가 변경됨에 따라 나머지 8개의 div도 레이아웃 재계산이 일어납니다. 크기가 고정된 부모 요소로 분리되어 있다면 그 내부의 요소들만 재계산이 일어나지만, 만약 그렇지 않은 경우 문서 전체를 다시 계산해야 할 가능성도 있습니다.

따라서 복잡한 시각 효과를 연출하거나, 많은 Element를 가진 요소들을 제어해야 하는 경우에는 canvas를 이용하여 렌더링하는 것이 효과적일 수 있습니다. canvas는 정해진 캔버스 영역 안에서만 렌더링이 일어나기 때문에 Reflow를 방지할 수 있기 때문이죠.

Refs.

JavaScript 최적화: DOM 핸들링 속도 개선
브라우저 렌더링 순서와 원리
브라우저 렌더링
주소창에 www.google.com을 입력했을 때 일어나는 과정
DocumentFragment - Web API | MDN
Javascript - DocumentFragment를 사용해보자 [성능 최적화]