향후 탐색 속도를 높이기 위해 리소스 미리 가져오기

rel=prefetch 리소스 힌트와 사용 방법을 알아보세요.

연구에 따르면 로드 시간이 빨라질수록 전환율이 높아지고 사용자 환경이 개선됩니다. 사용자가 웹사이트를 탐색하는 방식과 다음에 방문할 가능성이 높은 페이지를 파악하면 해당 페이지의 리소스를 미리 다운로드하여 향후 탐색의 로드 시간을 개선할 수 있습니다.

이 가이드에서는 <link rel=prefetch>를 사용하여 이를 실행하는 방법을 설명합니다. <link rel=prefetch>는 간편하고 효율적인 방식으로 미리 로드를 구현할 수 있는 리소스 힌트입니다.

웹페이지에 <link rel=prefetch>를 추가하면 브라우저에 전체 페이지 또는 사용자가 나중에 필요할 수 있는 일부 리소스 (예: 스크립트 또는 CSS 파일)를 다운로드하라는 신호를 보냅니다.

<link rel="prefetch" href="/articles/" as="document">

링크 미리 로드의 작동 방식을 보여주는 다이어그램

prefetch 힌트는 즉시 필요하지 않은 리소스에 추가 바이트가 소모되므로 이 기법은 신중하게 적용해야 합니다. 사용자가 리소스가 필요할 것이라고 확신할 때만 리소스를 미리 가져옵니다. 사용자가 느린 연결을 사용하는 경우 미리 로드하지 않는 것이 좋습니다. Network Information API를 사용하여 이를 감지할 수 있습니다.

미리 로드할 링크를 결정하는 방법에는 여러 가지가 있습니다. 가장 간단한 방법은 현재 페이지의 첫 번째 링크 또는 처음 몇 개의 링크를 미리 가져오는 것입니다. 이 게시물의 뒷부분에서 설명하는 것처럼 더 정교한 접근 방식을 사용하는 라이브러리도 있습니다.

사용 사례

후속 페이지 미리 가져오기

후속 페이지를 예측할 수 있는 경우 HTML 문서를 미리 가져와 링크를 클릭하면 페이지가 즉시 로드되도록 합니다.

예를 들어 제품 등록정보 페이지에서 목록에서 가장 인기 있는 제품의 페이지를 미리 로드할 수 있습니다. 다음 탐색을 더 쉽게 예측할 수 있는 경우도 있습니다. 쇼핑 장바구니 페이지에서 사용자가 결제 페이지를 방문할 가능성이 높으므로 이 페이지는 미리 가져오기에 적합합니다.

리소스 미리 로드 시 추가 대역폭이 사용되지만 대부분의 성능 측정항목을 개선할 수 있습니다. 문서 요청으로 인해 캐시가 적중하면 첫 바이트까지의 시간 (TTFB)이 훨씬 짧아지는 경우가 많습니다. TTFB가 낮아지므로 최대 콘텐츠 렌더링 시간 (LCP)콘텐츠가 포함된 첫 페인트 (FCP)를 비롯한 후속 시간 기반 측정항목도 종종 낮아집니다.

정적 애셋 미리 가져오기

사용자가 방문할 수 있는 후속 섹션을 예측할 수 있는 경우 스크립트나 스타일시트와 같은 정적 애셋을 미리 가져옵니다. 이러한 애셋이 여러 페이지에서 공유되는 경우에 특히 유용합니다.

예를 들어 Netflix는 사용자가 로그아웃한 페이지에 머무르는 시간을 활용하여 사용자가 로그인하면 사용될 React를 미리 로드합니다. 그 결과 향후 탐색의 상호작용 시작 시간이 30% 감소했습니다.

정적 애셋을 미리 로드하는 것이 성능 측정항목에 미치는 영향은 미리 로드되는 리소스에 따라 다릅니다.

  • 이미지를 미리 가져오면 LCP 이미지 요소의 LCP 시간이 크게 줄어들 수 있습니다.
  • 스타일시트를 미리 가져오면 스타일시트를 다운로드하는 데 걸리는 네트워크 시간이 제거되므로 FCP와 LCP가 모두 개선될 수 있습니다. 스타일 시트는 렌더링을 차단하므로 미리 가져올 때 LCP를 줄일 수 있습니다. 후속 페이지의 LCP 요소가 background-image 속성을 통해 요청된 CSS 배경 이미지인 경우 이미지도 미리 로드된 스타일시트의 종속 리소스로 미리 로드됩니다.
  • JavaScript를 미리 가져오면 탐색 중에 네트워크에서 먼저 가져와야 하는 경우보다 훨씬 더 빨리 미리 가져온 스크립트가 처리될 수 있습니다. 이로 인해 페이지의 다음 페인트에 대한 상호작용 (INP)이 영향을 받을 수 있습니다. 마크업이 JavaScript를 통해 클라이언트에서 렌더링되는 경우 리소스 로드 지연을 줄여 LCP를 개선할 수 있으며 페이지의 LCP 요소가 포함된 마크업의 클라이언트 측 렌더링이 더 빨리 실행될 수 있습니다.
  • 현재 페이지에서 아직 사용하지 않는 웹 글꼴을 미리 가져오면 레이아웃 전환을 제거할 수 있습니다. font-display: swap;가 사용되는 경우 글꼴의 전환 기간이 제거되어 텍스트가 더 빠르게 렌더링되고 레이아웃 전환이 제거됩니다. 향후 페이지에서 미리 가져온 글꼴을 사용하고 페이지의 LCP 요소가 웹 글꼴을 사용하는 텍스트 블록인 경우 해당 요소의 LCP도 더 빨라집니다.

