Critical Rendering Path
Critical Rendering Path
- 브라우저에서 웹 페이지를 렌더링하기 위해 필요한 자원들을 로드한 이후부터 렌더링이 완료되어 사용자 화면에 나타날 때까지의 단계를 말한다.
- 웹은 기본적으로 분산되어 있다. 설치하여 사용하는 네이티브 앱과 달리 브라우저는 페이지를 렌더링하기 위해 필요한 모든 자원을 가진 웹 사이트에 직접 의존할 수 없다.
- 그렇기 때문에 브라우저는 페이지를 점진적으로(progressively) 렌더링하는 데에 매우 능숙하다.
- 네이티브 앱은 일반적으로 설치 단계과 실행 단계가 명확히 구분되는 반면, 웹 페이지 혹은 웹 앱의 경우 그 경계는 덜 분명하다. 그리고 브라우저는 이 점을 염두에 두고 특별하게 설계되었다.
- 브라우저는 페이지를 렌더링할 자원을 가지고 있으면 렌더링을 시작한다. 중요한 점은 언제 렌더링을 시작할지 결정하는 것이다.
- 만약 브라우저에게 html 문서만 가지고 가능한 빨리 렌더링을 시작하도록 한다면 페이지는 최종 렌더링까지 잠시 동안 깨져보이고, 계속 변경될 것이다.
- 이는 브라우저가 초기 렌더링에 필요한 리소스를 더 많이 확보할 때까지 처음에 빈 화면을 보여주는 것보다 더 나쁜 사용자 경험을 제공한다.
- 하지만 브라우저가 순차적으로 렌더링을 하는 대신 모든 리소스를 사용할 수 있을 때까지 기다린다면 사용자는 훨씬 이른 시점에서 페이지를 이용 할 수 있었음에도 불구하고 불필요하게 오랫 동안 멈춰 있어야 한다.
- 브라우저는 손상된 경험을 제공하지 않기 위해 기다려야 할 최소한의 리소스 수를 알아야 한다.
- 동시에 사용자가 필요 이상으로 오래 기다리도록 하지 않아야 한다.
- 이와 같은 내용을 고려하여 브라우저가 초기 렌더링을 수행하기 전에 거치는 일련의 단계를 'Critical Rendering Path'라고 부른다.
- Critical Rendering Path를 이해하는 것은 초기 페이지 렌더링을 필요 이상으로 지연시키지 않으면서 동시에 필수 리소스를 제외시켜 렌더링이 너무 일찍 일어나도록 하지 않도록 하여 웹 성능을 개선하는데에 도움이 된다.
Rendering Path Steps
- HTML을 바탕으로 DOM 구성하기
- CSS을 바탕으로 CSSOM 구성하기
- DOM과 CSSOM에 JS 적용하기
- DOM과 CSSOM을 바탕으로 Render Tree 구성하기
- 스타일과 레이아웃 작업을 수행하여 어떤 요소가 어디에 적합한 지 확인하기
- 메모리 내에서 요소 픽셀 그리기
- 요소들이 겹치면 픽셀 합치기
- 화면에 픽셀 그리기
- 이러한 렌더링 과정은 여러번 발생한다.
- 기본적으로 초기 렌더링 과정에서 이 프로세스가 진행되지만, 페이지 렌더링에 영향을 미치는 추가 자원이 사용 가능해짐에 따라 브라우저는 이 프로세스 전체 혹은 일부를 다시 실행하여 사용자가 보는 것을 업데이트 한다.
- Critical rendering path는 초기 렌더링 프로세스에 초점을 맞추며 필수 리소스들에 의존한다.
- 브라우저가 초기 렌더링을 완료하기 위해 다운로드해야 하는 필수 리소스는 다음과 같다.
- HTML 일부
- <head> 내의 Render-blocking CSS
- <head> 내의 Render-blocking javascript
- 꼭 알아둬야 할 부분은, 브라우저는 HTML을 스트리밍 방식으로 처리한다는 것이다.
- 브라우저는 페이지의 어떤 HTML 일부라도 받는 즉시 그것을 처리하기 시작한다.
- 그리고 나머지 HTML을 받기 전에 렌더링을 시작할 수 있다.
- 브라우저가 초기 렌더링을 시작하기 전에 꼭 기다리지 않는 리소스는 다음과 같다.
- HTML 전체
- Fonts
- Images
- <head> 외부의 Non-render-blocking js
- <head> 외부의 Non-render-blocking CSS (현재 뷰포트에 적용되지 않는 media 속성값 같은)
- 폰트와 이미지는 후속 페이지를 리렌더링하는 동안 채우는 컨텐츠로 간주되므로 초기 렌더링에 포함시킬 필요가 없다.
- 그러나 초기 렌더링에서 폰트와 이미지가 차지하는 자리에 공백 영역이 생기기 때문에 해당 컨텐츠들이 로드 될 때 페이지 레이아웃이 변경되어 나쁜 사용자 경험을 제공할 수 있다. (이는 CLS 지표로 측정된다.)
- <head>는 Critical rendering path 처리에 핵심이 되는 요소이다.
- 이 태그를 최적화하는 것이 웹 성능의 핵심이다
- <head>에는 페이지와 리소스에 대한 메타데이터를 포함하지만, 사용자가 실제로 보는 컨텐츠는 포함되지 않는다.
- 메타데이터에는 브라우저가 <body>에 존재하는 컨텐츠를 렌더링하기 전에 렌더링할 컨텐츠와 렌더링하는 방법에 대한 정보가 담겨있다.
- <head>에 참조된 모든 리소스가 초기 페이지 렌더링에 필수적인 것은 아니기 때문에 브라우저는 꼭 필요한 리소스 로드만 기다린다.
- Critical rendering path의 리소스를 식별하기 위해서는 render-blocking, parser-blocking CSS & JS를 이해해야 한다.
Render-blocking Resources
- 브라우저가 페이지 렌더링을 일시 정지 할 정도로 중요하게 여기는 몇몇 리소스가 존재한다.
- CSS는 그 중 하나다.
- 브라우저는 <style> 요소 같은 inline CSS든, <link res=stylesheet href=''> 같은 외부 참조 CSS든 CSS를 발견하기만 하면 그 즉시 컨텐츠 렌더링을 멈추고 CSS를 완전히 로드하고 처리할 때까지 기다린다.
- *<link res=stylesheet href='' media=print>처럼 미디어 속성으로 조건부로 스타일을 적용하는 경우에는 렌더링을 차단하지 않는다.
- 하지만 브라우저의 작동이 멈추는 것은 아니다. 렌더링 작업이 중단되었을 뿐이지 리소스를 로드하고 처리하는 동안 나머지 HTML을 파싱하거나 다른 작업을 계속해서 찾는다.
- 최근 크롬 버전(chrome 105)에서는 <link>, <script>, <style> 등의 요소에 blocking=render 속성을 마킹하여 render-blocking을 명시할 수 있다.
Parser-blocking resources
- 브라우저가 HTML을 파싱하느라 다른 작업을 찾지 못하도록 한다.
- JS(async or defer가 아닌 동기적으로 실행될 때만)는 실행시 DOM이나 CSSOM을 변경할 수 있기 때문에 대표적인 parser-blocking 리소스이다.
- 자바스크립트가 HTML에 미치는 영향을 알기 전까지 브라우저는 다른 자원을 처리할 수 없다.
- parser-blocking 리소스는 곧 render-blocking 리소스이기도 하다. 파서가 이전 작업을 처리하기 전까지 다음의 컨텐츠에 접근하지 못하므로 렌더링도 불가능하다.
- 브라우저는 preload scanner라 부르는 HTML 보조 파서를 사용하여 주요 파서가 차단된 동안 리소스를 계속 다운로드한다.
Blocking resources 식별하기
- WebPageTest 같은 성능 검사 도구로 render&parser blocking resources를 찾아낼 수 있다.
- 아래 그림에서 왼쪽에 오렌지색 원으로 표시된 리소스가 블로킹 리소스이다.
- 블로킹 리소스는 브라우저가 렌더링을 시작할 수 있게 되기 전에 모두 다운로드 되고 처리를 마쳐야 한다.
- Lighthouse도 이 블로킹 자원을 강조하지만 자원이 실제로 페이지 렌더링을 지연시킬 경우에만 표시한다.
- 아래 그림에서는 위와 같은 페이지 url에 대해 실제로 렌더링을 차단하는 스타일시트만 식별한다.
Critical rendering path 최적화하기
- HTML을 로드하는 시간을 줄인다. (Time to First Byte (TTFB) metric)
- 우선 순위를 정해 리소스를 다운로드하는 순서를 최적화한다.
- 지연 로딩을 통해 주요 리소스의 수를 최소화한다.
- 렌더링 및 파서 블로킹 자원들의 영향을 줄인다.
Critical contentful rendering path
- 과거에는 critical rendering path(CRP)는 초기 렌더링에 초점을 맞췄지만, 최근 웹 성능을 위한 사용자 중심의 지표에서는 FCP 혹은 LCP과 더 연관이 깊다.
- 이에 따라 전형적으로 CRP를 블로킹하는 리소스가 아님에도 contentful paints를 렌더링하기 위해 포함될 수 있다.
- 용어와 관계 없이 초기 렌더링과 주요 컨텐츠를 지연시키는 것이 무엇인지를 파악하는 것이 가장 중요하다.
Contentful rendering path 식별하기
- 여러 도구로 LCP 요소와 이 요소가 렌더링되는 시점을 식별할 수 있다.
- Lighthouse에서는 LCP 요소, LCP 단계와 각 단계에서 소요된 시간을 측정하여 어떤 부분을 집중적으로 최적화해야 하는지 알려준다.
출처: https://web.dev/learn/performance/understanding-the-critical-path
계속해서 읽어보기: https://web.dev/learn/performance/optimize-resource-loading