Core Web Vitals 리소스 우선순위 지정 가이드

먼저 로드할 리소스와 대기할 리소스 제어

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-02-25

Core Web Vitals 리소스 우선순위 지정 가이드

브라우저의 기본 우선순위 지정 엔진은 휴리스틱으로 작동합니다. 즉, 파일 유형과 문서 위치를 기반으로 한 불완전한 추측입니다. 리소스는 preload 스캐너 또는 DOM 파서가 발견하는 시점에 따라 대기열에 추가됩니다.

Arjen Karel 님이 2026년 2월에 마지막으로 검토함

네트워크 대역폭과 CPU가 무제한 리소스가 아니라는 점을 고려할 때 이는 문제가 될 수 있습니다. 예를 들어, 낮은 우선순위의 추적 스크립트를 위해 전송되는 모든 바이트는 다운로드가 동시에 진행되는 동안 Largest Contentful Paint (LCP)에 필요한 바이트와 직접적으로 경쟁하게 됩니다.

이것은 브라우저의 잘못이 아닙니다. 예제의 HTML에서 브라우저는 잘못된 애셋의 우선순위를 지정하여 중요한 렌더링이 지연되었다는 사실을 알 수 있는 방법이 없었습니다.

무엇이 중요한지 아는 사람은 바로 사용자이며, 우선순위 지정(중요한 신호 강화) 및 우선순위 해제(덜 방해될 때까지 중요하지 않은 리소스 예약)라는 두 가지 메커니즘을 통해 이 일정을 제어합니다.

브라우저 휴리스틱의 한계

브라우저는 "계산된 우선순위" 점수에 따라 우선순위를 할당합니다. 이 점수는 애셋 유형(CSS, Script, Image) 및 HTML/DOM에서의 위치에서 파생됩니다. 단순한 문서에서는 일반적으로 효과적이지만, 리소스가 초기(preload 스캐너에 의해) 인식되지 않거나 잘못된 리소스가 조기 다운로드를 위해 트리거될 경우 이 시스템은 실패합니다.

Chrome의 기본 우선순위 레벨

Chrome은 Highest, High, Medium, Low, Lowest의 다섯 가지 내부 우선순위 레벨을 사용합니다. 기본적으로 할당하는 방식은 다음과 같습니다.

리소스 기본 우선순위 fetchpriority="high" 사용 시 fetchpriority="low" 사용 시
CSS (<head> 내부) Highest (이미 최대치) High
Script (블로킹, <head> 내부) Highest (이미 최대치) Low
Script (async / defer) Low High Lowest
Font (preload를 통해) Highest (이미 최대치) 해당 없음
Font (CSS 내부) High 해당 없음 해당 없음
Image (기본) Low High Lowest
Image (처음 5개의 큰 이미지) Medium High Low
Image (뷰포트 내, 레이아웃 이후) High (이미 High) 해당 없음

fetchpriority 속성은 <img>, <link><script> 요소에서 지원됩니다. 전 세계 브라우저의 93%가 지원하며(Chrome 102+, Firefox 132+, Safari 17.2+, Edge 102+) 점진적 향상 기능입니다. 즉, 이를 지원하지 않는 브라우저는 단순히 무시합니다. 2025 Web Almanac에 따르면 모바일 페이지의 17%가 fetchpriority="high"를 사용하지만, fetchpriority="low"를 사용하는 비율은 0.3%에 불과합니다. 이는 우선순위 해제가 널리 활용되지 않고 있는 최적화 기법임을 의미합니다.

Preload 스캐너의 한계

검색 속도를 높이기 위해 브라우저는 메인 HTML 파서보다 먼저 실행되어 리소스 URL을 찾는 경량 파서인 "preload 스캐너"를 사용합니다. 이 스캐너에는 한계가 있지만(빠르고 효과적으로 작동하게 만드는 요소이기도 함), 오직 HTML만 구문 분석합니다. CSS 파일 내부를 볼 수 없고, JavaScript를 실행하지 않으며, 렌더링을 하지 않으므로 리소스가 뷰포트에 표시되는지 확인할 수 없습니다.

