🟨 2-23. 브라우저 렌더링 과정 — 자바스크립트, CSS, DOM이 함께 그려지는 진짜 순서
1. 브라우저 렌더링이란?
렌더링(Rendering)은
브라우저가 HTML, CSS, JavaScript, 이미지 등의 자원을 해석해
사용자에게 보이는 화면(Pixels) 을 만드는 과정이다.
즉, “텍스트 파일을 시각적 결과로 변환하는 과정”이 바로 렌더링이다.
2. 렌더링의 전체 흐름
브라우저가 HTML 파일을 받으면 다음 순서로 진행된다 👇
1️⃣ HTML 파싱 → DOM 트리 생성
2️⃣ CSS 파싱 → CSSOM 트리 생성
3️⃣ DOM + CSSOM → Render Tree 결합
4️⃣ Layout (배치) → 요소 크기와 위치 계산
5️⃣ Paint (그리기) → 픽셀 단위로 색상, 테두리, 그림자 적용
6️⃣ Composite (합성) → GPU가 화면에 출력
이 전체 과정을 Critical Rendering Path (CRP) 라고 한다.
3. 단계별로 살펴보기
1️⃣ HTML 파싱 → DOM 생성
HTML은 위에서 아래로 순서대로 읽히며,
태그마다 노드(node) 로 변환되어 DOM(Document Object Model) 트리를 만든다.
<html>
<body>
<h1>제목</h1>
<p>내용</p>
</body>
</html>
→ 변환 결과 (DOM Tree)
Document
└── html
└── body
├── h1
└── p
✅ JS에서 접근하는 document.querySelector() 의 대상이 바로 이 DOM이다.
2️⃣ CSS 파싱 → CSSOM 생성
브라우저는 CSS 파일을 동시에 읽어 CSSOM (CSS Object Model) 을 만든다.
body {
color: black;
}
h1 {
font-size: 24px;
}
→ CSSOM Tree
CSS Rules
├── body { color: black }
└── h1 { font-size: 24px }
✅ CSS는 렌더링 차단(Render Blocking) 리소스다.
✅ 즉, CSS를 모두 파싱하기 전까지 브라우저는 화면을 그리지 않는다.
3️⃣ Render Tree 생성
브라우저는 DOM과 CSSOM을 결합해 렌더 트리(Render Tree) 를 만든다.
렌더 트리는 화면에 실제로 표시될 요소만 포함한다.
예를 들어, display: none 요소는 포함되지 않는다.
Render Tree
├── h1 (font-size: 24px, color: black)
└── p (color: black)
4️⃣ Layout (배치)
렌더 트리의 각 노드가
화면 어디에, 어떤 크기로 위치해야 하는지를 계산한다.
이를 Reflow (리플로우) 또는 Layout 단계라고 부른다.
<div style="width: 100px; height: 50px; margin: 10px;"></div>
→ 이 정보를 기반으로 브라우저가 픽셀 좌표를 계산한다.
✅ 리플로우는 DOM의 구조나 크기가 변할 때마다 다시 일어난다.
5️⃣ Paint (그리기)
Layout이 끝나면, 브라우저는
요소의 색상, 배경, 테두리, 그림자 등 시각적 속성을 칠한다.
이 과정을 Repaint (리페인트) 라고 한다.
✅ CSS 색상, 배경 변경 → Repaint만 일어남
✅ 크기나 위치 변경 → Reflow + Repaint 모두 발생
6️⃣ Composite (합성)
이제 Paint된 레이어들을 GPU가 합성(Composite)하여
화면에 실제 픽셀로 렌더링한다.
💡 예를 들어,
브라우저는 position: fixed나 transform, opacity 속성이 있는 요소를
“독립적인 레이어(Layer)”로 분리해 GPU에서 효율적으로 합성한다.
4. 자바스크립트가 렌더링을 막는 이유
자바스크립트는 HTML 파싱 도중 만나면
브라우저가 파싱을 일시 중단하고 JS를 먼저 실행한다.
<script src="app.js"></script>
✅ JS는 DOM을 조작할 수 있기 때문에
파싱 도중 실행되지 않으면 결과가 달라질 수 있다.
➡ 따라서 JS는 렌더링 차단(Render Blocking) 요인이 된다.
5. async / defer 속성으로 최적화
이 문제를 해결하기 위해
스크립트 로딩을 제어하는 속성 2가지를 사용할 수 있다.
속성 실행 시점 특징
| async | 다운로드 완료 즉시 실행 | 병렬로 로드, 순서 보장 X |
| defer | DOM 파싱 완료 후 실행 | 순서 보장 O, 렌더링 차단 X |
<script src="app.js" defer></script>
✅ defer는 HTML 파싱을 멈추지 않으므로
렌더링 속도를 높이는 가장 안전한 방법이다.
6. Reflow & Repaint 최적화
렌더링 성능 문제의 대부분은
Reflow (Layout) 와 Repaint (Painting) 에서 발생한다.
구분 발생 원인 비용
| Reflow | DOM 구조 변경, 크기/위치 조정 | 높음 |
| Repaint | 색상/배경 변경 | 낮음 |
✅ Reflow 최소화 팁
- DOM 변경 시, 한 번에 묶어서 처리하기❌ 이렇게 하면 매번 Reflow 발생
✅ 해결 → el.style.cssText = "width:200px;height:100px;margin:10px"; - const el = document.getElementById("box"); el.style.width = "200px"; el.style.height = "100px"; el.style.margin = "10px";
- display: none으로 숨긴 뒤 조작 후 다시 표시하기
- DOM 조작 대신 classList.toggle()로 스타일 변경
7. Layout Thrashing 방지
JS에서 DOM의 offsetWidth, getBoundingClientRect() 같은 속성을 자주 읽으면
Layout Thrashing(레이아웃 쓰래싱) 현상이 발생한다.
for (let i = 0; i < 1000; i++) {
box.style.width = box.offsetWidth + 1 + "px";
}
✅ 읽기(리플로우)와 쓰기(스타일 변경)가 반복되면서 성능 급락
➡ 해결: 읽기 → 쓰기 순서로 묶기
8. 브라우저의 프레임 렌더링 주기
브라우저는 초당 60fps(약 16.6ms 주기)로 렌더링 루프를 돌린다.
Frame(16ms)
├─ Input → Script → Style → Layout → Paint → Composite
💡 JS가 16ms 안에 실행되지 않으면
프레임 드롭(Frame Drop)이 발생 → “버벅임” 느낌
➡ 따라서 긴 연산은 Web Worker나 requestIdleCallback 으로 분리하는 게 좋다.
9. 실제 렌더링 최적화 예시
requestAnimationFrame(() => {
element.style.transform = "translateX(100px)";
});
✅ transform은 GPU 가속을 활용하므로
Layout(Reflow) 없이 Paint/Composite만 발생
➡ CSS Transition, Animation은 대부분 이 구조를 이용한다.
10. 렌더링 파이프라인 요약
단계 주요 결과물 비고
| HTML 파싱 | DOM Tree | 텍스트 → 객체 |
| CSS 파싱 | CSSOM Tree | 스타일 구조 |
| Render Tree | DOM + CSSOM 결합 | 실제 렌더링 대상 |
| Layout | 위치/크기 계산 | Reflow 발생 |
| Paint | 시각적 속성 칠하기 | Repaint 발생 |
| Composite | GPU 합성 | 최종 픽셀 출력 |
11. 정리
개념 핵심 내용
| DOM | HTML 구조 트리 |
| CSSOM | 스타일 구조 트리 |
| Render Tree | 실제 렌더링 대상 결합 구조 |
| Reflow | 레이아웃 계산 단계 |
| Repaint | 시각적 속성만 다시 그림 |
| Composite | GPU 합성 후 화면 표시 |
| Render Blocking | JS/CSS가 렌더링 중단시키는 현상 |
| 최적화 | Reflow 최소화 + GPU 활용 |
12. 마무리
이제 브라우저가 “코드를 눈에 보이게 만드는 과정”이 명확히 보일 거야.
이 구조를 이해하면 “성능을 높인다”는 게 단순한 추상적 개념이 아니라
실제 렌더링 파이프라인을 제어하는 행위라는 걸 깨닫게 된다.
“렌더링 최적화란, 브라우저의 일꾼(엔진)들에게 불필요한 일을 덜 시키는 것이다.”