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

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 미리 가져오기를 사용하면 탐색 중에 네트워크에서 먼저 가져와야 하는 경우보다 미리 가져온 스크립트를 훨씬 더 빨리 처리할 수 있습니다. 이는 페이지의 다음 페인트에 대한 상호작용 (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를 사용하는 라이브러리를 사용하여 더 스마트한 미리 가져오기를 구현할 수도 있습니다.

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

내부에서 미리 가져오기

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

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

미리 가져오기는 'Lowest'(최저) 값에서 우선순위로 설정되어 있지 않으므로 미리 가져온 리소스는 현재 페이지에 필요한 리소스와 대역폭을 놓고 경쟁하지 않습니다.

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

결론

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