카테고리 없음

Critical Rendering Path

Withlaw 2024. 3. 18. 17:21

Critical Rendering Path

- 브라우저에서 웹 페이지를 렌더링하기 위해 필요한 자원들을 로드한 이후부터 렌더링이 완료되어 사용자 화면에 나타날 때까지의 단계를 말한다.

- 웹은 기본적으로 분산되어 있다. 설치하여 사용하는 네이티브 앱과 달리 브라우저는 페이지를 렌더링하기 위해 필요한 모든 자원을 가진 웹 사이트에 직접 의존할 수 없다.

- 그렇기 때문에 브라우저는 페이지를 점진적으로(progressively) 렌더링하는 데에 매우 능숙하다.

- 네이티브 앱은 일반적으로 설치 단계과 실행 단계가 명확히 구분되는 반면, 웹 페이지 혹은 웹 앱의 경우 그 경계는 덜 분명하다. 그리고 브라우저는 이 점을 염두에 두고 특별하게 설계되었다.

 

- 브라우저는 페이지를 렌더링할 자원을 가지고 있으면 렌더링을 시작한다. 중요한 점은 언제 렌더링을 시작할지 결정하는 것이다.

- 만약 브라우저에게 html 문서만 가지고 가능한 빨리 렌더링을 시작하도록 한다면 페이지는 최종 렌더링까지 잠시 동안 깨져보이고, 계속 변경될 것이다.

- 이는 브라우저가 초기 렌더링에 필요한 리소스를 더 많이 확보할 때까지 처음에 빈 화면을 보여주는 것보다 더 나쁜 사용자 경험을 제공한다.

- 하지만 브라우저가 순차적으로 렌더링을 하는 대신 모든 리소스를 사용할 수 있을 때까지 기다린다면 사용자는 훨씬 이른 시점에서 페이지를 이용 할 수 있었음에도 불구하고 불필요하게 오랫 동안 멈춰 있어야 한다.

 

- 브라우저는 손상된 경험을 제공하지 않기 위해 기다려야 할 최소한의 리소스 수를 알아야 한다.

- 동시에 사용자가 필요 이상으로 오래 기다리도록 하지 않아야 한다.

- 이와 같은 내용을 고려하여 브라우저가 초기 렌더링을 수행하기 전에 거치는 일련의 단계를 'Critical Rendering Path'라고 부른다.

- Critical Rendering Path를 이해하는 것은 초기 페이지 렌더링을 필요 이상으로 지연시키지 않으면서 동시에 필수 리소스를 제외시켜 렌더링이 너무 일찍 일어나도록 하지 않도록 하여 웹 성능을 개선하는데에 도움이 된다.

 

 

Rendering Path Steps

  1. HTML을 바탕으로 DOM 구성하기
  2. CSS을 바탕으로 CSSOM 구성하기
  3. DOM과 CSSOM에 JS 적용하기
  4. DOM과 CSSOM을 바탕으로 Render Tree 구성하기
  5. 스타일과 레이아웃 작업을 수행하여 어떤 요소가 어디에 적합한 지 확인하기
  6. 메모리 내에서 요소 픽셀 그리기
  7. 요소들이 겹치면 픽셀 합치기
  8. 화면에 픽셀 그리기

 

 

 

 

 

 

- 이러한 렌더링 과정은 여러번 발생한다.

- 기본적으로 초기 렌더링 과정에서 이 프로세스가 진행되지만, 페이지 렌더링에 영향을 미치는 추가 자원이 사용 가능해짐에 따라 브라우저는 이 프로세스 전체 혹은 일부를 다시 실행하여 사용자가 보는 것을 업데이트 한다.

- 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