Head 대 Footer의 JavaScript: Core Web Vitals에 미치는 영향

head에 defer를 사용하는 것이 최신 모범 사례인 이유와 footer 배치가 여전히 의미 있는 경우

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

간단한 답변: head에 defer 사용

최종 검토: Arjen Karel, 2026년 3월

과거에는 JavaScript를 footer에 배치하라는 조언이 일반적이었습니다. 하지만 그 조언은 이제 구식입니다. 모든 브라우저에서 asyncdefer를 지원함에 따라, 대부분의 스크립트를 배치하기에 가장 좋은 위치는 defer 속성과 함께 <head>에 두는 것입니다.

그 이유는 프리로드 스캐너(preload scanner) 때문입니다. 브라우저는 head 스크립트를 즉시 발견하고 HTML 파싱과 병렬로 다운로드를 시작합니다. Footer 스크립트는 나중에 발견되므로 다운로드 시작도 늦어집니다. 렌더링을 차단하지 않는 비동기적인 동작은 같지만, 리소스 발견 속도가 더 빠릅니다.

2025년 Web Almanac에 따르면, 여전히 전체 페이지의 85%가 렌더링 차단 리소스(render-blocking resources) 감사를 통과하지 못합니다. 이는 엄청난 수치입니다. 한편, 모바일 총 차단 시간(Total Blocking Time)은 전년 대비 58% 증가하여 중앙값이 1,916ms에 달했습니다. JavaScript는 가벼워지기는 커녕 더 무거워지고 있습니다. 스크립트 배치를 올바르게 하는 것은 First Contentful PaintLargest Contentful Paint를 개선하기 위해 할 수 있는 가장 쉬운 방법 중 하나입니다.

프리로드 스캐너의 작동 방식

프리로드 스캐너는 메인 파서보다 앞서 실행되는 두 번째 HTML 파서입니다. 원시 HTML을 빠르게 스캔하여 메인 파서가 도달하기 전에 중요한 리소스(이미지, CSS, JavaScript)를 가져오기 시작합니다. 프리로드 스캐너는 리소스를 발견한 순서대로 대략적으로 가져옵니다.

이 지점에서 스크립트 배치가 중요해집니다. <head>에 있는 스크립트는 거의 즉시 발견됩니다. <body> 맨 아래에 있는 스크립트는 나중에 발견되며, 특히 용량이 큰 HTML 문서에서는 더 늦어집니다. 이러한 지연은 모바일 연결에서 수백 밀리초의 비용을 초래할 수 있습니다.

동적으로 주입된 스크립트(JavaScript를 통해 생성됨)는 프리로드 스캐너에 전혀 보이지 않습니다. 스캐너는 서버에서 반환된 HTML 마크업에 존재하는 리소스만 발견합니다. 이것이 코드로 스크립트를 주입하는 것보다 HTML 속성을 통해 JavaScript를 지연(defer)시키는 것이 거의 항상 더 나은 이유입니다.

head에 있는 JavaScript

페이지의 <head>에 JavaScript를 배치하면 프리로드 스캐너가 가장 빠르게 스크립트를 발견할 수 있습니다.

장점

  1. 빠른 발견: 프리로드 스캐너는 본문 콘텐츠를 파싱하기 전에 head 스크립트를 찾습니다. 다운로드가 가능한 한 일찍 시작됩니다.
  2. 더 빠른 실행: head에 있는 스크립트(defer 사용)는 문서의 뒷부분에서 발견된 스크립트보다 먼저 실행됩니다. 자세한 비교는 defer 대 async JavaScript 및 Core Web Vitals를 참조하세요.
  3. 코드 분리: 스크립트 참조를 <head>에 유지하면 콘텐츠 마크업과 분리되어 HTML을 유지 관리하기가 더 쉽습니다.

단점

  1. 렌더링 차단(defer 또는 async 미사용 시): head에 있는 일반 <script>는 스크립트가 다운로드되고 실행될 때까지 HTML 파싱을 차단합니다. 이것은 First Contentful Paint를 심각하게 망칩니다. 이를 방지하려면 head에 있는 외부 스크립트에 항상 defer 또는 async를 사용하세요.
  2. 대역폭 경쟁: 우선순위가 높은 head 스크립트는 CSS, 글꼴 및 LCP 이미지와 대역폭을 두고 경쟁합니다. 느린 연결에서는 이로 인해 Largest Contentful Paint가 2.5초 임계값을 초과할 수 있습니다.

