미리 가져오는 두 가지 방법: <link> 태그 및 HTTP 헤더

Demián Renzulli
Demián Renzulli

이 Codelab에서는 <link rel="prefetch">와 HTTP Link 헤더의 두 가지 방법으로 미리 로드를 구현합니다.

샘플 앱은 매장의 베스트셀러 티셔츠에 대한 특별 할인이 포함된 프로모션 방문 페이지가 있는 웹사이트입니다. 방문 페이지는 단일 제품으로 연결되므로 상당수의 사용자가 제품 세부정보 페이지로 이동한다고 가정할 수 있습니다. 따라서 제품 페이지는 방문 페이지에서 미리 로드하기에 적합한 후보입니다.

성능 측정

먼저 기준 성능을 설정합니다.

  1. 리믹스하여 수정을 클릭하여 프로젝트를 수정할 수 있도록 합니다.
  2. 사이트를 미리 보려면 앱 보기를 누른 다음 전체 화면 전체 화면을 누릅니다.
  3. `Control+Shift+J` (Mac의 경우 `Command+Option+J`)를 눌러 DevTools를 엽니다.
  4. 네트워크 탭을 클릭합니다.

  5. 제한 드롭다운 목록에서 빠른 3G를 선택하여 느린 연결 유형을 시뮬레이션합니다.

  6. 제품 페이지를 로드하려면 샘플 앱에서 지금 구매를 클릭합니다.

product-details.html 페이지를 로드하는 데 약 600ms가 걸립니다.

product-details.html의 로드 시간을 보여주는 네트워크 패널

탐색을 개선하려면 방문 페이지에 prefetch 태그를 삽입하여 product-details.html 페이지를 미리 로드합니다.

  • views/index.html 파일의 헤더에 다음 <link> 요소를 추가합니다.
<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">

      <link rel="prefetch" href="/product-details.html" as="document">
      ...
</head>

as 속성은 선택사항이지만 권장됩니다. 이 속성은 브라우저가 올바른 헤더를 설정하고 리소스가 이미 캐시에 있는지 확인하는 데 도움이 됩니다. 이 속성의 값 예로는 document, script, style, font, image, 기타가 있습니다.

미리 로드가 작동하는지 확인하려면 다음 단계를 따르세요.

  1. 사이트를 미리 보려면 앱 보기를 누른 다음 전체 화면 전체 화면을 누릅니다.
  2. `Control+Shift+J` (Mac의 경우 `Command+Option+J`)를 눌러 DevTools를 엽니다.
  3. 네트워크 탭을 클릭합니다.

  4. 제한 드롭다운 목록에서 빠른 3G를 선택하여 느린 연결 유형을 시뮬레이션합니다.

  5. '캐시 사용 중지' 체크박스를 선택 해제합니다.

  6. 앱을 새로고침합니다.

이제 방문 페이지가 로드되면 product-details.html 페이지도 로드되지만 우선순위가 가장 낮습니다.

미리 가져온 product-details.html을 보여주는 네트워크 패널

페이지는 5분 동안 HTTP 캐시에 보관되며, 그 후에는 문서의 일반 Cache-Control 규칙이 적용됩니다. 이 경우 product-details.html에는 값이 public, max-age=0cache-control 헤더가 있습니다. 즉, 페이지가 총 5분 동안 유지됩니다.

실적 재평가

  1. 앱을 새로고침합니다.
  2. 제품 페이지를 로드하려면 샘플 앱에서 지금 구매를 클릭합니다.

네트워크 패널을 살펴봅니다. 초기 네트워크 트레이스와 비교하여 두 가지 차이점이 있습니다.

  • 크기 열에는 '미리 가져오기 캐시'가 표시됩니다. 즉, 이 리소스는 네트워크가 아닌 브라우저의 캐시에서 가져온 것입니다.
  • 시간 열에 표시된 대로 문서를 로드하는 데 걸리는 시간이 이제 약 10ms입니다.

이는 이전 버전(약 600ms 소요)에 비해 약 98% 감소한 수치입니다.

미리 가져오기 캐시에서 가져온 product-details.html을 보여주는 네트워크 패널

추가 크레딧: 점진적 개선으로 prefetch 사용

미리 가져오기는 빠른 연결에서 탐색하는 사용자를 위한 점진적 개선사항으로 구현하는 것이 가장 좋습니다. Network Information API를 사용하여 네트워크 상태를 확인하고 이를 기반으로 프리캐시 태그를 동적으로 삽입할 수 있습니다. 이렇게 하면 느린 데이터 요금제 또는 비용이 많이 드는 데이터 요금제를 사용하는 사용자의 데이터 사용량을 최소화하고 비용을 절약할 수 있습니다.

적응형 미리 로드를 구현하려면 먼저 views/index.html에서 <link rel="prefetch"> 태그를 삭제합니다.

