Fetch Priority API로 리소스 로드 최적화

Addy Osmani
Addy Osmani
Leena Sohoni
Leena Sohoni
Patrick Meenan
Patrick Meenan

브라우저 지원

  • 102
  • 102
  • x
  • 17.2

소스

브라우저가 웹페이지를 파싱하고 이미지, 스크립트, CSS와 같은 리소스를 발견하고 다운로드하기 시작하면 최적의 순서로 다운로드할 수 있도록 리소스에 가져오기 priority를 할당합니다. 리소스의 우선순위는 일반적으로 리소스의 종류와 문서 내 위치에 따라 다릅니다 예를 들어 표시 영역 내 이미지의 우선순위는 High일 수 있으며, <head>에서 <link>를 사용하는 조기에 로드된 렌더링 차단 CSS의 우선순위는 Very High일 수 있습니다. 자동 우선순위 할당은 일반적으로 잘 작동하지만 할당된 순서가 최적화되지 않는 사용 사례도 있습니다.

이 페이지에서는 리소스의 상대적 우선순위 (high 또는 low)를 힌트를 통해 코어 웹 바이탈을 최적화하는 데 도움이 되는 Fetch Priority API와 fetchpriority HTML 속성을 설명합니다.

요약

가져오기 우선순위가 도움이 되는 몇 가지 주요 영역은 다음과 같습니다.

  • 이미지 요소에 fetchpriority="high"를 지정하여 LCP 이미지의 우선순위를 높임으로써 LCP가 더 빨리 발생하도록 합니다.
  • 현재 가장 일반적인 해킹 (async 스크립트에 <link rel="preload"> 삽입)보다 더 나은 의미 체계를 사용하여 async 스크립트의 우선순위를 높입니다.
  • 이미지 순서 지정을 개선하기 위해 지연 본문 스크립트의 우선순위를 낮춥니다.
두 가지 Google 항공편 검색 홈페이지의 테스트를 비교하는 슬라이드 보기 하단에 있는 Fetch Priority를 사용해 히어로 이미지의 우선순위를 높여 LCP를 0.7초 줄입니다.
Google 항공편 검색 테스트에서 최대 콘텐츠 페인트를 개선하는 우선순위를 2.6초에서 1.9초로 가져옵니다.

지금까지 개발자는 preloadpreconnect를 사용하여 리소스 우선순위에 대한 영향력이 제한적이었습니다. 미리 로드를 사용하면 브라우저가 자연스럽게 발견하기 전에 조기에 로드하려는 중요한 리소스를 브라우저에 알릴 수 있습니다. 이 기능은 스타일시트에 포함된 글꼴, 배경 이미지 또는 스크립트에서 로드된 리소스와 같이 찾기 어려운 리소스에 특히 유용합니다. 사전 연결은 교차 출처 서버 연결을 준비하는 데 도움이 되며 첫 바이트까지의 시간과 같은 측정항목을 개선하는 데 도움이 될 수 있습니다. 이는 출처를 알고 있지만 필요한 리소스의 정확한 URL이 아닐 때 유용합니다.

가져오기 우선순위는 이러한 리소스 힌트를 보완합니다. 개발자가 특정 리소스의 상대적 우선순위를 나타내는 데 사용할 수 있는 fetchpriority 속성을 통해 사용할 수 있는 마크업 기반 신호입니다. 또한 JavaScript 및 priority 속성과 함께 Fetch API를 통해 이러한 힌트를 사용하여 데이터의 리소스 가져오기 우선순위에 영향을 줄 수 있습니다. 가져오기 우선순위는 미리 로드를 보완할 수도 있습니다. 최대 콘텐츠 렌더링 시간 이미지를 가져옵니다. 이 이미지는 미리 로드되면 여전히 우선순위가 낮습니다. 우선순위가 낮은 다른 리소스에 의해 푸시백되는 경우 Fetch Priority를 사용하면 이미지가 로드되는 데 도움이 됩니다.

리소스 우선순위

리소스 다운로드 순서는 페이지의 모든 리소스에 대해 브라우저에 할당된 우선순위에 따라 다릅니다. 우선순위 계산 로직에 영향을 줄 수 있는 요소는 다음과 같습니다.

  • CSS, 글꼴, 스크립트, 이미지, 서드 파티 리소스와 같은 리소스 유형입니다.
  • 문서가 리소스를 참조하는 위치 또는 순서입니다.
  • preload 리소스 힌트: 브라우저가 리소스를 더 빠르게 검색하고 더 일찍 로드하는 데 도움이 됩니다.
  • async 또는 defer 스크립트의 우선순위 계산이 변경되었습니다.

