티스토리 뷰

DEV/SCRIPT

HTML, CSS, JS 로딩 순서

SBP 2025. 6. 9. 16:07
HTML, CSS, JS 로딩 순서

웹 브라우저의 자원 로딩 순서 (HTML, CSS, JavaScript)

웹 브라우저가 사용자에게 웹 페이지를 보여주기까지 HTML, CSS, JavaScript와 같은 자원(Resource)들을 정해진 순서와 규칙에 따라 불러오고 처리합니다. 이 과정을 이해하는 것은 웹 페이지의 성능 최적화에 매우 중요합니다.

기본 로딩 및 렌더링 순서 📜

브라우저는 HTML 문서를 위에서 아래로 한 줄씩 순차적으로 읽고(파싱, Parsing) 처리합니다. 이 과정에서 각 태그가 무엇을 의미하는지 해석하며 DOM(Document Object Model) 트리를 만들어나갑니다.

  1. HTML 파싱: 브라우저가 서버로부터 HTML 파일을 받아 한 줄씩 읽으며 DOM 트리를 구성합니다.
  2. CSS 로드 및 파싱: <head><link> 태그를 만나면, HTML 파싱을 멈추지 않고 CSS 파일 다운로드를 요청합니다. 다운로드가 완료되면 CSS를 파싱하여 CSSOM(CSS Object Model) 트리를 만듭니다.
  3. JavaScript 로드 및 실행: <script> 태그를 만나면, HTML 파싱을 즉시 중단하고 JavaScript 파일을 다운로드하여 실행합니다. 스크립트 실행이 완료될 때까지 뒤따르는 HTML의 파싱은 멈춥니다. (이를 '파서 블로킹'이라 합니다)
  4. 렌더 트리(Render Tree) 생성: DOM 트리와 CSSOM 트리가 완성되면, 화면에 실제로 표시될 요소들로만 구성된 렌더 트리를 생성합니다. (display: none; 같은 요소는 제외됩니다)
  5. 레이아웃(Layout/Reflow): 렌더 트리를 기반으로 각 요소가 화면의 어느 위치에 어떤 크기로 배치될지 정확히 계산합니다.
  6. 페인트(Paint): 레이아웃 계산이 끝난 요소들을 화면에 실제로 그립니다.

CSS와 JavaScript의 위치가 중요한 이유 💡

CSS를 <head>에 두는 이유

CSS는 렌더링 차단(Render-Blocking) 리소스입니다. 브라우저는 CSSOM 트리가 완성되지 않으면 렌더링을 시작하지 않습니다. 만약 CSS를 <body> 태그 중간이나 끝에 두면 다음과 같은 문제가 발생할 수 있습니다.

  • 스타일 없는 콘텐츠 노출 (FOUC): 스타일이 적용되지 않은 HTML이 먼저 보인 후, CSS가 적용되면서 화면이 번쩍거리는 현상이 발생합니다.
  • 불필요한 재렌더링: 이미 그려진 페이지에 새로운 CSS 규칙이 적용되면서 레이아웃을 재계산(리플로우)하고 다시 그리는(리페인트) 과정이 발생하여 성능이 저하됩니다.

JavaScript를 <body> 끝에 두거나 속성을 사용하는 이유

일반적인 <script> 태그는 HTML 파싱을 차단하여, 사용자가 첫 화면을 보기까지의 시간을 지연시킵니다. 이를 해결하기 위한 방법은 다음과 같습니다.

1. <script><body> 태그가 닫히기 직전에 배치

  • 장점: HTML 파싱이 모두 끝난 후에 스크립트를 로드하므로, 파싱 차단 문제가 발생하지 않아 사용자가 페이지 콘텐츠를 더 빨리 볼 수 있습니다.
  • 단점: 페이지가 전부 표시된 후에야 스크립트 다운로드가 시작되므로, 스크립트에 의존하는 기능(이미지 슬라이더 등)의 시작이 늦어질 수 있습니다.

2. <script async> 속성 사용

  • HTML 파싱과 동시에 비동기적으로 스크립트를 다운로드합니다.
  • 다운로드가 완료되면 HTML 파싱을 즉시 중단하고 스크립트를 실행합니다.
  • 실행 순서가 보장되지 않아 다른 스크립트와 의존성이 없는 독립적인 스크립트(광고, 분석 스크립트 등)에 적합합니다.

3. <script defer> 속성 사용 (⭐ 권장)

  • HTML 파싱과 동시에 비동기적으로 스크립트를 다운로드합니다.
  • 다운로드가 완료되어도 즉시 실행하지 않고, HTML 파싱이 모두 끝난 후에 스크립트를 실행합니다.
  • 여러 defer 스크립트는 HTML에 명시된 순서대로 실행이 보장됩니다.
  • DOM을 조작하는 등 페이지 콘텐츠 전체가 필요한 스크립트에 가장 이상적입니다.

시각적 요약 📊

태그 위치 / 속성 HTML 파싱 중단
(스크립트 다운로드 시)
HTML 파싱 중단
(스크립트 실행 시)
스크립트 실행 시점 실행 순서 보장
<head><script> 다운로드 직후
<body><script> 아니요 HTML 파싱 완료 후
<script async> 아니요 다운로드 직후 아니요
<script defer> 아니요 아니요 HTML 파싱 완료 후

결론: 최적의 배치 전략 ✨

CSS는 <head> 안에, JavaScript는 <body>가 닫히기 직전에 defer 속성과 함께 배치하는 것이 현대 웹 개발의 가장 일반적이고 효율적인 방법입니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>최적의 로딩 순서</title>
&lt;!-- 1. CSS: 렌더링 차단을 최소화하기 위해 head에 배치 --&gt;
&lt;link rel="stylesheet" href="style.css"&gt;

</head>
<body>
&lt;!-- 2. HTML: 위에서 아래로 순차적으로 파싱되며 DOM 생성 --&gt;
&lt;header&gt;
    &lt;h1&gt;웹페이지 제목&lt;/h1&gt;
&lt;/header&gt;
&lt;main&gt;
    &lt;p&gt;페이지의 주요 콘텐츠입니다.&lt;/p&gt;
&lt;/main&gt;

&lt;!-- 3. JavaScript: defer를 사용하여 HTML 파싱을 막지 않고,
     DOM 생성이 완료된 후 순서대로 스크립트를 실행. --&gt;
&lt;script src="library.js" defer&gt;&lt;/script&gt;
&lt;script src="main.js" defer&gt;&lt;/script&gt;

</body>
</html>

'DEV > SCRIPT' 카테고리의 다른 글

JS : 호이스팅(Hoisting)  (0) 2025.06.09
[JS] COPY  (0) 2024.02.22
[JS] 화면 PRINT  (2) 2023.12.08
[JS] 배열 - 두 배열 합치기, 배열 평탄화, 배열 분할  (3) 2023.12.08
[JS] 소수점  (0) 2023.12.08
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/07   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함