브라우저 렌더링과 성능
Table of Contents
브라우저 렌더링
성능 최적화를 위해, 브라우저가 어떻게 HTML 문서를 화면에 그리는지 과정에 대해 이해할 필요가 있습니다. 브라우저 렌더링은 아래 사진과 같은 흐름으로 이루어집니다.
- 서버로부터 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를 사용해보자 [성능 최적화]