다음 표는 Chrome에서 대부분의 리소스에 우선순위를 지정하고 순서를 지정하는 방식을 보여줍니다.

  레이아웃 차단 단계에서 로드 레이아웃 차단 단계에서 한 번에 하나씩 로드
깜빡임
우선순위
VeryHigh 높음 보통 낮음 VeryLow
DevTools
우선순위
최고 높음 보통 낮음 낮음
기본 리소스
CSS (초기**) CSS (늦게**) CSS (미디어 불일치***)
스크립트 (프리로드 스캐너에서 초기** 또는 사용 안 함) 스크립트 (늦게**) 스크립트 (비동기)
글꼴 글꼴 (rel=preload)
가져오기
이미지 (표시 영역 내) 이미지 (처음 5개 이미지 > 10,000px2) 이미지
미디어 (동영상/오디오)
프리페치
XSL
XHR (동기화) XHR/가져오기* (비동기)

브라우저는 계산된 우선순위가 동일한 리소스를 발견된 순서대로 다운로드합니다. 페이지를 로드할 때 Chrome 개발자 도구 네트워크 탭에서 다른 리소스에 할당된 우선순위를 확인할 수 있습니다. 표 제목을 마우스 오른쪽 버튼으로 클릭하여 우선순위 열을 포함해야 합니다.

Chrome DevTools의 네트워크 탭에 나열된 애셋의 스크린샷 열은 이름, 상태, 유형, 개시자, 크기, 시간, 우선순위의 왼쪽에서 오른쪽으로 읽습니다.
BBC 뉴스 세부정보 페이지에 있는 type = "font" 리소스의 우선순위
Chrome DevTools의 네트워크 탭에 나열된 애셋의 스크린샷 열은 이름, 상태, 유형, 개시자, 크기, 시간, 우선순위의 왼쪽에서 오른쪽으로 읽습니다.
BBC 뉴스 세부정보 페이지의 리소스 유형 우선순위 = 'script'

우선순위가 변경되면 대규모 요청 행 설정 또는 도움말에서 초기 및 최종 우선순위를 모두 확인할 수 있습니다.

Chrome DevTools의 네트워크 탭에 나열된 애셋의 스크린샷 &#39;대규모 요청 행&#39; 설정이 선택되어 있고 우선순위 열에는 우선순위가 높음이고 다른 초기 우선순위는 보통인 첫 이미지가 그 아래에 표시됩니다. 도움말에도 동일한 내용이 표시되어 있습니다.
DevTools의 우선순위 변경사항

가져오기 우선순위는 언제 필요한가요?

이제 브라우저의 우선순위 지정 로직을 이해했으므로 페이지의 다운로드 순서를 조정하여 성능과 코어 웹 바이탈을 최적화할 수 있습니다. 다음은 가져오기 우선순위를 사용하지 않고 변경할 수 있는 항목의 예입니다.

  • <script><link>와 같은 리소스 태그를 브라우저에서 다운로드할 순서대로 배치합니다.
  • preload 리소스 힌트를 사용하여 필요한 리소스, 특히 브라우저에서 찾기 어려운 리소스를 더 일찍 다운로드합니다.
  • async 또는 defer를 사용하여 다른 리소스를 차단하지 않고 스크립트를 다운로드합니다.
  • 브라우저가 더 중요한 스크롤 없이 볼 수 있는 부분에 있는 리소스에 사용 가능한 대역폭을 사용할 수 있도록 스크롤해야 볼 수 있는 콘텐츠를 지연 로드하세요.

