웹 성능 최적화를 하고 싶다면 CRP를 꼭 알아두는 것이 좋다. 만약 사이트의 속도를 높이기 위해 프로젝트를 진행하고 있다면 CRP의 단계를 반복적으로 읊고 있을 것이다. 나는 그랬다^_^

CRP(Critical Rendering Path)는 브라우저가 서버로부터 HTML을 받아 화면에 무언가 그릴 때까지 거치는 단계를 뜻한다.


DOM 트리 생성

<html>
 <head>
   <title>웰컴 투 Joyfuljoeunlee.dev</title>
   <link rel="stylesheet" href="style.css">
 </head>
 <body>
   <header>
       <h1>기술 블로그</h1>
   </header>
   <main>
       <h2>크리티컬 렌더링 패스란</h2>
   </main>
 </body>
 </html>

DOM(Document Object Model) 트리는 완전히 파싱된 HTML 객체를 의미한다. 최상단의 요소부터 시작하여 페이지의 요소마다 노드가 생성된다.

HTML은 부분적으로 실행될 수 있는데, 이 말인즉슨 페이지에 어떤 내용이 보이기 시작할 때 전체 DOM이 완전히 로드될 필요는 없다는 것이다. 하지만 CSS와 JavaScript가 페이지의 렌더를 막을 수는 있다.

CSSOM 트리 생성

header {color: yellow;}
h1 {font-size: 32px;}

main {font-size: 24px;}
h2 {display: none;}

CSSOM(CSS Object Model)은 DOM과 관련된 스타일 객체를 의미한다. DOM과 비슷한 방식으로 표현되는데, 각 노드에 명시적으로 선언된 스타일 혹은 암시적으로 상속된 스타일을 모두 포함한다.

<link href="style.css" rel="stylesheet">
<link href="print.css" rel="stylesheet" media="print">
<link href="landscape.css" rel="stylesheet" media="orientation:landscape">
<link href="minWidth.css" rel="stylesheet" media="min-width:100rem">

CSS는 렌더링 차단 리소스(Render Blocking Resource)이다. CSSOM이 만들어지기 전까지 브라우저는 렌더 트리를 생성하지 않는다.

렌더링 차단을 막기 위해 미디어 유형과 미디어 쿼리를 사용할 수 있는데 조건이 일치하는 경우에만 렌더링을 차단한다. 위의 예를 보면 style.css는 미디어 유형이나 미디어 속성이 없기 때문에 항상 렌더링을 차단한다. print.css는 프린트 될 때, landscape.css는 기기가 가로 모드일 때, minWidth.css는 기기의 최소 너비가 100rem일 때만 렌더링을 차단하게 된다.

CSS는 스크립트 차단 리소스(Script Blocking Resource)이기도 하다. 자바스크립트는 CSSOM이 만들어지기까지 브라우저에 의해서 실행이 지연되기 때문이다.

JavaScript 실행

<script async src="script.js">

자바스크립트는 파서 차단 리소스(Parser Blocking Resource)이다. HTML은 자바스크립트를 만나면 파싱을 중단하고 자바스크립트를 실행한다.

이런 이유로 자바스크립트 파일이 있을 경우에 HTML의 가장 끝에 파일을 위치시키는 것이 좋다.

파서 차단을 막기 위해 async 속성을 이용하면 자바스크립트 파일을 비동기적으로 로드할 수 있다.

Render 트리 생성

렌더 트리는 DOM과 CSSOM을 합친 결과로서 최종적으로 페이지에 렌더되는 것이다. 예를 들어 display: none을 사용하여 보이지 않는 요소는 렌더 트리에 포함되지 않는다.

Layout 그리기

<meta name="viewport" content="width=device-width,initial-scale=1">

레이아웃은 뷰포트 크기가 얼마일지 결정하는 것이다.  뷰포트 크기는 head 부분에 위치한 메타 뷰포트 값에 의해 결정된다. 만약 이 값이 없으면 뷰포트의 기본 설정 값은 980px이 된다.

위의 예시는 가장 흔히 사용하는 모바일 최적화 뷰포트 메타 값이다. 이 코드가 쓰이면 뷰포트 사이즈가 기기 너비로 맞춰진다.

이 태그에 사용되는 프로퍼티를 살펴보자. width는 뷰포트  너비를 컨트롤한다. width=600과 같이 픽셀 단위로 표현할 수도 있고 width=device-width와 같이 특별한 값을 주어 기기 너비로 할 수 있다. 이와 비슷하게 height는 뷰포트 높이를 컨트롤한다. initial-scale은 페이지를 처음 로드할 때 초기 확대/축소 값을 설정한다. mimimum-scale은 허용되는 최소 확대/축소 값이며 기본 값은 0.25이다. maximum-scale은 허용되는 최대 확대/축소 값이며 기본 값은 5.0이다. user-scalable은 줌 여부를 결정한다.

Painting

페이지에 렌더되는  내용은 픽셀로 변환된다. 이 페인트 단계가 얼마나 오래 진행되느냐는 DOM의 사이즈나 적용된 스타일에 의해 결정된다. 예를 들어, 복잡한 배경 이미지는 단순한 배경보다 더 많은 시간이 소요된다.


도움이 된 자료

Understanding the Critical Rendering Path, (2021.12.12), https://bitsofco.de/understanding-the-critical-rendering-path/

Using the viewport meta tag to control layout on mobile browsers, (2021.12.12), https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag