Skip to content

DevTools Performance로 렌더링 병목 추적하기

앞서 DOM, CSSOM, Render Tree가 어떻게 결합되어 화면을 그리는지 살펴봤다. 이제는 실제 브라우저가 렌더링하는 과정을 직접 관찰하고 병목을 찾는 방법을 알아보자 👀 !

💡 Performance 탭은 이론으로 배운 HTML 파싱 → Style 계산 → Layout → Paint → Composite 과정이 실시간으로 어떻게 일어나는지 보여주는 도구다.

1. Performance 탭이란?

Performance 탭은 브라우저가 실제로 Recalculate Style → Layout → Paint → Composite을 어떻게 처리했는지를 타임라인 기반으로 시각화해주는 도구이다.

다음과 같은 것을 확인할 수 있다:

  • 한 프레임(frame)이 언제, 어떤 이유로 느려졌는지
  • JavaScript, Layout, Paint, Composite 각 단계의 수행 시간
  • 애니메이션, 스크롤, 이벤트 핸들링 중 CPU/GPU 부하 정도

💡 즉, Render Tree가 실제로 픽셀로 변환되는 과정을 실시간으로 추적하는 곳이다


2. 기본 사용 방법

DevTools

  1. Performance 탭 선택, ⏺️ Record 버튼 클릭
  2. 페이지를 새로고침하거나, 애니메이션/스크롤 등 실제 상호작용 수행
  3. ⏹️ 버튼을 다시 눌러 기록 중단

Reload + record 옵션을 선택하면 페이지 초기 로딩부터 자동으로 기록 가능


3. 성능 분석 타임라인 구조

Performance 탭을 열면 상단부터 다음과 같은 영역이 나타난다.

주요 영역설명
FPS 그래프초당 프레임 (녹색이 높을수록 부드럽다)
Main ThreadJS 실행, Style 계산, Layout, Paint, Composite 흐름
Frames 섹션각 프레임이 얼마의 시간(16ms 이내)을 소비했는지 표시
Bottom-Up / Call Tree어떤 함수/작업이 가장 많은 시간을 썼는지 분석

4. 렌더링 파이프라인의 주요 이벤트

앞서 배운 렌더링 과정이 Performance 탭에서는 다음과 같은 이벤트로 나타난다.

이벤트 이름설명원인관련 개념
Recalculate StyleCSS 변경 감지 후 스타일 재계산class 추가, inline style 변경CSSOM
Layout요소의 위치·크기 다시 계산DOM 구조 변경, 크기 조정Render Tree
Paint픽셀 다시 그리기색상, 그림자, 테두리 변경Painting
Composite LayersGPU에서 레이어 합성transform/opacity 변경Composite
Evaluate ScriptJS 실행무거운 연산, 이벤트 핸들러 등DOM 조작

💡 Recalculate Style → Layout → Paint → Composite가 과도하게 반복된다면 불필요한 Reflow/Repaint 루프 가능성이 높다.


5. 병목 구간 읽기

Main Thread의 색상별 의미를 파악하면 병목 지점을 쉽게 찾을 수 있다.

색상이벤트의미
🟡 노란색JavaScript메인 스레드를 점유 중 (렌더링 차단 가능)
🟣 보라색Layout (Reflow)DOM 구조·크기 변경 빈번 → 성능 저하
🟢 초록색Paint (Repaint)배경색, 그림자, 테두리 재그리기 비용 과다
🔵 파란색CompositeGPU 합성만 발생 → 성능 양호 ✅
  • 색상은 DevTools 테마(라이트/다크)나 버전에 따라 다를 수 있다.

6. 예시: Layout Thrashing 탐지

js
// bad: 읽기와 쓰기가 반복되어 Layout이 100번 발생
for (let i = 0; i < 100; i++) {
  box.style.width = box.offsetWidth + 1 + "px"; // 읽기 → 강제 Layout → 쓰기...
}
  • Recalculate Style / Layout 이벤트가 100회 이상 반복 표시됨
  • FPS 그래프는 급격히 떨어짐 (빨간색 구간 발생)

js
// good: 읽기와 쓰기 분리
const width = box.offsetWidth; // 읽기 1회
for (let i = 0; i < 100; i++) {
  box.style.width = width + i + "px"; // 쓰기만 반복
}
  • Performance 탭에서 다시 측정하면 Layout이 1~2회로 줄어들고 FPS가 안정화된다.

7. FPS와 프레임 분석

Performance 탭의 상단 Frames 섹션을 보면 각 프레임의 색상으로 상태를 구분할 수 있다.

색상의미
🟢 녹색60fps 이상 — 부드럽게 렌더링 중
🟡 노랑/주황30~59fps — 약간의 지연
🔴 빨강30fps 이하 — 프레임 드랍 발생
  • 🕒 1초(1000ms)를 60프레임으로 나누면 약 16.67ms
  • 따라서 각 프레임이 16ms 안에 완료되어야 60fps가 유지된다.

8. 실전 분석 팁

분석 항목확인 위치개선 포인트
JS 실행 시간Main → Scripting비동기 처리 / Web Worker
Layout 빈도Main → RenderingDOM 변경 최소화
Paint 빈도Main → PaintingCSS 단순화 / transform 활용
Composite 빈도Compositor ThreadGPU-friendly 속성 사용
FPSFrames 그래프 상단60fps 근처 유지 목표

9. 실습: transform vs top 비교

Case 1: top 사용 (Reflow 발생)

js
element.style.top = "100px";
  • Performance 결과: Layout + Paint 발생 (메인 스레드 부하 ↑)
  • FPS 저하 가능성 높음

Case 2: transform 사용 (GPU 합성)

js
element.style.transform = "translateY(100px)";
  • Performance 결과: Composite만 발생 (GPU 처리, FPS 유지)
  • Layout/Paint 이벤트가 사라짐

💡 DevTools Summary 탭에서 두 코드를 비교하면 성능 차이가 명확히 보인다.


정리

핵심 포인트설명
Performance 탭렌더링 과정을 실시간으로 시각화
Recalculate Style / Layout / Paint병목의 3대 원인
CompositeGPU 합성 단계 — 성능에 유리
JS 점유 시간메인 스레드 블로킹의 주요 원인
FPS 모니터링60fps 근처 유지 여부 판단 기준



💡 요약

  • Performance 탭은 DOM → CSSOM → Render Tree → 픽셀 과정을 실시간으로 관찰하는 도구다.
  • Reflow·Repaint가 어디서 발생하는지 색상별로 시각적 확인 가능.
  • transform, opacity, will-change를 활용해 Composite 중심 구조로 설계하면 병목이 사라진다.
  • 최종 목표: Main Thread 부하 ↓, GPU 처리 ↑, 안정적 60fps 유지

💡 최종 목표

렌더링 병목을 눈으로 확인하고, Main Thread 부하를 줄여 GPU 합성 중심 구조로 전환하는 것.
🎯 이는 브라우저 내부 렌더링 시리즈의 핵심 결론이다.