다음과 같은 좀 더 복잡한 경우에는 가져오기 우선순위를 사용하여 필요한 리소스 우선순위 순서를 가져올 수 있습니다.

  • 스크롤 없이 볼 수 있는 부분에 여러 개의 이미지가 있지만 모든 이미지가 동일한 우선순위를 가져야 하는 것은 아닙니다. 예를 들어 이미지 캐러셀에서는 가장 먼저 표시되는 이미지에만 더 높은 우선순위가 필요합니다.
  • 표시 영역 내 히어로 이미지는 일반적으로 Low 또는 Medium 우선순위에서 시작합니다. 레이아웃이 완료되면 Chrome에서 사용자가 표시 영역에 있음을 감지하고 우선순위를 높입니다. 이로 인해 일반적으로 이미지 로드가 상당히 지연됩니다. 마크업에 가져오기 우선순위를 제공하면 이미지를 '높음' 우선순위에서 시작하고 훨씬 일찍 로드할 수 있습니다.

    CSS 배경으로 포함된 LCP 이미지의 조기 탐색에는 여전히 미리 로드가 필요합니다. 배경 이미지의 우선순위를 높이려면 미리 로드에 fetchpriority='high'를 포함합니다.
  • 스크립트를 async 또는 defer로 선언하면 브라우저가 스크립트를 비동기식으로 로드하도록 지시합니다. 그러나 우선순위 표에 표시된 것처럼 이러한 스크립트에는 '낮음' 우선순위도 할당됩니다. 특히 사용자 환경에 중요한 스크립트의 경우 비동기식 다운로드를 보장하면서 우선순위를 높이는 것이 좋습니다.
  • JavaScript fetch() API를 사용하여 리소스 또는 데이터를 비동기적으로 가져오는 경우 브라우저는 High 우선순위를 할당합니다. 특히 백그라운드 API 호출과 사용자 입력에 응답하는 API 호출을 혼합하는 경우 일부 가져오기를 낮은 우선순위로 실행하는 것이 좋습니다. 백그라운드 API 호출은 Low 우선순위로, 대화형 API 호출은 High 우선순위로 표시합니다.
  • 브라우저는 CSS 및 글꼴에 High" priority를 할당하지만 이러한 리소스 중 일부가 다른 리소스보다 더 중요할 수 있습니다. 가져오기 우선순위를 사용하여 중요하지 않은 리소스의 우선순위를 낮출 수 있습니다.

fetchpriority 속성

fetchpriority HTML 속성을 사용하여 link, img 또는 script 태그를 사용하여 다운로드할 때 CSS, 글꼴, 스크립트, 이미지와 같은 리소스 유형의 다운로드 우선순위를 지정합니다. 다음 값을 사용할 수 있습니다.

  • high: 리소스의 우선순위가 높으며, 브라우저 자체 휴리스틱에 의해 차단되지 않는 한 브라우저에서 리소스의 우선순위를 지정하려고 합니다.
  • low: 리소스의 우선순위가 낮으며 휴리스틱이 허용하는 경우 브라우저에서 리소스의 우선순위를 낮춥니다.
  • auto: 기본값. 브라우저가 적절한 우선순위를 선택할 수 있습니다.

다음은 마크업에서 fetchpriority 속성과 스크립트에 상응하는 priority 속성을 사용하는 몇 가지 예입니다.

<!-- We don't want a high priority for this above-the-fold image -->
<img src="/images/in_viewport_but_not_important.svg" fetchpriority="low" alt="I'm an unimportant image!">

<!-- We want to initiate an early fetch for a resource, but also deprioritize it -->
<link rel="preload" href="/js/script.js" as="script" fetchpriority="low">

<script>
  fetch('https://example.com/', {priority: 'low'})
  .then(data => {
    // Trigger a low priority fetch
  });
</script>

브라우저 우선순위 및 fetchpriority의 영향

다음 표와 같이 fetchpriority 속성을 여러 리소스에 적용하여 계산된 우선순위를 늘리거나 줄일 수 있습니다. 각 행의 fetchpriority="auto" (◉)은 해당 리소스 유형의 기본 우선순위를 표시합니다.

  레이아웃 차단 단계에서 로드 레이아웃 차단 단계에서 한 번에 하나씩 로드
깜빡임
우선순위
VeryHigh 높음 보통 낮음 VeryLow
DevTools
우선순위
최고 높음 보통 낮음 낮음
기본 리소스
CSS (초기**) ⬆◉
CSS (늦게**)
CSS (미디어 불일치***) ⬆*** ◉⬇
스크립트 (프리로드 스캐너에서 초기** 또는 사용 안 함) ⬆◉
스크립트 (늦게**)
스크립트 (async/defer) ◉⬇
글꼴
글꼴 (rel=preload) ⬆◉
가져오기
이미지 (표시 영역에 있음 - 레이아웃 후) ⬆◉
이미지 (처음 5개 이미지 > 10,000px2)
이미지 ◉⬇
미디어 (동영상/오디오)
XHR (동기화) - 지원 중단됨
XHR/가져오기* (비동기) ⬆◉
프리페치
XSL

fetchpriority상대적 우선순위를 설정합니다. 즉, 우선순위를 명시적으로 High 또는 Low로 설정하는 대신 적절한 금액만큼 기본 우선순위를 높이거나 낮춥니다. 이로 인해 우선순위가 High 또는 Low인 경우가 많지만 항상 그런 것은 아닙니다. 예를 들어 fetchpriority="high"가 있는 중요한 CSS는 '매우높음'/'가장 높은' 우선순위를 유지하며 이러한 요소에 fetchpriority="low"를 사용하면 '높음' 우선순위가 유지됩니다. 두 경우 모두 우선순위를 High 또는 Low로 명시적으로 설정하지 않습니다.

