JavaScript 생태계 전반에서 최대 콘텐츠 페인트를 개선합니다.
Google은 Aurora 프로젝트의 일환으로 인기 있는 웹 프레임워크와 협력하여 Core Web Vitals에 따라 우수한 성능을 발휘하도록 하고 있습니다. Angular와 Next.js는 이미 글꼴 인라인을 지원하며 이는 이 도움말의 첫 번째 부분에 설명되어 있습니다. 두 번째로 다룰 최적화는 이제 Angular CLI에서 기본적으로 사용 설정되고 Nuxt.js에서 구현 중인 중요한 CSS 인라인 처리입니다.
글꼴 인라인 처리
Aurora팀은 수백 개의 애플리케이션을 분석한 결과, 개발자가 index.html
의 <head>
요소에서 글꼴을 참조하여 애플리케이션에 글꼴을 포함하는 경우가 많다는 사실을 발견했습니다. Material 아이콘을 포함하는 경우의 예는 다음과 같습니다.
<!doctype html>
<html lang="en">
<head>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
...
</html>
이 패턴은 완전히 유효하고 작동하지만 애플리케이션의 렌더링을 차단하고 추가 요청을 도입합니다. 어떤 일이 일어나고 있는지 더 잘 이해하려면 위의 HTML에서 참조된 스타일시트의 소스 코드를 살펴보세요.
/* fallback */
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/font.woff2) format('woff2');
}
.material-icons {
/*...*/
}
font-face
정의가 fonts.gstatic.com
에 호스팅된 외부 파일을 참조하는 방식에 주목하세요.
애플리케이션을 로드할 때 브라우저는 먼저 헤드에서 참조된 원래 스타일시트를 다운로드해야 합니다.

그런 다음 브라우저가 woff2
파일을 다운로드하고, 마지막으로 애플리케이션 렌더링을 진행할 수 있습니다.

최적화의 기회는 빌드 시 초기 스타일시트를 다운로드하여 index.html
에 인라인으로 삽입하는 것입니다. 이렇게 하면 런타임 시 CDN으로의 전체 왕복이 건너뛰어 차단 시간이 줄어듭니다.
애플리케이션을 빌드할 때 CDN에 요청이 전송되면 CDN에서 스타일시트를 가져와 HTML 파일에 인라인 처리하여 도메인에 <link rel=preconnect>
를 추가합니다. 이 기법을 적용하면 다음과 같은 결과가 나옵니다.
<!doctype html>
<html lang="en">
<head>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin >
<style type="text/css">
@font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/font.woff2) format('woff2');}.material-icons{/*...*/}</style>
...
</html>
이제 Next.js 및 Angular에서 글꼴 인라인을 사용할 수 있습니다.
프레임워크 개발자가 기본 도구에서 최적화를 구현하면 기존 애플리케이션과 새 애플리케이션에서 더 쉽게 최적화를 사용 설정할 수 있어 전체 생태계가 개선됩니다.
이 개선사항은 Next.js v10.2 및 Angular v11부터 기본적으로 사용 설정됩니다. 둘 다 Google 및 Adobe 글꼴의 인라인화를 지원합니다. Angular는 v12.2에서 후자를 도입할 예정입니다.
GitHub의 Next.js에서 글꼴 인라인 처리 구현을 확인하고 Angular 컨텍스트에서 이 최적화를 설명하는 동영상을 확인하세요.
중요한 CSS 인라인 처리
또 다른 개선사항은 중요한 CSS를 인라인 처리하여 콘텐츠가 포함된 첫 페인트 (FCP) 및 콘텐츠가 포함된 최대 페인트 (LCP) 측정항목을 개선하는 것입니다. 페이지의 중요 CSS에는 초기 렌더링에 사용된 모든 스타일이 포함됩니다. 이 주제에 관해 자세히 알아보려면 비중 낮은 CSS 지연을 참고하세요.
많은 애플리케이션이 스타일을 동기식으로 로드하여 애플리케이션 렌더링을 차단하는 것으로 확인되었습니다. 스타일을 비동기식으로 로드하면 이 문제를 빠르게 해결할 수 있습니다. media="all"
로 스크립트를 로드하는 대신 media
속성 값을 print
로 설정하고 로드가 완료되면 속성 값을 all
로 바꿉니다.
<link rel="stylesheet" href="..." media="print" onload="this.media='all'">
하지만 이 방법을 사용하면 스타일이 지정되지 않은 콘텐츠가 깜박일 수 있습니다.
위의 동영상은 스타일을 비동기식으로 로드하는 페이지 렌더링을 보여줍니다. 브라우저가 먼저 스타일 다운로드를 시작한 다음 HTML을 렌더링하기 때문에 플리커링이 발생합니다. 브라우저가 스타일을 다운로드하면 링크 요소의 onload
이벤트를 트리거하여 media
속성을 all
로 업데이트하고 DOM에 스타일을 적용합니다.
HTML을 렌더링하고 스타일을 적용하는 사이의 시간 동안 페이지의 일부는 스타일이 적용되지 않습니다. 브라우저에서 이 스타일을 사용하면 깜박임이 발생하여 사용자 환경이 저하되고 누적 레이아웃 전환 (CLS)이 회귀합니다.
비동기 스타일 로드와 함께 중요한 CSS 인라인 처리를 사용하면 로드 동작을 개선할 수 있습니다. critters 도구는 스타일시트의 선택자를 보고 HTML과 일치시켜 페이지에서 사용되는 스타일을 찾습니다. 일치하는 항목을 찾으면 해당 스타일을 중요한 CSS의 일부로 간주하고 인라인 처리합니다.
예를 살펴보겠습니다.
<head> <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'"> </head> <body> <section> <button class="primary"></button> </section> </body>
/* styles.css */ section button.primary { /* ... */ } .list { /* ... */ }
인라인 처리 전의 예시
위 예시에서 크리터는 styles.css
의 콘텐츠를 읽고 파싱한 후 두 선택기를 HTML과 일치시켜 section button.primary
를 사용한다는 것을 발견합니다.
마지막으로 크리터는 페이지의 <head>
에 해당하는 스타일을 인라인으로 추가하여 다음과 같이 표시합니다.
<head> <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'"> <style> section button.primary { /* ... */ } </style> </head> <body> <section> <button class="primary"></button> </section> </body>
인라인 처리 후 예시
HTML에 중요한 CSS를 인라인 처리하면 페이지의 깜박임이 사라집니다.
이제 Angular에서 Critical CSS 인라인을 사용할 수 있으며 v12에서는 기본적으로 사용 설정됩니다. v11을 사용하는 경우 angular.json
에서 inlineCritical
속성을 true
로 설정하여 사용 설정합니다. Next.js에서 이 기능을 사용하려면 next.config.js
에 experimental: { optimizeCss: true }
를 추가합니다.
결론
이 게시물에서는 Chrome과 웹 프레임워크 간의 공동작업에 대해 살펴봤습니다. 프레임워크 작성자이고 Google에서 기술에서 해결한 문제 중 일부를 알고 있다면 Google의 발견사항을 바탕으로 유사한 성능 최적화를 적용해 보시기 바랍니다.
개선사항에 대해 자세히 알아보기 Aurora 소개 게시물에서 Core Web Vitals를 위해 진행한 최적화 작업의 포괄적인 목록을 확인할 수 있습니다.