Codelab: 중요한 애셋을 미리 로드하여 로드 속도 개선

이 Codelab에서는 몇 가지 리소스를 미리 로드하고 미리 가져와 다음 웹페이지의 성능을 개선합니다.

앱 스크린샷

측정

최적화를 추가하기 전에 먼저 웹사이트 실적을 측정하세요.

  • 사이트를 미리 보려면 View App을 누른 다음 Fullscreen 전체 화면을 누릅니다.

Glitch의 실시간 버전에서 Lighthouse 성능 감사 (Lighthouse > 옵션 > 성능)를 실행합니다 (Lighthouse로 성능 기회 탐색 참고).

Lighthouse는 늦게 가져온 리소스에 대한 다음과 같은 실패한 감사를 보여줍니다.

Lighthouse: 키 요청 미리 로드 감사
  • `Control+Shift+J` (Mac의 경우 `Command+Option+J`)를 눌러 DevTools를 엽니다.
  • 네트워크 탭을 클릭합니다.
늦게 발견된 리소스가 포함된 네트워크 패널

main.css 파일은 HTML 문서에 있는 링크 요소 (<link>)가 가져오지 않지만 별도의 JavaScript 파일인 fetch-css.jswindow.onLoad 이벤트 뒤에 링크 요소를 DOM에 연결합니다. 즉, 브라우저가 JS 파일의 파싱과 실행을 완료한 에만 파일을 가져옵니다. 마찬가지로 main.css 내에 지정된 웹 글꼴 (K2D.woff2)은 CSS 파일 다운로드가 완료된 후에만 가져옵니다.

중요한 요청 체인은 우선순위가 지정되고 브라우저에서 가져오는 리소스의 순서를 나타냅니다. 이 웹페이지의 경우 현재 다음과 같이 표시됩니다.

├─┬ / (initial HTML file)
  └── fetch-css.js
    └── main.css
      └── K2D.woff2

CSS 파일은 요청 체인의 세 번째 수준에 있으므로 Lighthouse는 이 파일을 늦게 발견된 리소스로 식별했습니다.

중요 리소스 미리 로드

main.css 파일은 페이지가 로드되는 즉시 필요한 중요한 애셋입니다. 애플리케이션에서 늦게 가져오는 이 리소스와 같은 중요한 파일의 경우 링크 미리 로드 태그를 사용하여 문서의 헤드에 링크 요소를 추가하여 브라우저가 더 빨리 다운로드하도록 알립니다.

이 애플리케이션에 미리 로드 태그를 추가합니다.

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
</head>

as 속성은 가져올 리소스 유형을 식별하는 데 사용되고 as="style"는 스타일시트 파일을 미리 로드하는 데 사용됩니다.

애플리케이션을 새로고침하고 DevTools에서 네트워크 패널을 살펴봅니다.

리소스가 미리 로드된 네트워크 패널

가져오기를 담당하는 JavaScript가 파싱을 완료하기 전에 브라우저가 CSS 파일을 어떻게 가져오는지 확인하세요. 미리 로드를 사용하면 브라우저는 웹페이지에 중요하다는 가정하에 리소스에 대한 선제적 가져오기를 실행할 수 있습니다.

올바르게 사용하지 않을 경우 미리 로드는 사용되지 않는 리소스를 불필요하게 요청하여 성능을 저하시킬 수 있습니다. 이 애플리케이션에서 details.css는 프로젝트의 루트에 있는 또 다른 CSS 파일이지만 별도의 /details route에 사용됩니다. 미리 로드를 잘못 사용하는 방법의 예를 보여주기 위해 이 리소스에도 미리 로드 힌트를 추가합니다.

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

애플리케이션을 새로고침하고 네트워크 패널을 확인합니다. 웹페이지에서 사용되지 않는 details.css를 검색하도록 요청합니다.

불필요한 미리 로드가 있는 네트워크 패널

미리 로드된 리소스가 로드된 후 몇 초 이내에 페이지에서 사용되지 않으면 Chrome에서 콘솔 패널에 경고를 표시합니다.

콘솔의 미리 로드 경고

이 경고를 표시기로 사용하여 웹페이지에서 즉시 사용되지 않는 미리 로드된 리소스가 있는지 확인하세요. 이제 이 페이지의 불필요한 미리 로드 링크를 삭제할 수 있습니다.

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

가져올 수 있는 모든 유형의 리소스 목록과 as 속성에 사용해야 하는 올바른 값은 미리 로드에 대한 MDN 문서를 참조하세요.

향후 리소스 미리 가져오기

미리 가져오기는 다른 탐색 경로에 사용되는 애셋 요청에 사용할 수 있지만 현재 페이지에 필요한 다른 중요 애셋보다 우선순위가 낮은 경우 사용할 수 있는 또 다른 브라우저 힌트입니다.

이 웹사이트에서 이미지를 클릭하면 별도의 details/ 경로로 이동합니다.

경로 세부정보

