⭐️ 브라우저 렌더링 동작 과정
브라우저가 서버에서 페이지에 대한 HTML 응답을 받고 화면에 표시하기 전에 여러 단계가 있다. 이를 웹 페이지 빌드 과정(Critical Rendering Path, CRP)이라고 한다.
그 전에 렌더링 엔진이 무엇인지 알아야 한다.
렌더링 엔진에 대하여..
브라우저의 기본 구조는 다음과 같다.
렌더링 엔진은 URI를 통해 요청 받은 내용을 브라우저 화면에 표시하는 역할을 한다.
대표적으로 사파리와 크롬은 Webkit 이라는 렌더링 엔진을 사용한다.
렌더링 엔진이 하는 일
1. Dom tree 구축
2. Render tree 구축
3. Render tree 배치
4. Render tree 그리기
* DOM tree가 완벽하게 구축되고 나서 Render tree가 배치, 그려지는 순서가 아니고, DOM tree가 완성되는 중간중간에 Render tree가 그려지는 병렬적인 실행이 이루어진다.
webkit의 동작 과정이다.
브라우저 렌더링 동작 과정을 간단하게 정리하면 다음과 같다. 웹 브라우저가 HTML 문서를 읽고, 스타일을 입히고 뷰포트에 표시하는 과정을 살펴보자.
- Parsing - 서버로부터 받은 HTML 파일과 CSS 파일 문서를 렌더링 엔진이 읽고 파싱 하여 각각 Tree를 생성한다. (HTML은 DOM으로, CSS는 CSSOM으로 만들어진다.)
- Attachment - 두 Tree를 결합하여 Render Tree를 생성한다.
- Layout(Reflow) - Render Tree에서 각 노드들의 위치와 크기를 계산한다.
- Painting - 계산된 값을 이용하여 각 노드를 화면상의 실제 픽셀로 변환하고, 레이어를 만든다.
- Composite - 레이어를 합성하여 실제 화면에 나타낸다.
Parsing
HTML 파일을 해석하여 DOM(Document Object Model) Tree를 생성하는 단계이다. 다시 말해, 웹 브라우저와 Javascript가 이해하기 쉽도록 HTML Parser가 HTML을 트리 구조 객체 DOM으로 변환시키는 것이다. (Javascript로 조작 가능하도록 변환하여 동적 상호작용이 가능해지도록 하기 위함)
* HTML5에서는 <script> 태그를 비동기로 처리하는 속성을 추가했다. (참고: script의 속성 async와 defer)
파싱 중 HTML에 CSS가 포함되어 있다면 DOM에 CSS가 적용된 객체 모델 CSSOM(CSS Object Model) Tree 구성 작업도 함께 진행한다.
Attachment
Parsing 단계에서 생성된 DOM Tree와 CSSOM Tree를 합쳐 실제로 화면에 그려질 Render Tree를 구성한다.
순수한 요소들의 구조와 텍스트만 존재하는 DOM 트리와는 달리 Render Tree는 스타일 정보가 설정되어 있으며 실제 화면에 표현되는 노드들로만 구성된다.
따라서 CSS 속성에 따라 화면에 보이지 않는 Element는 제외되기도 한다. visibility: hidden 은 요소가 공간을 차지하고 보이지만 않기 때문에 Render Tree에 포함되지만, display:none의 경우 Render Tree에서 제외된다.
Layout or Reflow
Render Tree를 기기의 뷰포트 화면 내에서 어떻게 배치해야 할 것인지 루트부터 노드를 순회하면서 노드의 정확한 위치와 크기를 계산하고 Render Tree에 반영한다.
Layout 과정 즉, 리플로우는 최초 한 번만 실행되고 끝나는 것이 아닌 width, height, left, top, offsetHeight, offsetWidth, scrollTop 등 수치를 계산해 새로운 위치에 나타나게 하는 동작이 일어날 때마다 반복해서 실행된다.
크기 값을 %로 지정하였다면, 이 단계에서 % 값을 계산하여 픽셀 단위로 변환한다. 즉 상대적인 위치나 크기의 속성은 실제 화면에 그려지는 절대적인 px 단위로 계산되어 변환된다.
Painting or Repaint
Layout 단계에서 계산된 값을 이용해 Render Tree의 각 노드를 화면상의 실제 픽셀로 변환하여 화면에 그리는 단계이다. 이때 픽셀로 변환된 결과는 하나의 레이어가 아니라 여러 개의 레이어로 관리된다. 처리해야 하는 스타일이 복잡할수록 Paint 단계에 소요되는 시간도 증가한다.
Composite
Paint 단계에서 생성된 레이어를 합성하여 실제 화면에 나타낸다. 화면에서 웹 페이지를 볼 수 있다.
🚀 렌더링 최적화
렌더링 과정을 모두 마친 후 최종적으로 브라우저에 페이지가 그려진다고 해서 렌더링 과정이 모두 끝난 것이 아니다.
특정 액션이나 이벤트에 따라 HTML 요소의 크기나 위치 등 레이아웃 수치를 수정하면 그에 영향받는 자식 노드나 부모 노드들을 포함하여 Layout(Reflow) 과정을 다시 수행하게 된다.
이렇게 되면 Render Tree와 각 요소들의 크기, 위치를 다시 계산하게 되는데 이 과정을 Reflow라고 하며, Reflow 된 Render Tree를 다시 화면에 그리는 과정을 Repaint라고 한다.
Reflow
Reflow가 일어나는 대표적인 경우는 아래와 같다.
- 페이지 초기 렌더링 시 (최초 Layout 과정)
- 브라우저 리사이징 시 (Viewport 크기 변경)
- 노드 추가 또는 제거
- 요소의 위치, 크기 변경
- 폰트 변경과 이미지 크기 변경
Repaint
Reflow만 수행되면 실제 화면에는 반영되지 않기 때문에 다시 Painting이 일어나야 한다. 이 과정을 Repaint라고 한다.
무조건 Reflow가 발생해야 Repaint가 수행되는 것은 아니다. background-color, opacity와 같이 레이아웃에 영향을 주지 않는 스타일 속성이 변경되었을 때는 Reflow를 수행할 필요가 없기 때문에 Repaint만 수행하게 된다.
📌 렌더링 최적화 방법
1️⃣ Reflow 최소화하기
브라우저가 렌더링을 더 빠르고 효율적으로 할 수 있도록 개발하기 위해서는 Reflow 과정을 최소화하는 것이 좋다.
Reflow가 발생하면 필연적으로 Repaint가 일어나기 때문에 렌더링 최적화에 좋지 않은 영향을 준다. 그러므로 Reflow가 발생하는 속성보다 Repaint만 발생하는 속성을 사용하는 것이 좋다.
[ Reflow가 일어나는 대표적인 속성 ]
position, width, height, left, top, right, bottom, margin, padding, border, border-width, clear, display, float, font-family, font-size, font-weight, line-height, min-height, overflow, text-align, vertical-align, white-space...
[ Repaint가 일어나는 대표적인 속성 ]
background, background-image, background-position, background-repeat, background-size, border-radius, border-style, box-shadow, color, line-style, outline, outline-color, outline-style, outline-width, text-decoration, visibilty...
2️⃣ 영향을 주는 노드 최소화하기
JavaScript와 CSS를 조합해 애니메이션이나 레이아웃 변화가 많은 요소의 경우, position을 absolute 또는 fixed를 사용하여 영향을 받는 주변 노드들을 줄일 수 있다.
fixed와 같이 영향을 받는 노드가 전혀 없는 경우, Reflow 과정이 전혀 필요 없어지기 때문에 Repaint 연산 비용만 들게 되어 효율적이다.
3️⃣프레임 줄이기
단순하게 생각하면 0.1초마다 1px씩 이동하는 요소보다 0.3초마다 3px씩 이동하는 요소가 Reflow 연산 비용이 3배가 줄어든다고 볼 수 있다. 따라서 부드러운 효과를 조금 줄이면서 성능 개선을 할 수 있다.
참고
https://d2.naver.com/helloworld/59361
'Devlog > Web' 카테고리의 다른 글
Flask Framework 이해하기 (0) | 2022.07.22 |
---|---|
Node.js 란? (0) | 2022.04.06 |
CORS(Cross-Origin Resource Sharing) (0) | 2021.07.05 |
Encoding & Decoding (0) | 2021.06.08 |
웹페이지 HTTP 헤더를 커스텀하게 변경할 수 있는 ModHeader (0) | 2021.04.06 |