사용 사례

리소스를 가져올 우선순위에 관한 추가 힌트를 브라우저에 제공하려면 fetchpriority 속성을 사용합니다.

LCP 이미지의 우선순위 높이기

fetchpriority="high"를 지정하여 LCP 또는 기타 중요한 이미지의 우선순위를 높일 수 있습니다.

<img src="lcp-image.jpg" fetchpriority="high">

다음 비교에서는 가져오기 우선순위를 사용하거나 사용하지 않고 LCP 배경 이미지가 로드된 Google 항공편 검색 페이지를 보여줍니다. 우선순위를 높음으로 설정하면 LCP가 2.6초에서 1.9초로 개선되었습니다.

Cloudflare 작업자를 통해 Fetch Priority를 사용하여 Google 항공편 페이지를 재작성하는 실험

fetchpriority="low"를 사용하여 스크롤 없이 볼 수 있는 부분 중 이미지 캐러셀과 같이 당장 중요하지 않은 이미지의 우선순위를 낮춥니다.

<ul class="carousel">
  <img src="img/carousel-1.jpg" fetchpriority="high">
  <img src="img/carousel-2.jpg" fetchpriority="low">
  <img src="img/carousel-3.jpg" fetchpriority="low">
  <img src="img/carousel-4.jpg" fetchpriority="low">
</ul>

이전 Oodle 앱 실험에서는 이를 사용하여 로드 시 표시되지 않는 이미지의 우선순위를 낮췄습니다. 페이지 로드 시간이 2초 줄었습니다.

가져오기 우선순위를 Oodle 앱의 이미지 캐러셀에서 사용할 때 나란히 비교 왼쪽에서 브라우저가 캐러셀 이미지의 기본 우선순위를 설정하지만 오른쪽 예시보다 이러한 이미지를 약 2초 느리게 다운로드하고 페인트합니다. 이는 첫 번째 캐러셀 이미지에만 더 높은 우선순위를 설정합니다.
첫 번째 캐러셀 이미지에만 높은 우선순위를 사용하면 페이지를 더 빠르게 로드할 수 있습니다.

미리 로드된 리소스의 우선순위 낮춤

미리 로드된 리소스가 다른 중요한 리소스와 경쟁하지 않도록 하려면 우선순위를 낮추면 됩니다. 이미지, 스크립트 및 CSS에 이 기법을 사용하세요.

<!-- Lower priority only for non-critical preloaded scripts -->
<link rel="preload" as="script" href="critical-script.js">
<link rel="preload" href="/js/script.js" as="script" fetchpriority="low">

<!-- Preload CSS without blocking other resources -->
<link rel="preload" as="style" href="theme.css" fetchpriority="low" onload="this.rel='stylesheet'">

스크립트 우선순위 다시 지정

페이지에서 상호작용이 가능해야 하는 스크립트는 빠르게 로드되어야 하지만 다른 리소스를 차단해서는 안 됩니다. 이를 높은 우선순위의 async로 표시할 수 있습니다.

<script src="async_but_important.js" async fetchpriority="high"></script>

스크립트가 특정 DOM 상태를 사용하는 경우 스크립트를 async로 표시할 수 없습니다. 하지만 페이지에서 나중에 실행되는 경우 더 낮은 우선순위로 로드할 수 있습니다.

<script src="blocking_but_unimportant.js" fetchpriority="low"></script>

중요하지 않은 데이터 가져오기의 우선순위 낮추기

브라우저가 높은 우선순위로 fetch를 실행합니다. 동시에 실행될 수 있는 가져오기가 여러 개 있는 경우 더 중요한 데이터 가져오기에는 높은 기본 우선순위를 사용하고 덜 중요한 데이터의 우선순위는 낮출 수 있습니다.

// Important validation data (high by default)
let authenticate = await fetch('/user');

// Less important content data (suggested low)
let suggestedContent = await fetch('/content/suggested', {priority: 'low'});

우선순위 구현 참고사항 가져오기