별도의 CSS 파일 details.css에는 이 간단한 페이지에 필요한 모든 스타일이 포함되어 있습니다. 이 리소스를 미리 가져오려면 index.html에 링크 요소를 추가합니다.

<head>
  <!-- ... -->
  <link rel="prefetch" href="details.css">
</head>

이로 인해 파일 요청이 트리거되는 방식을 이해하려면 DevTools에서 네트워크 패널을 열고 캐시 사용 중지 옵션을 선택 해제하세요.

Chrome DevTools에서 캐시 사용 중지

애플리케이션을 새로고침하면 다른 모든 파일을 가져온 후 details.css에 대해 우선순위가 매우 낮은 요청이 어떻게 생성되는지 확인합니다.

미리 가져온 리소스가 포함된 네트워크 패널

DevTools를 연 상태에서 웹사이트의 이미지를 클릭하여 details 페이지로 이동합니다. 링크 요소는 details.html에서 details.css를 가져오는 데 사용되므로 예상대로 리소스에 대한 요청이 실행됩니다.

세부정보 페이지 네트워크 요청

DevTools에서 details.css 네트워크 요청을 클릭하여 세부정보를 확인합니다. 파일이 브라우저의 디스크 캐시에서 검색된 것을 알 수 있습니다.

디스크 캐시에서 가져온 세부정보 요청

미리 가져오기는 브라우저 유휴 시간을 활용하여 다른 페이지에 필요한 리소스를 조기에 요청합니다. 이렇게 하면 브라우저가 애셋을 더 빨리 캐시하고 필요할 때 캐시에서 제공할 수 있으므로 향후 탐색 요청 속도가 빨라집니다.

webpack으로 미리 로드 및 미리 가져오기

코드 분할로 JavaScript 페이로드 줄이기 게시물에서는 동적 가져오기를 사용하여 번들을 여러 청크로 분할하는 방법을 알아봅니다. 양식을 제출할 때 Lodash에서 모듈을 동적으로 가져오는 간단한 애플리케이션을 통해 이를 확인할 수 있습니다.

코드 분할을 보여주는 Magic Sorter 앱

여기에서 이 애플리케이션의 Glitch에 액세스할 수 있습니다.

src/index.js,에 있는 다음 코드 블록은 버튼 클릭 시 메서드를 동적으로 가져오는 역할을 합니다.

form.addEventListener("submit", e => {
  e.preventDefault()
  import('lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

번들을 분할하면 초기 크기가 줄어들어 페이지 로드 시간이 개선됩니다. webpack 버전 4.6.0은 동적으로 가져온 청크를 미리 로드하거나 미리 가져오는 기능을 지원합니다. 이 애플리케이션을 예로 들면 브라우저 유휴 시간에 lodash 메서드를 미리 가져올 수 있습니다. 사용자가 버튼을 눌러도 리소스 가져오기가 지연되지 않습니다.

동적 가져오기 내에서 특정 webpackPrefetch 주석 매개변수를 사용하여 특정 단위를 미리 가져옵니다. 이 애플리케이션에서는 다음과 같이 표시됩니다.

form.addEventListener("submit", e => {
  e.preventDefault()
  import(/* webpackPrefetch: true */ 'lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

애플리케이션이 다시 로드되면 webpack이 리소스의 미리 가져오기 태그를 문서의 헤드에 삽입합니다. DevTools의 요소 패널에서 이를 확인할 수 있습니다.

프리패치 태그가 있는 요소 패널

네트워크 패널에서 요청을 관찰하면 다른 모든 리소스가 요청된 후 이 청크가 낮은 우선순위로 가져오는 것을 알 수 있습니다.

미리 가져온 요청이 있는 네트워크 패널

이 사용 사례에는 미리 가져오기가 더 적합하지만 webpack은 동적으로 가져오는 청크를 미리 로드하는 기능도 지원합니다.

import(/* webpackPreload: true */ 'module')

결론

이 Codelab을 통해 특정 애셋을 미리 로드하거나 미리 가져오는 것이 사이트의 사용자 환경을 어떻게 개선할 수 있는지 확실하게 이해해야 합니다. 이러한 기법을 모든 리소스에 사용해서는 안 되며 잘못 사용하면 성능이 저하될 수 있습니다. 최상의 결과는 선택적으로 미리 로드하거나 미리 가져오는 방식으로만 알 수 있습니다.

요약:

  • 늦게 검색되지만 현재 페이지에 중요한 리소스에는 preload를 사용하세요.
  • 향후 탐색 경로 또는 사용자 작업에 필요한 리소스에는 미리 가져오기를 사용합니다.

현재 일부 브라우저에서는 미리 로드와 미리 가져오기를 모두 지원하지 않습니다. 즉, 애플리케이션의 모든 사용자가 성능이 향상되는 것은 아닙니다.

미리 로드와 미리 가져오기가 웹페이지에 미치는 영향에 관한 자세한 내용은 다음 도움말을 참고하세요.