결과적으로 스크립트에 의해 주입되거나 지연 로드되는 등 스타일시트에서 참조되는 리소스(예: 배경 이미지 또는 웹 폰트)는 메인 파서가 전체 웹페이지를 다운로드하고 처리할 때까지 건너뛰어집니다. 이로 인해 브라우저가 중요한 애셋의 존재를 실질적으로 알지 못하는 "discovery delay"가 발생합니다.

리소스 경합

브라우저가 애셋을 검색하면 대기 중인 다른 요청과 동시에 다운로드를 시도하는 경우가 많습니다. 중요한 LCP 이미지가 중간 우선순위의 스크립트나 중요하지 않은 이미지(예: 바닥글의 소셜 미디어 아이콘)와 경쟁하는 경우 사용 가능한 대역폭을 나누어 사용합니다. 이러한 경합은 둘 다의 로드 시간을 연장시켜 LCP 지표를 "Needs Improvement" 영역으로 밀어냅니다.

수동 우선순위 지정 전략

빠른 렌더링 경로를 구축하려면 수동으로 개입해야 합니다. 목표는 LCP의 대역폭을 최대화하고 다른 모든 항목의 대역폭을 최소화하는 것입니다. CoreDash에서 모니터링하는 사이트 전반에 걸쳐 LCP 이미지에 fetchpriority="high"를 사용하는 사이트의 82%가 LCP를 통과한 반면, 그렇지 않은 사이트는 61%였습니다.

1. Preload를 사용하여 검색 문제 해결

숨겨진 애셋을 수동으로 preload 스캐너에 노출시켜야 합니다. rel="preload"를 사용하여 중요한 리소스를 HTML <head>로 이동함으로써 브라우저가 즉시 리소스를 인식하도록 강제하여 검색 지연을 제거할 수 있습니다. 전체 과정은 LCP 이미지 preload 가이드를 참조하세요.

구현:

<!-- 폰트를 스캐너에 즉시 노출 -->
<link rel="preload" as="font" type="font/woff2" href="/fonts/inter-bold.woff2" crossorigin>

<!-- LCP 배경 이미지를 즉시 노출 -->
<link rel="preload" as="image" href="/images/hero-banner.jpg" fetchpriority="high">

더 이른 검색을 위해서는 HTML 응답이 도착하기 전에 브라우저에 preload 신호를 보내는 103 Early Hints를 고려하세요.

2. LCP 휴리스틱 재정의

브라우저는 초기 가져오기 중에 최종 레이아웃 크기를 알 수 없기 때문에 이미지에 종종 "Low" 또는 "Medium" 우선순위를 할당합니다. 브라우저는 렌더 트리가 빌드된 후에야 이미지가 LCP인지 확인할 수 있는데, 이 시점은 이미 너무 늦습니다.

구현:

fetchpriority="high"를 사용하여 LCP 요소에 "High" 우선순위 상태를 강제 지정합니다. 이렇게 하면 내부 휴리스틱을 우회하고 이미지를 다운로드 대기열의 맨 앞에 배치합니다. Google 항공편은 이 단일 속성을 추가하여 LCP를 2.6초에서 1.9초로 단축(0.7초 개선)했습니다.

<!-- 즉시 높은 우선순위 가져오기 강제 -->
<img src="hero.jpg" alt="Hero Product" fetchpriority="high">

여기서 최악의 실수는 LCP 이미지의 지연 로드이며, 이는 페이지에서 가장 중요한 요소의 우선순위를 적극적으로 해제하게 됩니다.

3. 중요하지 않은 이미지의 우선순위 해제

우선순위를 높이는 것보다 대역폭을 확보하는 것이 더 효과적인 경우가 많습니다. 필수적이지 않은 애셋을 명시적으로 지연시켜 중요한 리소스를 위한 네트워크 파이프를 확보해야 합니다.

구현:

  • 스크롤 아래 (Below the fold): 사용자가 스크롤할 때까지 loading="lazy"를 사용하여 화면 밖의 이미지들을 지연시킵니다.
  • 스크롤 위 (Above the fold), 보조: 초기에 렌더링되지만 LCP보다 덜 중요한 캐러셀 슬라이드 또는 보조 시각적 요소에 대해 fetchpriority="low"를 사용합니다.
  • 스크롤 위 (Above the fold), 시각적으로 중요하지 않음: loading="lazy"를 사용하여 preload 스캐너를 우회하고 낮은 대역폭 우선순위를 할당합니다. 첫 렌더링 시 눈에 띄지 않으면서도 초기 대역폭 요청을 많이 유발할 수 있는 국기나 아이콘 같은 작은 이미지에 유용합니다.