<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
       <link rel="prefetch" href="/product-details.html" as="document">
       ...
    </head>

그런 다음 public/script.js에 다음 코드를 추가하여 사용자가 빠른 연결 상태일 때 prefetch 태그를 동적으로 삽입하는 함수를 선언합니다.

function injectLinkPrefetchIn4g(url) {
    if (window.navigator.connection.effectiveType === '4g') {
        //generate link prefetch tag
        const linkTag = document.createElement('link');
        linkTag.rel = 'prefetch';
        linkTag.href = url;
        linkTag.as = 'document';

        //inject tag in the head of the document
        document.head.appendChild(linkTag);
    }
}

이 함수는 다음과 같이 작동합니다.

  • Network Information APIeffectiveType 속성을 확인하여 사용자가 4G (또는 그보다 빠른) 연결을 사용 중인지 확인합니다.
  • 이 조건이 충족되면 힌트 유형으로 prefetch를 사용하여 <link> 태그를 생성하고, 미리 가져올 URL을 href 속성에 전달하며, 리소스가 HTML document임을 as 속성에 나타냅니다.
  • 마지막으로 페이지의 head에 스크립트를 동적으로 삽입합니다.

다음으로 </body> 태그를 닫기 직전에 views/index.htmlscript.js를 추가합니다.

<body>
      ...
      <script src="/script.js"></script>
</body>

페이지 끝에서 script.js를 요청하면 페이지가 파싱되고 로드된 후에 로드되고 실행됩니다.

미리 로드가 현재 페이지의 중요한 리소스를 방해하지 않도록 하려면 다음 코드 스니펫을 추가하여 window.load 이벤트에서 injectLinkPrefetchIn4g()를 호출합니다.

<body>
      ...
      <script src="/script.js"></script>
      <script>
           window.addEventListener('load', () => {
                injectLinkPrefetchIn4g('/product-details.html');
           });
      </script>
</body>

이제 방문 페이지가 빠른 연결에서만 product-details.html를 미리 로드합니다. 다음 사항을 확인하세요.

  1. 사이트를 미리 보려면 앱 보기를 누른 다음 전체 화면 전체 화면을 누릅니다.
  2. `Control+Shift+J` (Mac의 경우 `Command+Option+J`)를 눌러 DevTools를 엽니다.
  3. 네트워크 탭을 클릭합니다.
  4. 제한 드롭다운 목록에서 온라인을 선택합니다.
  5. 앱을 새로고침합니다.

네트워크 패널에 product-details.html가 표시됩니다.

미리 가져온 product-details.html을 보여주는 네트워크 패널

느린 연결에서 제품 페이지가 미리 로드되지 않는지 확인하려면 다음 단계를 따르세요.

  1. 제한 드롭다운 목록에서 느린 3G를 선택합니다.
  2. 앱을 새로고침합니다.

네트워크 패널에는 product-details.html가 없는 방문 페이지의 리소스만 포함되어야 합니다.

product-details.html이 미리 로드되지 않는 것을 보여주는 네트워크 패널

HTTP Link 헤더는 link 태그와 동일한 유형의 리소스를 미리 로드하는 데 사용할 수 있습니다. 둘 중 어느 것을 사용할지는 성능 차이가 미미하므로 주로 선호도에 따라 결정됩니다. 이 경우 제품 페이지의 기본 CSS를 미리 로드하여 렌더링을 더욱 개선하는 데 사용합니다.

방문 페이지의 서버 응답에 style-product.css의 HTTP Link 헤더를 추가합니다.

  1. server.js 파일을 열고 루트 URL /get() 핸들러를 찾습니다.
  2. 핸들러 시작 부분에 다음 줄을 추가합니다.
app.get('/', function(request, response) {
    response.set('Link', '</style-product.css>; rel=prefetch');
    response.sendFile(__dirname + '/views/index.html');
});
  1. 사이트를 미리 보려면 앱 보기를 누른 다음 전체 화면 전체 화면을 누릅니다.
  2. `Control+Shift+J` (Mac의 경우 `Command+Option+J`)를 눌러 DevTools를 엽니다.
  3. 네트워크 탭을 클릭합니다.
  4. 앱을 새로고침합니다.

이제 방문 페이지가 로드된 후 style-product.css가 가장 낮은 우선순위로 미리 로드됩니다.

미리 가져온 style-product.css를 보여주는 네트워크 패널

제품 페이지로 이동하려면 지금 구매를 클릭합니다. 네트워크 패널을 살펴보세요.

미리 가져온 캐시에서 가져온 style-product.css를 보여주는 네트워크 패널

style-product.css 파일은 '미리 로드 캐시'에서 검색되며 로드하는 데 12ms밖에 걸리지 않았습니다.