head 배치를 사용해야 할 때

페이지 경험에 중요한 스크립트(메뉴, 쿠키 알림, 슬라이더 또는 방문자가 스크롤하기 전 보이는 화면인 '스크롤 위(above the fold)'에 영향을 주는 모든 스크립트)에는 <head>를 사용하세요. 렌더링 차단을 방지하기 위해 defer(또는 실행 순서가 중요하지 않은 경우 async)를 추가하세요. 기능 감지(feature detection) 라이브러리 역시 body가 파싱되기 전에 실행되어야 하므로 head에 속합니다.

footer에 있는 JavaScript

닫는 </body> 태그 바로 앞에 JavaScript를 배치하는 것은 수년간 표준적인 성능 최적화 조언이었습니다. 아이디어는 HTML이 먼저 렌더링되게 하고, 스크립트를 나중에 다운로드하는 것입니다.

장점

  1. 기본적으로 차단되지 않음: 위에 있는 HTML이 이미 파싱되었기 때문에 footer 스크립트는 초기 렌더링을 차단하지 않습니다.
  2. 낮은 대역폭 경쟁: 브라우저가 footer 스크립트에 도달할 때쯤이면 CSS, 글꼴 및 LCP 이미지가 이미 다운로드를 시작한 후입니다.

단점

  1. 늦은 발견: 프리로드 스캐너는 head 스크립트보다 footer 스크립트를 더 나중에 찾습니다. 크기가 큰 페이지에서는 다운로드 시작과 실행이 더 늦어진다는 것을 의미합니다.
  2. 구식 패턴: <head><script defer>는 렌더링을 차단하지 않으면서도 더 빠르게 발견할 수 있습니다. footer 배치는 defer가 범용적인 브라우저 지원을 갖기 전의 차선책이었습니다. 그 시대는 끝났습니다.

footer 배치가 여전히 의미 있는 경우

초기 페이지 로드 중 대역폭을 두고 경쟁하지 않기를 진심으로 원하는 스크립트(분석, A/B 테스트 도구 또는 소셜 위젯)의 경우 footer 배치가 의미 있을 수 있습니다. 하지만 이들조차도 프리로드 스캐너의 빠른 발견 덕분에 head의 defer가 보통 더 나은 선택입니다.

최신 스크립트 속성

asyncdefer 외에도 알아두어야 할 두 가지 속성이 더 있습니다.

type="module": 모듈 스크립트는 기본적으로 지연(defer)됩니다. 모듈 스크립트에는 이미 그 방식대로 작동하므로 defer를 추가할 필요가 없습니다. 모듈 스크립트에 async를 추가하면 기본 지연 동작이 재정의되고 다운로드가 완료되는 즉시 실행됩니다.

fetchpriority: 기본적으로 asyncdefer 스크립트는 낮음(Low) 네트워크 우선순위를 갖습니다. async 스크립트에 fetchpriority="high"를 추가하면 렌더링 차단 없이 높음(High) 우선순위로 다운로드할 수 있습니다. 이는 사용자 경험(UX)에 필수적이지만 렌더링을 차단해서는 안 되는 스크립트에 이상적인 조합입니다. 전체적인 내용은 리소스 우선순위 지정 가이드JavaScript 우선순위 수준을 참조하세요.

실용적인 스크립트 배치 전략