<!-- LCP 이미지: 가장 높은 우선순위 -->
<img src="slide-1.jpg" fetchpriority="high">

<!-- 보조 캐러셀 이미지: 즉시 가져오기, 낮은 대역폭 사용 -->
<img src="slide-2.jpg" fetchpriority="low">

<!-- 번역 국기: 뷰포트에 있는 동안 preload 스캐너에서 숨김 -->
<img src="dutch-flag.jpg" loading="lazy" fetchpriority="low">

<!-- 화면 밖 이미지: 지연된 가져오기 -->
<img src="footer-promo.jpg" loading="lazy">

4. 스크립트 실행 제어

JavaScript는 DOM 파서를 차단합니다. 표준 <script> 태그를 사용하면 브라우저는 파일을 다운로드하고 실행하기 위해 HTML 구문 분석을 중지합니다. 제어되지 않는 스크립트 실행은 기본 스레드를 차단하여 Interaction to Next Paint (INP)에 직접적인 악영향을 미칩니다.

구현:

  • defer: 애플리케이션 로직에 사용합니다. 병렬로 다운로드(Low 우선순위)하고 HTML이 완전히 구문 분석된 후에만 실행하여 종속성 순서를 유지합니다.
  • async: 독립적인 타사 스크립트(예: 분석)에 사용합니다. 병렬로 다운로드하고 완료 즉시 실행되며 순서를 무시합니다.
  • async + fetchpriority="high": 구문 분석을 차단하지 않고 빠른 다운로드가 필요한 중요한 async 스크립트(예: A/B 테스트)에 사용합니다. 이는 실행을 비차단 상태로 유지하면서 다운로드 우선순위를 Low에서 High로 높입니다.
  • 주입(Inject): preload 스캐너를 우회하여 초기 대역폭과 경쟁하지 않도록 합니다. 주입된 스크립트는 async로 처리됩니다.
  • 예약(Schedule) + 주입: 예를 들어 load 이벤트가 발생한 후와 같이 나중에 스크립트를 주입합니다.
<!-- 애플리케이션 로직: 비차단, 실행 순서 유지 -->
<script src="app.js" defer></script>

<!-- 타사 동의: 비차단, 독립적인 실행 -->
<script src="consent.js" async></script>

<!-- 중요한 async: 빠른 다운로드, 비차단 실행 -->
<script src="ab-test.js" async fetchpriority="high"></script>

<script>
  /* 분석 주입 예시 */
  const script = document.createElement('script');
  script.src = 'analytics.js';
  script.async = true;
  document.head.appendChild(script);

  /* 채팅을 위한 주입 + 예약 예시 */
  window.addEventListener('load', () => {
    const chatScript = document.createElement('script');
    chatScript.src = 'chat-widget.js';
    document.head.appendChild(chatScript);
  });
</script>

사용 가능한 모든 기법에 대한 포괄적인 분석은 JavaScript를 지연시키는 16가지 방법async 대 defer JavaScript를 참조하세요. 중요도에 따른 스크립트 분류에 대한 지침은 JavaScript 우선순위 레벨을 참조하세요.

5. CSS 렌더링 차단 해제

CSS는 설계상 렌더링을 차단합니다. 브라우저는 CSS가 없으면 페이지가 어떻게 보일지 알 수 없습니다. 따라서 스타일시트를 먼저 다운로드하고 구문 분석합니다.

최적화 전략:

  • @import 피하기: 성능을 심각하게 저하시키는 순차적인 종속성 체인을 만듭니다.
  • 번들 크기 최적화: 3kB(오버헤드)보다 작거나 20kB(차단)보다 큰 CSS 파일은 피하세요. 이상적으로는 약 15kB 파일을 목표로 합니다.
  • 비동기 로드(Async Loading): 화면 밖의 스타일을 비동기식으로 로드하여 중요 경로의 차단을 해제합니다.
  • 중요(Critical) CSS의 트레이드오프: Critical CSS를 인라인화하면 첫 페이지 뷰가 향상되지만 브라우저 캐시를 우회하여 후속 페이지 뷰가 지연될 수 있습니다.

