중요 렌더링 경로란 무엇일까요
중요 렌더링 경로(Critical Rendering Path, CRP)
브라우저가 HTML, CSS, Javascript를 화면에 픽셀로 변화하는 일련의 단계
- 이를 최적화 하는 것은 렌더링 성능을 향상시킴
- 다음을 포함: DOM, CSSOM, 렌더 트리, 레이아웃
DOM(Document Object Model)
- HTML을 분석함으로써 만들어짐
- HTML은 Javascript를 요청할 수 있음
- 이 경우 DOM이 변경될 수 있음
CSSOM
- HTML은 차례대로 CSS 오브젝트 모델을 만들기 위한 스타일에 대한 요청을 만들거나 포함함
렌더 트리
- 브라우저 엔진은 DOM과 CSSOM을 결합하여 렌더 트리를 생성함
레이아웃
- 페이지의 모든 것에 대한 크기와 위치를 결정
- 일단 레이아웃이 결정되면 화면에 픽셀을 그림
중요 렌더링 경로 최적화
- 첫번째 렌더링의 시간을 개선시킴
- 뛰어난 사용자 상호작용을 보장하며 버벅거림을 피할 수 있도록 함
- 1초당 60 프레임에 리플로우와 리페인트가 발생할 수 있도록 하는 데 중요
CRP 이해하기
웹 성능
- 서버의 요청과 응답, 로딩, 스크립팅, 렌더링, 레이아웃 그리고 화면에 픽셀 그리기를 포함함
웹 페이지 또는 애플리케이션에 대한 요청 순서
- HTML 요청으로 시작됨
- 서버가 응답 헤더 또는 데이터로 HTML을 반환
- 브라우저는 HTML을 분석하고 수신된 바이트들을 DOM 트리로 변환하기 시작
- 브라우저는 스타일시트, 스크립트 또는 포함된 이미지 참조인 외부 자원에 대한 링크를 찾을 때마다 요청을 시작
- 불러온 에셋을 다룰 때까지 나머지 HTML을 분석하는 작업하는 일부 요청은 중단되며 차단됨
- 브라우저는 CSSOM을 구축하는 작업이 끝날 때까지 요청을 만들고 DOM을 생성하는 HTML을 계속해서 분석
- DOM과 CSSOM이 완료되면 브라우저는 렌더 트리를 생성하고 보여지는 컨텐츠를 위해 스타일을 계산
- 렌더 트리가 완료된 후 모든 렌더 트리 요소들에 대한 위치와 크기가 정의된 레이아웃이 만들어짐
- 일단 완료되면 페이지는 렌더링되거나 화면에 그려짐(painted)
DOM (Document Object Model)
DOM
- DOM은 페이지의 모든 컨텐츠를 포함
- DOM 구성은 점진적으로 증가
- HTML 응답 -> 토큰 -> 노드 -> DOM 트리 …로 변환됨
DOM 노드
- 1개의 DOM 노드는 시작태그 토큰으로 시작해서 끝태그 토큰으로 끝남
- 노드들은 HTML 요소에 대한 모두 연관성 있는 정보를 포함하고 있음
- 그 정보는 토큰을 통해 설명됨
- 노드들은 토큰의 위계서열을 기반으로 DOM 트리 안에 연결됨
- 많은 수의 노드는 CRP에서 다음의 이벤트를 더 오래 발생시킬 것임
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Bytes 3C 62 6F 64 79 3E 48 65 6C 6C 6F 2C 20 3C 73 70 61 6E 3E 77 6F 72 6C 64 ...
Characters <htm|><head>...</head><body><p>Hello <span>web performance</span>...
Tokens [StartTag: html] [StartTag: head] [...] [EndTag: head] [StartTag: body] [StartTag: p] [Hello] [...]
{
startTag: 'html',
contents: {
startTag: 'head',
contents: { ... },
...,
},
endTag: 'html'
}
Nodes [html] [head] [meta] [body] [p] [Hello]
DOM
html
head body
meta link p div
Hello span students img
web performance
CSSOM (CSS Object Model)
CSSOM
- CSSOM은 DOM을 스타일링 하기 위한 페이지의 모든 스타일 정보를 포함
- CSSOM은 DOM과 유사하지만 다름
- DOM의 구조는 점진적으로 증가하지만 CSSOM은 아님
CSS는 렌더링을 막음
- 브라우저는 모든 CSS를 처리하고 수신할 때까지 페이지 렌더링을 막음
- CSS는 규칙을 덮어쓸 수 있기 때문에 CSSOM이 완료될 때까지 컨텐츠를 렌더링할 수 없음
- CSS는 렌더링 차단 리소스
CSS는 유효한 토큰들을 인식하기 위해 스스로 규칙 세트를 가짐
- CSS의 C는 Cascade(종속 또는 폭포)
- CSS 규칙은 아래로 종속됨
분석기는 토큰을 노드로 변환할 때, 하위 노드가 스타일을 상속함
- 연속적인 규칙들이 이전의 규칙들에 덮어쓰여질 수 있기 때문에, 증감 처리 기술은 HTML 처럼 CSS에 적용되지는 않음
CSSOM은 CSS를 분석할 때 빌드됨
- 하지만 나중에 분석되어 덮어쓸 스타일들은 화면에 렌더링할 수 없음
- 따라서 완전히 분석될 때까지 렌더 트리를 생성하는데 사용할 수 없음
선택자 성능 측면에서, 덜 구체적인 선택자는 더 구체적인 선택자보다 더 빠름
- 예를 들어 브라우저가
.foo
를 찾을 때,.foo {}
는.bar .foo {}
보다 빠름 - 두 번째 시나리오에서
.foo
가 부모 객체인.bar
를 가지고 있는지 확인하기 위해 DOM을 거슬러 올라가기 때문 - 더 구체적인 태그는 브라우저에게 더 많은 작업을 요구하지만 이러한 패널티는 최적화할 가치가 없음
만약 CSS 분석 시간을 측정한다면, 브라우저들이 정말 빠르다는 것에 놀랄 것임
- 규칙이 구체적일수록 DOM 트리 안에서 더 많은 노드들은 지나야 하기 때문에 더 높은 비용이 듦
- 그러나 추가적인 비용은 일반적으로 최소임
- CSS 측면에서, 선택자 성능 최적화와 개선은 오직 ms밖에 되지 않을 것임
CSS 최적화
- 축소화와 미디어 쿼리를 사용함으로써 지연된 CSS를 논-블로킹 요청으로 분리하는 것과 같은 CSS 최적화를 위한 다른 방법이 있음
1
2
3
4
5
6
<!-- 렌더링 차단 -->
<link href="style.css" rel="stylesheet" />
<!-- 렌더링 차단. all은 기본값 -->
<link href="style.css" rel="stylesheet" media="all" />
<!-- 페이지가 브라우저에서 처음 로드될 때는 렌더링이 차단되지 않음. 페이지가 인쇄될 때만 적용 -->
<link href="print.css" rel="stylesheet" media="print" />
Render Tree
Render Tree
- 렌더 트리는 컨텐츠와 스타일 둘다 캡처함
- DOM과 CSSOM 트리는 렌더 트리에 결합됨
- 렌더 트리를 구성하기 위해 브라우저는 DOM 트리의 root에서 시작해 모든 노드를 확인하면서 어떤 CSS 규칙들을 첨부할 지 결정함
렌더 트리는 오직 보여지는 컨텐츠만 캡처함
- 일반적으로 헤드 섹션은 보여지는 정보를 포함하고 있지 않으므로 렌더트리 안에 포함되지 않음
- 만약 요소에
display: none
이 적용되어 있다면, 해당 요소 또는 하위 요소는 포함되지 않음
Layout
Layout
- 일단 렌더 트리가 생성되고 나면, 레이아웃은 가능해지며 화면의 크기에 의존함
- 레이아웃 단계는 요소들이 페이지에서 배치되는 위치와 방법, 각 요소의 너비와 높이 그리고 서로 관련된 위치를 결정함
- 디바이스가 회전하거나 브라우저의 사이즈가 조정될 때마다 레이아웃 발생
요소의 너비
- 정의에 따르면, 블럭 수준의 요소들은 그 부모 너비의 기본 너비값의 100%
- 50%의 너비를 갖는 요소는 부모 요소의 절반일 것
- 비록 그렇게 정의되어 있지 않더라도,
body
는 뷰포트 너비의 100%를 의미하는 너비 - 디바이스의 너비는 레이아웃에 영향을 미침
- 디바이스 너비는 사용자가 디바이스를 가로(landscape) 또는 세로(portrait) 모드 사이로 돌릴 때마다 바뀜
뷰포트 메타 태그
- 뷰포트 메타 태그는 레이아웃에 영향을 미치는 뷰포트 레이아웃의 너비로 정의함
- 이 태그가 없다면, 브라우저는 뷰포트 기본값을 사용
브라우저의 full screen 기본값은 일반적으로 960px
- 기본적으로 브라우저의 full screen에서, 스마트폰의 브라우저와 같은 너비는
<meta name="Viewport" content="width=device-witdh">
로 세팅함으로써 기본 뷰포트 너비 대신에 디바이스의 너비를 사용
레이아웃 성능
- DOM의 영향을 받음
- 노드의 수가 많을수록 레이아웃은 더 길어짐
- 스크롤링 또는 다른 애니메이션들이 필요하다면 레이아웃에 쟁크(jank)를 일으키는 병목현상이 발생할 수 있음
- 로딩 또는 방향 전환에 20ms 정도 밀릴 수 있지만 애니메이션 또는 스크롤에 쟁크(jank) 유발할 수 있습니다.
- 노드에 박스 모델 업데이트, 컨텐츠 대체 그리고 노드 추가와 같은 수정은 언제든지 렌더 트리를 수정할 수 있으며 레이아웃을 형성함
레이아웃 성능 향상
- 레이아웃 이벤트의 반복과 형성시간을 줄이기 위해서 일괄 업데이트 해야 함
- 박스 모델 속성을 애니메이션화 하지 말아야 함
Paint
Paint
- 마지막 단계는 화면에 픽셀을 그리는 것
- 일단 렌더 트리가 생성되고 레이아웃이 나타나기 시작하면, 화면에 픽셀을 그릴 수 있음
페인트 과정
- 로드 시, 전체 화면을 그림
- 그 후에는 브라우저가 필요한 최소 영역만을 다시 그리도록 최적화되어 있기 때문에 영향을 받는 영역만을 화면에 다시 그림
- 그리는 시간은 렌더 트리에 적용되는 업데이트의 종류가 무엇이냐에 따라 달라짐
페인트 성능
- 페인팅은 매우 빠르게 진행되는 과정
- 때문에 성능 향상에 집중해야 하는 가장 큰 영향있는 부분이 아닐 수 있지만
- 애니메이션 프레임 소요시간을 측정할 때, 레이아웃과 리페인트 시간을 모두 고려하는 것이 중요
- 각 노드에 적용된 스타일은 페인트 시간을 증가시킴
- 하지만 페인트 시간을 0.001ms 증가시키는 스타일을 제거하는 것은 여러분의 최적화 비용이 매우 커지는 것을 막지 못할 수 있음
Optimizing for CRP
자원 로드 순서를 관리하고, 파일 사이즈를 줄이며 어떤 자원을 먼저 로드할지 정함으로써 페이지 로드 속도를 개선해야 함
성능 팁으로는
- 자원 다운로드를 연기함으로써 중요 자원들의 수를 최소화하기
- 각 요청에 대한 파일 사이즈에 따라 필수적인 요청 횟수 최적하하기
- 다운받을 중요 에셋의 우선순위를 정함으로써 중요 자원 불러오는 순서 최적화하고, 중요 경로 길이 최소화하기