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

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일 수 있습니다. 브라우저는 잘 작동하는 우선순위를 할당하는 데 능숙하지만 모든 경우에 최적화되어 있지는 않습니다.

이 페이지에서는 리소스의 상대적 우선순위를 암시할 수 있는 fetchpriority HTML 속성 (high 또는 low)과 Fetch Priority API에 대해 설명합니다. 가져오기 우선순위는 코어 웹 바이탈을 최적화하는 데 도움이 됩니다.

요약

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

  • 이미지 요소에 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, 글꼴, 스크립트, 이미지, 타사 리소스 등 리소스 유형입니다.
  • 문서가 리소스를 참조하는 위치 또는 순서입니다.
  • 스크립트에서 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 뉴스 세부정보 페이지에 있는 type = "script" 리소스의 우선순위

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

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

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

이제 브라우저의 우선순위 지정 로직을 이해했으니 페이지의 다운로드 순서를 조정하여 성능과 코어 웹 바이탈을 최적화할 수 있습니다. 리소스 다운로드 우선순위에 영향을 주기 위해 변경할 수 있는 항목의 예는 다음과 같습니다.

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

이러한 기법을 사용하면 브라우저의 우선순위 계산을 제어하여 성능과 코어 웹 바이탈을 개선할 수 있습니다. 예를 들어 중요한 배경 이미지가 미리 로드되면 훨씬 일찍 발견되어 최대 콘텐츠 렌더링 시간 (LCP)을 개선할 수 있습니다.

때때로 이러한 핸들은 애플리케이션에 맞게 리소스의 우선순위를 최적화하기에 충분하지 않을 수 있습니다. 다음은 우선순위 가져오기가 도움이 될 수 있는 몇 가지 시나리오입니다.

  • 스크롤 없이 볼 수 있는 부분에 여러 개의 이미지가 있지만 모든 이미지의 우선순위가 같아서는 안 됩니다. 예를 들어 이미지 캐러셀에서 가장 먼저 표시되는 이미지만 더 높은 우선순위를 필요로 하고, 일반적으로 초기에는 화면 밖인 다른 이미지는 더 낮은 우선순위를 갖도록 설정할 수 있습니다.
  • 표시 영역 내 이미지는 일반적으로 우선순위 Low에서 시작합니다. 레이아웃이 완료되면 Chrome은 사용자가 표시 영역에 있음을 감지하고 우선순위를 높입니다. 이로 인해 일반적으로 히어로 이미지와 같은 중요한 이미지를 로드하는 데 상당한 지연이 발생합니다. 마크업에 Fetch Priority를 제공하면 이미지가 High 우선순위에서 시작하고 훨씬 일찍 로드될 수 있습니다. Chrome에서 처음 5개의 큰 이미지를 어느 정도 자동화하기 위해 Medium의 우선순위로 설정하는 데 도움이 되지만, 명시적인 fetchpriority="high"을 사용하면 훨씬 더 좋습니다.

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

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" (◉)은 해당 리소스 유형의 기본 우선순위를 표시합니다. (Google 문서로 사용 가능).

  레이아웃 차단 단계에서 로드 레이아웃 차단 단계에서 한 번에 하나씩 로드
깜빡임
우선순위
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>

이미지 2~4는 표시 영역 밖에 있지만 high로 부스트하고 load=lazy 속성이 추가되더라도 로드하기에 '충분히 가까운' 것으로 간주될 수 있습니다. 따라서 이를 위한 올바른 솔루션은 fetchpriority="low"입니다.

이전 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" as="script" href="non-critical-script.js" fetchpriority="low">

<!-- Preload CSS without blocking render, or 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>

이렇게 하면 이 스크립트에 도달하면 파서를 계속 차단하지만 이보다 이전의 콘텐츠에 우선순위를 부여할 수 있습니다.

완성된 DOM이 필요한 경우 대안으로, defer 속성 (DOMContentLoaded 다음에 순서대로 실행됨)을 사용하거나 페이지 하단의 async를 사용할 수도 있습니다.

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

브라우저가 높은 우선순위로 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 또는 HTTP/3 연결에서 일반적입니다. 이 경우 우선순위를 지정하면 병목 현상을 해결할 수 있습니다.

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

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

개발자는 파서에서 감지하지 않는 리소스 (글꼴, 가져오기, 백그라운드 LCP 이미지)를 미리 로드하는 데 의도된 목적으로 미리 로드를 사용해야 합니다. preload 힌트의 배치는 리소스가 미리 로드되는 시점에 영향을 미칩니다.

가져오기 우선순위는 리소스를 가져올 때 가져오는 방법에 관한 것입니다.

미리 로드 사용 팁

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

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

기록

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

결론

미리 로드 동작이 수정되고 최근에는 코어 웹 바이탈과 LCP에 중점을 둔 가져오기 우선순위에 개발자들이 관심을 가질 가능성이 높습니다. 이제 선호하는 로드 시퀀스를 달성하는 데 사용할 수 있는 추가 노브가 있습니다.