모든 스크립트가 동일한 대우를 받아야 하는 것은 아닙니다. 저는 4단계 접근 방식을 사용합니다.

  1. 렌더링에 중요한 스크립트: 페이지의 눈에 보이는 레이아웃(메뉴, 슬라이더, 스크롤 위 UI)에 영향을 미치는 스크립트입니다. 첫 번째 페인트 전에 실행해야 하는 경우 defer 없이 <head>에 배치하세요. 이들은 렌더링을 차단하고 Core Web Vitals에 손상을 줄 수 있으므로 가능한 한 작게 유지하세요.
  2. 중요한 스크립트: 전환 또는 상호 작용(양식, 내비게이션, 쿠키 동의)에 필수적인 스크립트입니다. defer 또는 async와 함께 <head>에 배치하세요.
  3. 일반 스크립트: 첫 번째 페이지 렌더링에 영향을 미치지 않는 스크립트(캐러셀, 모달, 탭)입니다. defer와 함께 <head>에 배치하세요.
  4. 있으면 좋은 스크립트: 정말 필요하다면 없어도 되는 스크립트(분석, 채팅 위젯, 소셜 공유)입니다. load 이벤트 또는 requestIdleCallback을 사용하여 페이지 렌더링이 완료된 후 이들을 로드하세요. 기술에 대해서는 JavaScript를 지연하는 16가지 방법을 참조하세요. 이 범주에 사용되지 않는 JavaScript가 많은 경우 사용되지 않는 JavaScript를 줄이는 방법을 참조하세요.

DOMContentLoadedload 이벤트를 사용하면 HTML에서 스크립트가 배치된 위치에 관계없이 실행 타이밍을 제어할 수 있습니다. 이는 다른 모든 것이 준비될 때까지 기다려야 하는 비필수적인 초기화를 보장하는 데 유용합니다.

코드 예시

예시 1: head에 있는 JavaScript (렌더링 차단)

<!DOCTYPE html>
<html>
<head>
    <title>JavaScript in the Head Example</title>
    <script>
        function showMessage() {
            alert("Hello from JavaScript in the head!");
        }
    </script>
    <!-- This script blocks rendering -->
    <script src="script.js"></script>
</head>
<body>
    <button onclick="showMessage()">Click Me</button>
</body>
</html>

이 예시에서 <head>script.js는 렌더링을 차단합니다. 브라우저는 스크립트가 다운로드되고 실행될 때까지 버튼을 표시하지 않습니다. 이를 수정하려면 스크립트 태그에 defer를 추가하세요.

예시 2: footer에 있는 JavaScript

<!DOCTYPE html>
<html>
<head>
    <title>JavaScript in the Footer Example</title>
</head>
<body>
    <button onclick="showMessage()">Click Me</button>
    <!-- Script at the end of the body -->
    <script src="script.js"></script>
    <script>
        function showMessage() {
            alert("Hello from JavaScript in the footer!");
        }
    </script>
</body>
</html>

여기서 script.js는 HTML 콘텐츠 이후에 로드되므로 렌더링을 차단하지 않습니다. 하지만 프리로드 스캐너는 head에 있을 때보다 나중에 이를 발견합니다. <head><script defer src="script.js"></script>를 사용하면 더 빠른 다운로드 발견과 함께 동일한 비차단 동작을 얻을 수 있습니다.

예시 3: 이벤트 리스너 사용

<!DOCTYPE html>
<html>
<head>
    <title>Event Listener Example</title>
    <script>
        window.addEventListener('load', function() {
            console.log("Page is fully loaded.");
        });
    </script>
</head>
<body>
    <!-- Page content -->
</body>
</html>

load 이벤트 리스너는 스크립트가 배치된 위치에 관계없이 콜백 내부의 코드가 페이지가 완전히 로드된 후에만 실행되도록 보장합니다. 이는 다른 모든 것이 준비될 때까지 기다려야 하는 비중요(non-critical) 초기화에 유용합니다.

변경 사항 확인

스크립트를 footer에서 <head>defer로 이동한 후, Real User Monitoring으로 그 영향을 확인하세요. FCPLCP가 모두 개선되어야 합니다. CoreDash가 모니터링하는 사이트 전반에서 대부분의 스크립트에 defer를 사용하는 출처(origins)는 여전히 footer 배치에 의존하는 출처보다 중앙값 FCP가 18% 더 빠릅니다.

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.

실시간 데이터. 28일 평균 말고.

CoreDash는 라우트, 디바이스, 브라우저, 회선별로 모든 지표를 쪼개서 보여줍니다.

CoreDash 둘러보기
Head 대 Footer의 JavaScript: Core Web Vitals에 미치는 영향Core Web Vitals Head 대 Footer의 JavaScript: Core Web Vitals에 미치는 영향