구현:

@import를 완전히 제거하세요. 병렬 로드를 위해 <link> 태그를 사용하세요. 중요하지 않은 CSS(예: 인쇄 스타일)의 경우 media 속성을 사용하여 기본 스레드의 차단을 해제하세요. CSS 최적화에 대한 자세한 내용은 사용하지 않는 CSS 제거를 참조하세요.

<!-- 중요(Critical) CSS: 렌더링 차단 (정확함) -->
<link rel="stylesheet" href="main.css">

<!-- 인쇄 CSS: 인쇄 이벤트가 발생할 때까지 비차단 -->
<link rel="stylesheet" href="print.css" media="print">

<!-- 비동기 패턴: 낮은 우선순위로 로드되며 로드 시 적용됨 -->
<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">

6. 폰트 렌더링 안정화

폰트는 무거운 차단 리소스입니다. 효과적인 우선순위 지정을 위해서는 다운로드되는 항목에 대한 엄격한 제한과 렌더링 방식에 대한 제어가 필요합니다.

최적화 전략:

  • 엄격한 Preload 제한: 가장 중요한 폰트 파일 1~2개(일반적으로 LCP 텍스트)만 preload 하세요. 5개 이상의 폰트를 preload 하면 대역폭이 정체됩니다.
  • 셀프 호스팅(Self-host): 타사 CDN에서 로드하는 대신 웹 폰트를 셀프 호스팅하세요. 이렇게 하면 추가적인 연결 설정이 필요하지 않습니다.
  • 페이로드(Payload) 감소: 가변 폰트(모든 두께에 대해 하나의 파일) 및 서브세팅(사용하지 않는 문자 제거)을 사용하여 파일 크기를 최소화하세요.
  • 렌더링 전략:

구현:

<!-- 중요 하위 집합(예: Header + Body)만 Preload -->
<link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin>

<style>
  @font-face {
    font-family: 'Inter Variable';
    src: url('/fonts/inter-var.woff2') format('woff2-variations');
    /* 안정성 요구 사항에 따라 선택: */
    font-display: optional; /* 레이아웃 이동은 없지만 폰트가 폴백 상태로 유지될 수 있음 */
    /* font-display: swap;     가장 빠른 텍스트 가시성이 확보되지만 레이아웃 이동 위험이 있음 */
  }
</style>

7. 연결 속도 향상

브라우저가 타사 출처에서 리소스를 다운로드하려면 먼저 DNS 조회를 수행하고, TCP 연결을 설정하고, TLS 암호화를 협상해야 합니다. 이 작업에는 시간이 걸립니다. 브라우저에 연결을 일찍 설정하도록 지시하여 이 지연을 제거할 수 있습니다.

구현:

  • preconnect: 브라우저에 필요할 것으로 예상되는 중요한 타사 출처에 사용합니다. 전체 핸드셰이크(DNS + TCP + TLS)를 미리 수행합니다.
  • dns-prefetch: 덜 중요한 출처에 사용합니다. DNS 확인만 수행하므로 가볍지만 여전히 20~120ms를 절약할 수 있습니다.
<!-- 중요한 타사: 완벽한 초기 연결 -->
<link rel="preconnect" href="https://cdn.example.com">

<!-- 구형 브라우저를 위한 폴백(Fallback) -->
<link rel="dns-prefetch" href="https://cdn.example.com">

preconnect를 2~4개의 출처로 제한하세요. 각 연결은 CPU와 대역폭을 소비합니다. 너무 많은 preconnect는 실제 리소스 다운로드와 경쟁하여 성능에 도움이 되기는커녕 저해할 수 있습니다. 2025 Web Almanac에 따르면 페이지의 22%가 preconnect를 사용하고 24%가 dns-prefetch를 사용합니다. 차단 리소스보다 먼저, 둘 다 <head>의 가능한 한 앞부분에 배치하세요.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

진짜 뭐가 느린지부터.

실제 필드 데이터로 Critical Rendering Path를 뜯어봅니다. Lighthouse 리포트가 아니라 우선순위가 매겨진 수정 목록을 드립니다.

감사 받기
Core Web Vitals 리소스 우선순위 지정 가이드Core Web Vitals Core Web Vitals 리소스 우선순위 지정 가이드