CRP 최적화란 HTML, CSS 및 JS 간 종속성을 이해하고 최적화 하는것이다.
Critical Rendering Path란?
브라우저가 페이지의 초기 출력을 위해 실행해야 하는 순서
- DOM 트리 구축
- CSSOM 트리 구축
- JS 실행
- 렌더트리 구축
- 레이아웃 생성
- 페인팅
CSS
CSS는 렌더링 차단 리소스이므로 최초 렌더링에 걸리는 시간을 최적화하려면 클라이언트에 최대한 빠르게 다운로드되어야 한다.
- 렌더 트리를 만들 때 사용되는 HTML, CSS 모두 렌더링 차단 리소스
CSS가 없는 페이지는 상대적으로 사용성이 떨어지기 때문에 브라우저는 DOM과 CSSOM을 모두 사용할 수 있게 될 때까지 렌더링을 차단한다.
CSS를 간단하게 유지하고 가능한 빨리 제공하고 최대한 빨리 렌더링의 차단을 해제해야 한다.
미디어 쿼리, 미디어 유형
미디어 쿼리를 사용하면 특정한 사용 사례와 동적인 조건에 맞게 렌더링이 차단되므로 효율을 높힐 수 있다.
- 미디어 유형과 미디어 쿼리를 통해 일부 CSS 리소스를 렌더링 비차단 리소스로 표시할 수 있음
- 브라우저는 차단 동작이든 비차단 동작이든 관계없이 모든 CSS 리소스를 다운로드함
미디어 쿼리는 하나의 미디어 유형과 특정 미디어 기능의 조건을 확인하는 0개 이상의 식으로 구성된다.
|
|
- 조건이 없는 경우
미디어 유형이나 미디어 쿼리를 제공하지 않아서 모든 경우에 적용됨- 즉 항상 렌더링을 차단함
- 미디어 유형을 적용
콘텐츠가 인쇄될 때만 적용- 처음에 로드될 때 페이지 렌더링을 차단할 필요가 없음
- 미디어 쿼리 적용
조건이 일치하면 스타일시트가 다운로드되고 처리될 때까지 브라우저가 렌더링을 차단.
JS
자바스크립트는 파서 차단 리소스(parser blocking resource)이며, JS를 사용하면 콘텐츠, 스타일, 사용자와의 상호작용등 거의 모든것을 수정할 수 있다.
JS실행은 DOM 생성을 차단하고 페이지 렌더링을 지연하게 된다.
- 자바스크립트를 비동기로 설정하고, CRP에서 불필요한 JS를 제거해야 한다.
JS와 HTML의 종속성
HTML 파서는 script
태그를 만나면 DOM 생성 프로세스를 중지하고 자바스크립트 엔진에 권한을 넘긴다. 자바스크립트 엔진의 실행이 완료된 후 브라우저가 중지했던 시점부터 DOM 생성을 다시 시작하게 된다.
script
태그의 뒷부분에서 정의된 어떠한 태그들도 아직 생성되지 않았기 때문에 노드를 찾을 수 없다. 또한, 인라인 스크립트를 실행하면 DOM 생성이 차단되고, 이로 인해 초기 렌더링도 지연된다.
이러한 이유로 인하여 자바스크립트는 화면에 그려지는 태그들이 모두 파싱 된 후인, <body>
태그를 닫기 직전에 <script>
태그를 선언하는 것이 좋다.
JS와 CSS의 종속성
CSS를 파싱 하는 동안 자바스크립트에서 스타일 정보를 요청하는 경우, CSS가 파싱이 끝나지 않은 상태라면 자바스크립트 오류가 발생할 수 있다. CSS 파싱으로 생성되는 CSSOM과 JavaScript에서 스타일 수정 시 발생하는 CSSOM 수정 사이에 경쟁 조건(race condition)이 발생할 수 있다.
브라우저는 이 문제를 해결하기 위해 CSSOM을 생성하는 작업이 완료할 때까지 자바스크립트 실행 및 DOM 생성을 지연시킨다. DOM, CSSOM, 자바스크립트 실행 간에 종속성 때문에 브라우저가 화면에 페이지를 처리하고 렌더링 할 때 상당한 지연이 발생할 수 있습니다.
비동기 JS
HTML을 파싱 하면서 script 태그를 만나면 DOM 생성을 중지시키고 자바스크립트 엔진에게 제어 권한을 넘겨 자바스크립트를 실행한 후, DOM 생성을 진행한다.
|
|
|
|
위에서 살펴본 인라인 스크립트뿐만 아니라 위의 코드와 같이 script
태그를 통해 포함된 자바스크립트 역시 파싱을 중지시킨다.
script
태그를 사용하여 자바스크립트를 실행할 경우, 서버에서 자바스크립트를 가져올 때까지 기다려야하며 이로 인해 수십~수천 밀리초의 지연이 추가로 발생할 수 있다.
기본적으로 자바스크립트가 실행될 때, 스크립트가 페이지에서 무엇을 수행할지 모르기 때문에 브라우저는 최악의 대비하여 파서를 차단한다.
브라우저에 자바스크립트를 바로 실행할 필요가 없음을 알려준다면, 브라우저는 계속해서 DOM을 생성할 수 있고 DOM 생성이 끝난 후에 자바스크립트를 실행할 수 있게 된다.
이때 사용할 수 있는 것이 비동기 자바스크립트이다.
|
|
위의 코드와 같이 단순히 script
태그에 async
속성을 추가해 주면 됩니다. async
속성을 script
태그에 추가하여 자바스크립트가 사용 가능해질 때까지 브라우저에게 DOM 생성을 중지하지 않아도 괜찮다는 것을 알릴 수 있다.
리소스 우선순위 지정
브라우저는 가장 중요한 리소스(스크립트나 이미지보다 CSS 우선)를 우선 로드하기 위해 가장 중요하다 생각되는 리소스를 추측하여 먼저 로드한다. 하지만 브라우저에게 리소스의 우선순위를 전달하여 중요한 리소스를 먼저 처리하게 할 수 있다.
preload 속성
현재 페이지에서 빠르게 가져와야 하는 리소스에 사용되는 속성이다.
<link rel="preload" as="...">
는 브라우저에게 현재 리소스가 필요하며, 가능한 한 빨리 가져오기를 시도해야 한다고 알리는 역할을 한다.
|
|
as
속성을 사용하여 리소스의 유형을 알려줘야 한다.- 브라우저는 올바른 유형이 설정되어 있지 않으면 미리 가져온 리소스를 사용하지 않는다.
preload
는 브라우저가 반드시 리소스를 가져오게 만들며, 리소스를 두 번 가져오게 하거나, 필요하지 않은 것을 가져오지 않도록 주의해야한다.
preload
를 이용하여 리소스를 가져왔지만 현재 페이지에서 즉시 사용되지 않는 리소스는 위의 그림과 같이 워닝 로그가 노출된다.
prefetch 속성
미래에 필요할 수 있는 리소스를 가져와야 할 때 사용되는 속성이다.
<link rel="prefetch">
는 현재 페이지 로딩이 마치고 다운로드할 여유가 생겼을 때 가장 낮은 우선순위로 리소스를 가져온다.
prefetch
는 사용자가 다음에 할 행동을 미리 준비하는 역할을 한다. 예를 들어, 현재 페이지가 1페이지 라면,
|
|
위의 코드와 같이 사용하여 2페이지를 먼저 가져와 준비하게 된다.
page-2.html
의 HTML만 가져오고page-2.html
에서 사용되는 리소스는 가져오지 않는다.
요약
CSS 최적화 방법
- 미디어 유형, 미디어 쿼리를 사용
JavaScript 최적화 방법
body
태그 닫기 직전<script>
태그를 선언<script ... async>
와 같이async
속성을 사용
리소스 우선순위 지정
- 현재 페이지에서 빠르게 가져와야 하는 리소스에
<link rel="preload" as="...">
와 같이preload
속성을 사용 - 미래에 사용할 수 있는 리소스는
<link rel="prefetch">
와 같이prefetch
속성을 사용
- 현재 페이지에서 빠르게 가져와야 하는 리소스에