브라우저 렌더링 방식
렌더링(rendering)
- HTML, CSS, JavaScript 등 개발자가 작성한 문서가 브라우저에서 출력되는 과정
- 브라우저의 렌더링 엔진을 통해 렌더링이 수행됨
브라우저의 렌더링 과정
- 브라우저를 통해 사용자가 웹 사이트에 접속
- 브라우저는 서버로부터 HTML, CSS, JavaScript와 같은 웹사이트에 필요한 리소스를 다운 받음
- 렌더링 엔진은 전달받은 HTML 문서를 파싱(parsing)해 DOM 트리를 만듦
- 다운받은 외부 CSS 파일과 함께 포함된 스타일 요소를 파싱(parsing)해 CSSOM 트리를 만듦
- DOM 트리와 CSSOM 트리를 결합해 Render 트리를 구축
- 레이아웃 과정을 통해 각 요소를 어디에 배치할지 결정
- paint: 레이아웃 과정이 끝나면 UI 백엔드에서 Render 트리를 화면에 그리기 시작
(참고) 렌더링 관련 용어
파싱(Parsing)
- 프로그래밍 언어로 작성된 파일을 실행시키기 위해 구문 분석(syntax analysis)을 하는 단계
- 일종의 인터프리터나 컴파일러 구성 요소 가운데 하나인 파서(parser)를 통해 파싱을 진행함
- 파서는 HTML 파일의 코드를 문법적 의미를 갖는 최소 단위인 토큰(token)으로 분해함
- 이 토큰들을 문법적 의미와 구조에 따라 노드(node)라는 요소로 바꿈
- 파스 트리(parse tree), 혹은 문법 트리(syntax tree): 노드들이 상하 관계에 따라 하나의 트리로 형성된 것
- 특징
- 문서에 작성된 언어 또는 형식의 규칙에 따름
- 파싱할 수 있는 모든 형식은 정해진 용어와 구문 규칙에 따라야 함
- 형식을 잘 갖춘 문서일수록 파싱 과정이 직관적이고 빠르게 진행됨
문서 파싱(document parsing)
- 브라우저가 코드를 이해하고 사용할 수 있는 구조로 변환하는 것
- 렌더링 과정에서는 HTML 파일을 바탕으로 DOM 트리를 구축하고 및 CSS 파일로 CSSOM 트리를 만드는 것을 의미
브라우저 렌더링 과정
1. HTML 문서를 DOM 트리로 파싱하기
- 이때 HTML 토큰이 만들어지는데, 이 토큰에는 시작 태그와 마침 태그가 포함되고, 속성 이름과 값도 포함
- 이런 토큰으로 변한 입력 값이 파서에 의해 노드가 되고, 최종적으로 트리 구조의 DOM으로 구성됨
- CSSOM 트리 파싱하기
- HTML 문서를 파싱하면서
<link>
, <style>
태그 만날 경우 텍스트를 CSS 스타일링 레이아웃과 페인팅에 사용하는 데이터 구조인 CSSOM으로 파싱
script
태그를 만날 경우 렌더링을 차단하면서 HTML 파싱 또한 중단
- 이어 script 파일을 다운 받아 파싱하고 실행시킨 뒤 다시 HTML 파일을 파싱
DOM Tree
- DOM(Document Object Model, 문서 객체 모델)
HTML문서의 요소들의 중첩 관계를 기반으로 노드들을 트리 구조로 구성한 것을 의미
- DOM 트리: 브라우저가 이해할 수 있는 객체 형태로 바꿔준 것
브라우저는 JavaScript 언어만 알아듣기 때문에 HTML의 태그나 속성들을 이해하지 못하고, response로 받아온 HTML 문서는 텍스트로만 이뤄져 있으므로 DOM 트리 형태로 바꿔줘야함
CSSOM Tree
- CSSOM(CSS Object Model, CSS 객체 모델)
- html 파일을 DOM 트리로 파싱하던 브라우저가
<link>
, <style>
태그를 만나게 되면 파싱을 잠시 멈추고 해당 리소스 파일을 서버로 요청하여 해당 파일을 파싱해 만든 트리
- CSSOM 트리를 구축하고 나면 브라우저는 다시 html 파일의 파싱을 멈췄던 부분으로 돌아가서 마저 DOM 트리를 구축함
- CSS는 부모의 속성을 자식이 상속 받음
Render Tree
- 렌더링을 하기 위해 서로 다른 속성을 가진 독립적인 트리인 DOM 트리와 CSSOM 트리를 합치는 작업
- 사용자에게 브라우저가 보여주고자 하는 화면을 그리는 과정이므로, 사용자에게 보여주지 않아도 되거나, 보여주지 말아야 할 태그나 요소는 렌더 트리에서 제외됨
- DOM 트리의
<meta>
나 CSSOM 트리의 display:none
레이아웃
- 렌더 트리를 기반으로 HTML 요소의 레이아웃(위치, 크기 등)을 계산하여 브라우저 화면 어디에 배치할지 결정하는 과정
- 브라우저는 각 요소들이 전체 화면에서 어디에, 어떤 크기로, 어떻게 배치가 되어야 하는지 파악하기 위해 렌더 트리를 위에서 아래로 읽고 모든 값을 절대적인 단위인 px 값으로 변환
페인팅
- 레이아웃에서 결정된 대로 브라우저가 화면에 출력하는 과정
- 픽셀에 대한 정보들을 바탕으로 픽셀을 채워나가는 과정
- 텍스트에 불과한 HTML 파일의 내용들이 이미지화된 모습으로 브라우저 화면에 띄워짐
리플로우와 리페인트
의미
- 리플로우: 어떤 웹 인터랙션으로 인해 렌더링 과정의 레이아웃을 반복해 수행하는 것
- 리페인트: 어떤 웹 인터랙션으로 인해 렌더링 과정의 페인트 과정을 반복해 수행하는 것
문제점
- 매끄러운 UX 경험을 위해서는 1초 안에 브라우저는 60장 가량의 레이아웃과 페인트 과정을 동시에 처리해야함
- DOM이 변경이 되면 렌더 트리를 다시 구축하기 때문에 변경이 될 때마다 리플로우와 리페인트를 다시 해야함
- 리플로우 하는 과정은 렌더링을 다시 하는 것이기 때문에 배치를 위한 연산을 해야 해 실제로 CPU를 많이 차지
- 리페인트는 페인트를 다시 하는 것이라 픽셀을 다시 화면에 찍어 그려야 하기 때문에 GPU를 많이 차지
- 프레임 드랍(Frame Drop) 현상
- 초당 60프레임으로 유지시키던 프레임의 수가 브라우저의 과부하로 인해 줄어드는 현상
- 드랍, 즉 없어진 프레임은 렌더링 엔진이 인식할 수 없기 때문에 드랍된 프레임을 브라우저 화면에 그리지 못함
개선 방법
- 레이아웃과 페인트 과정은 별개의 과정처럼 보일 수 있으나 리플로우 시 리페인트는 필연적으로 일어나므로 가능하다면 리플로우가 발생하는 속성보다 리페인트만 발생하는 속성을 사용하기
- 페인트 과정은 유저에게 화면을 보여주기 위해 그리는 과정이라 필수적인 과정이기 때문
- 불필요한 레이아웃 줄이기
- CSSOM 트리의 CSS 속성 중에 레이아웃을 발생시키는 속성을 사용하면 그때마다 변경이 되어 렌더 트리를 만들고, 레이아웃을 발생시키고, 페인트를 하는 과정이 연속적으로 발생함
- 따라서 이런 레이아웃을 발생시키는 속성을 피하면 해당 과정이 발생하는 횟수를 줄일 수 있음
- 영향을 주는 노드를 줄이기
- JavaScript + CSS를 조합한 애니메이션이 많거나, 레이아웃 변화가 많은 요소의 경우 position을
absolute
또는 fixed
를 사용해 영향을 받는 주변 노드들을 줄이기
- fixed와 같이 영향을 받는 노드가 전혀 없는 경우 리플로우 과정이 필요 없기 때문에 리페인트 연산 비용만 들기 때문
CSS에서 레이아웃, 페인트를 발생시키는 속성들
리플로우가 일어나는 속성
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 | ... | |
- 대안)
transform
속성 사용하기
transform에 있는 translate를 사용하면 좌표 값을 사용해 위치를 이동하지만, 레이아웃을 발생시키지 않고 페인트만 다시 발생시키는 쪽으로 렌더링 과정이 일어나기 때문에 유지하고자 하는 프레임 수를 기대할 수 있음
리페인트가 일어나는 속성
background | background-image | background-position | background-repeat | background-size | border-radius |
---|
border-style | box-shadow | color | line-style | outline | clear |
display | float | font-family | font-size | font-weight | outline-color |
visibility | ... | | | | |
참고
https://www.w3schools.com/js/js_htmldom.asp
https://www.hongkiat.com/blog/css-object-model-cssom/
https://web.dev/critical-rendering-path-render-tree-construction/