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

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

연구에 따르면 로드 시간이 단축되면 전환율이 높아지고 사용자 환경이 개선됩니다. 사용자가 웹사이트에서 어떻게 이동하는지, 다음에 어떤 페이지를 방문할지 알 수 있다면 해당 페이지의 리소스를 미리 다운로드하여 향후 탐색의 로드 시간을 개선할 수 있습니다.

이 가이드에서는 미리 가져오기를 쉽고 효율적으로 구현할 수 있게 해주는 리소스 힌트<link rel=prefetch>를 사용하여 이 작업을 수행하는 방법을 설명합니다.

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 미리 가져오기를 사용하면 탐색 중에 네트워크에서 먼저 가져와야 하는 경우보다 미리 가져온 스크립트를 처리할 수 있습니다. 이는 첫 입력 지연 (FID)다음 페인트에 대한 상호작용 (INP)과 같은 반응성 측정항목에 영향을 미칠 수 있습니다. JavaScript를 통해 클라이언트에서 마크업이 렌더링되는 경우 리소스 로드 지연을 줄여 LCP를 개선할 수 있으며, 페이지의 LCP 요소가 포함된 마크업의 클라이언트 측 렌더링이 더 빨리 발생할 수 있습니다.
  • 현재 페이지에서 아직 사용하지 않는 웹 글꼴을 미리 가져오면 레이아웃 변경을 없앨 수 있습니다. font-display: swap;가 사용되는 경우 글꼴의 스왑 기간이 제거되므로 텍스트가 더 빠르게 렌더링되고 레이아웃 변경이 제거됩니다. 향후 페이지에서 미리 가져온 글꼴을 사용하고 페이지의 LCP 요소가 웹 글꼴을 사용하는 텍스트 블록인 경우 해당 요소의 LCP도 더 빨라집니다.

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

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

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

rel=prefetch 구현 방법

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

<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) });
});

이 기능을 로드하기 위해 'submit' 이벤트가 발생할 때까지 기다리는 대신 이 리소스를 미리 가져와 사용자가 양식을 제출할 때까지 캐시에서 리소스를 사용할 가능성을 높일 수 있습니다. 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를 사용하는 라이브러리를 사용하여 더 스마트한 미리 가져오기를 구현할 수도 있습니다.

빠른 링크와 Guess.js는 모두 Network Information API를 사용하여 사용자가 느린 네트워크를 사용하거나 Save-Data를 사용 설정한 경우 미리 가져오기를 방지합니다.

미리 가져오기

리소스 힌트는 필수적인 지침이 아니며, 실행 여부와 시기는 브라우저가 결정합니다.

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

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

미리 가져온 파일은 HTTP 캐시 또는 메모리 캐시 (리소스의 캐시 가능 여부에 따라 다름)에 저장되며, 소요 시간은 브라우저에 따라 다릅니다. 예를 들어 Chrome 리소스는 5분 동안 유지된 후 리소스에 대한 일반적인 Cache-Control 규칙이 적용됩니다.

결론

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