다음은 가져오기 우선순위를 사용할 때 유의해야 할 사항입니다.

  • fetchpriority 속성은 지시어가 아닌 힌트입니다. 브라우저는 개발자의 환경설정을 존중하려고 하지만 리소스 우선순위에 관한 리소스 우선순위 환경설정을 적용하여 충돌을 해결할 수도 있습니다.
  • 가져오기 우선순위를 미리 로드와 혼동하지 마세요.

    • 미리 로드는 힌트가 아니라 필수 가져오기입니다.
    • 미리 로드를 사용하면 브라우저가 리소스를 조기에 발견할 수 있지만 기본 우선순위로 리소스를 가져옵니다. 한편 가져오기 우선순위는 검색 가능성에 도움이 되지 않지만 가져오기 우선순위를 높이거나 낮출 수 있습니다.
    • 우선순위 변경의 효과보다 미리 로드의 효과를 관찰하고 측정하기가 더 쉽습니다.

    가져오기 우선순위를 사용하면 우선순위 지정의 세분화 정도를 늘려 미리 로드를 보완할 수 있습니다. 이미 미리 로드를 LCP 이미지의 <head>의 첫 번째 항목 중 하나로 지정한 경우 high 가져오기 우선순위를 사용해도 LCP가 크게 개선되지 않을 수 있습니다. 그러나 다른 리소스가 로드된 후 미리 로드가 발생하는 경우 high 가져오기 우선순위로 LCP를 더 개선할 수 있습니다. 중요한 이미지가 CSS 배경 이미지인 경우 fetchpriority = "high"를 사용하여 미리 로드합니다.

  • 우선순위를 지정하여 로드 시간을 개선하면 더 많은 리소스가 사용 가능한 네트워크 대역폭을 두고 경쟁하는 환경에서 더 중요합니다. 이는 동시 다운로드가 불가능한 HTTP/1.x 연결이나 낮은 대역폭의 HTTP/2 연결에서 일반적입니다. 이러한 경우 우선순위를 지정하면 병목 현상을 해결할 수 있습니다.

  • CDN은 균일하게 HTTP/2 우선순위를 구현하지 않습니다. 브라우저가 Fetch Priority의 우선순위를 전달하더라도 CDN은 지정된 순서로 리소스의 우선순위를 다시 지정하지 않을 수 있습니다. 이로 인해 가져오기 우선순위를 테스트하기가 어려워집니다. 우선순위는 브라우저 내부와 우선순위 지정을 지원하는 프로토콜 (HTTP/2 및 HTTP/3)을 통해 모두 적용됩니다. 브라우저가 리소스를 요청할 때 우선순위가 변경되는 경우가 많으므로 CDN 또는 원본 지원과 별개로 내부 브라우저 우선순위 지정에만 Fetch Priority를 사용하는 것이 좋습니다. 예를 들어 이미지와 같이 우선순위가 낮은 리소스는 브라우저에서 중요한 <head> 항목을 처리하는 동안 종종 보류됩니다.

  • 초기 설계에서는 가져오기 우선순위를 권장사항으로 도입하지 못할 수도 있습니다. 개발 주기 후반에 페이지의 여러 리소스에 우선순위를 할당할 수 있으며, 우선순위가 예상과 일치하지 않으면 추가 최적화를 위해 가져오기 우선순위를 도입할 수 있습니다.

미리 로드 사용 팁

미리 로드를 사용할 때는 다음 사항에 유의하세요.

  • HTTP 헤더에 미리 로드를 포함하면 로드 순서의 다른 모든 항목보다 먼저 배치됩니다.
  • 일반적으로 우선순위가 '중간' 이상인 경우 파서가 미리 로드한 순서대로 로드됩니다. 미리 로드를 포함하는 경우 HTML의 시작 부분에 주의하세요.
  • 글꼴 미리 로드는 머리 끝 또는 본문 시작 부분에서 가장 잘 작동합니다.
  • 미리 로드 가져오기 (동적 import() 또는 modulepreload)는 가져오기가 필요한 스크립트 태그 다음에 실행되어야 하므로 종속 항목이 로드되는 동안 평가될 수 있도록 먼저 스크립트를 로드하거나 파싱해야 합니다.
  • 이미지 미리 로드의 우선순위는 기본적으로 '낮음' 또는 '중간'입니다. 비동기 스크립트 및 기타 우선순위가 낮거나 가장 낮은 태그를 기준으로 정렬하세요.

기록

Fetch Priority는 2018년에 Chrome에서 오리진 트라이얼로 처음 실험한 후 2021년에 다시 importance 속성을 사용하여 테스트되었습니다. 당시 이 기능은 우선순위 힌트였습니다. 이후 인터페이스는 웹 표준 프로세스의 일부로 HTML의 경우 fetchpriority, 자바스크립트의 Fetch API의 경우 priority로 변경되었습니다. 혼동을 줄이기 위해 이제 이 API 가져오기 우선순위를 호출합니다.