주문형 JavaScript 청크 미리 가져오기

JavaScript 번들을 코드 분할하면 처음에는 앱의 일부만 로드하고 나머지는 지연 로드할 수 있습니다. 이 기법을 사용하면 즉시 필요하지는 않지만 곧 요청될 가능성이 있는 경로나 구성요소에 미리 가져오기를 적용할 수 있습니다.

예를 들어 그림 이모티콘 선택 도구가 포함된 대화상자를 여는 버튼이 포함된 페이지가 있는 경우 이 페이지를 home, dialog, picker라는 세 개의 JavaScript 청크로 나눌 수 있습니다. 홈과 대화상자는 처음에 로드될 수 있고 선택 도구는 필요에 따라 로드될 수 있습니다. webpack과 같은 도구를 사용하면 브라우저에 이러한 주문형 청크를 미리 가져오도록 지시할 수 있습니다.

rel=prefetch 구현 방법

prefetch를 구현하는 가장 간단한 방법은 문서의 <head><link> 태그를 추가하는 것입니다.

<head>
  ...
  <link rel="prefetch" href="/articles/" as="document">
  ...
</head>

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

Link HTTP 헤더를 통해 미리 가져오기를 시작할 수도 있습니다.

Link: </css/style.css>; rel=prefetch

HTTP 헤더에 미리 로드 힌트를 지정하면 브라우저가 문서를 파싱하여 리소스 힌트를 찾을 필요가 없으므로 경우에 따라 약간의 개선이 가능합니다.

webpack 매직 주석으로 JavaScript 모듈 미리 가져오기

webpack을 사용하면 사용자가 곧 방문하거나 사용할 것으로 확신하는 경로 또는 기능의 스크립트를 미리 가져올 수 있습니다.

다음 코드 스니펫은 lodash 라이브러리에서 정렬 기능을 지연 로드하여 양식으로 제출할 숫자 그룹을 정렬합니다.

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

이 기능을 로드하기 위해 '제출' 이벤트가 발생할 때까지 기다리는 대신 이 리소스를 미리 가져와 사용자가 양식을 제출할 때 캐시에서 사용할 수 있는 가능성을 높일 수 있습니다. webpack은 import() 내에서 마법 주석을 사용하여 이를 허용합니다.

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

이렇게 하면 webpack이 <link rel="prefetch"> 태그를 HTML 문서에 삽입합니다.

<link rel="prefetch" as="script" href="1.bundle.js">

주문형 청크를 미리 가져오는 것의 성능 이점은 약간 미묘하지만 일반적으로 이러한 주문형 청크에 종속된 상호작용에 대한 응답이 더 빨라질 수 있습니다. 즉시 사용할 수 있기 때문입니다. 상호작용의 특성에 따라 페이지의 INP에 이점이 있을 수 있습니다.

일반적으로 선행 로드는 전반적인 리소스 우선순위 지정에도 영향을 미칩니다. 리소스가 프리패치되면 가능한 한 가장 낮은 우선순위로 프리패치됩니다. 따라서 미리 가져온 리소스는 현재 페이지에 필요한 리소스의 대역폭을 놓고 경쟁하지 않습니다.

내부적으로 prefetch를 사용하는 라이브러리로 더 스마트한 미리 가져오기를 구현할 수도 있습니다.

quicklink와 Guess.js 모두 Network Information API를 사용하여 사용자가 느린 네트워크를 사용 중이거나 Save-Data가 사용 설정된 경우 미리 로드하지 않습니다.

미리 가져오기의 작동 원리

리소스 힌트는 필수 안내가 아니며 실행 여부와 시기는 브라우저에서 결정합니다.

동일한 페이지에서 여러 번 미리 로드할 수 있습니다. 브라우저는 모든 힌트를 큐에 추가하고 유휴 상태일 때 각 리소스를 요청합니다. Chrome에서 미리 로드가 완료되지 않았고 사용자가 대상 미리 로드 리소스로 이동하면 브라우저에서 진행 중인 로드를 탐색으로 선택합니다 (다른 브라우저 공급업체는 다르게 구현할 수 있음).

미리 가져오기는 '가장 낮음' 우선순위에서 실행되므로 미리 가져온 리소스는 현재 페이지에 필요한 리소스와 대역폭을 놓고 경쟁하지 않습니다.

미리 가져온 파일은 리소스를 캐시할 수 있는지 여부에 따라 HTTP 캐시 또는 메모리 캐시에 브라우저에 따라 달라지는 시간 동안 저장됩니다. 예를 들어 Chrome에서는 리소스가 5분 동안 유지된 후 리소스에 대한 일반 Cache-Control 규칙이 적용됩니다.

결론

prefetch를 사용하면 향후 탐색의 로드 시간이 크게 개선되고 페이지가 즉시 로드되는 것처럼 보일 수도 있습니다. prefetch는 최신 브라우저에서 광범위하게 지원되므로 많은 사용자의 탐색 환경을 개선하는 데 매력적인 기술입니다. 이 기법을 사용하려면 사용되지 않을 수도 있는 추가 바이트를 로드해야 하므로 주의해서 사용해야 합니다. 필요한 경우에만 사용하고, 가능하면 빠른 네트워크에서만 사용하세요.