SJSBiz SJSBiz

브라우저 렌더링 병목 진단|Layout·Paint 30분 추적

읽는 시간 약 8분

페이지가 버벅인다고 무조건 JavaScript 파일을 줄이거나 GPU 가속을 켜면 원인을 놓치기 쉽습니다. 같은 끊김도 긴 스크립트, 강제 동기 레이아웃, 넓은 다시 그리기, 과도한 레이어처럼 발생 지점이 다릅니다. 이 글은 Chrome DevTools 기록에서 병목 이벤트와 원인 코드를 연결하는 30분 진단 순서입니다.

10초 요약

  • Performance 기록 전 재현할 동작을 하나로 고정합니다.
  • Main 트랙에서 긴 작업과 보라색 Rendering 이벤트를 먼저 찾습니다.
  • Layout은 위치·크기 계산, Paint는 픽셀 그리기, Composite는 레이어 합성 단계입니다.
  • 문제 이벤트의 Initiator와 호출 스택에서 원인 파일·함수를 확인합니다.
  • 한 번에 한 원인만 수정하고 같은 조건으로 전후 기록을 비교합니다.

렌더링 흐름과 병목 신호

브라우저는 HTML로 DOM을, CSS로 CSSOM을 만든 뒤 화면에 필요한 구조를 계산합니다. 이후 Style, Layout, Paint, Composite 작업을 거쳐 픽셀을 표시합니다. 모든 변경이 전체 단계를 실행하는 것은 아니므로 실제 기록에서 시작 지점을 확인해야 합니다.

기록에서 보이는 신호가능한 원인먼저 확인할 것
긴 노란색 Scripting이벤트 핸들러·반복 연산·외부 스크립트Long task의 호출 스택과 Self time
반복되는 Recalculate Style대량 DOM 변경·복잡한 스타일 무효화Initiator와 영향을 받은 노드 수
Layout에 빨간 경고쓰기 직후 위치·크기 읽기Forced reflow 원인 코드
넓은 Paint큰 영역의 그림자·배경·고정 요소Paint flashing과 Paint profiler
프레임 누락한 프레임 안에 과도한 JS·렌더링 작업Frames·CPU 차트와 긴 이벤트
Layout Shift이미지 크기 누락·늦은 글꼴·삽입 요소Layout shifts 트랙과 이동 노드
사용자 동작에서 Main Thread의 Scripting Style Layout Paint Composite로 이어지는 병목 추적

1단계: 재현 동작과 측정 조건 고정

스크롤, 메뉴 열기, 검색 입력처럼 문제가 드러나는 동작 하나를 정하세요. 확장 프로그램 영향을 줄이려면 시크릿 창을 사용하고, DevTools Performance에서 네트워크와 CPU 조건을 기록합니다. 첫 측정과 수정 후 측정은 같은 뷰포트·페이지·동작으로 반복합니다.

  1. 새로고침 뒤 3초 동안 기다립니다.
  2. Record를 누르고 문제 동작을 한 번 실행합니다.
  3. 동작이 끝나면 바로 Stop을 누릅니다.
  4. 문제가 발생한 1~2초 구간만 확대합니다.
  5. 기록 이름에 날짜·동작·조건을 남깁니다.

실사용자의 LCP·INP·CLS와 개발자 도구의 단일 기록은 역할이 다릅니다. 현장 지표의 문제 페이지를 고른 뒤 로컬 기록으로 원인을 재현하려면 Core Web Vitals 30분 진단 순서를 함께 참고하세요.

2단계: Main 트랙에서 가장 긴 작업 선택

전체 타임라인을 한꺼번에 읽지 말고 문제가 보인 구간의 Main 트랙부터 봅니다. 긴 작업은 빨간 표시와 함께 나타날 수 있습니다. 이벤트를 선택해 Summary의 Self time, Total time, 호출 스택과 Initiator를 확인하세요. 외부 도메인 코드라면 해당 스크립트가 꼭 필요한지 먼저 판단합니다.

JavaScript 다운로드 용량과 실행 시간은 별개입니다. Coverage와 코드 분할까지 확인해야 한다면 JS 번들 실행 비용 진단으로 이어서 점검하세요. 광고·분석·채팅 위젯이 원인이면 외부 스크립트 지연 로딩 검증에서 기능별 제외 조건을 정할 수 있습니다.

3단계: 강제 레이아웃과 스타일 무효화 구분

스타일을 바꾼 직후 offsetWidth, offsetHeight, getBoundingClientRect()처럼 기하 정보를 읽으면 브라우저가 최신 값을 계산하기 위해 레이아웃을 즉시 실행할 수 있습니다. 반복문 안에서 쓰기와 읽기가 교차하면 비용이 커집니다.

// 읽기를 먼저 모으고 쓰기를 나중에 처리
const heights = cards.map(card => card.offsetHeight);
cards.forEach((card, i) => {
  card.style.height = `${heights[i] + 20}px`;
});
DOM 읽기와 쓰기 교차로 반복되는 강제 레이아웃과 일괄 처리 비교

코드를 바꾸기 전 Layout 이벤트를 선택해 경고와 원인 링크가 실제 해당 함수로 이어지는지 확인합니다. 단순히 requestAnimationFrame으로 감싸는 것만으로 읽기·쓰기 순서가 자동 개선되지는 않습니다.

4단계: Paint와 레이어 문제를 화면에 표시

명령 메뉴에서 Rendering 패널을 열고 Paint flashing을 켜면 다시 그려지는 영역이 녹색으로 표시됩니다. 기대하지 않은 전체 화면이 반복해 깜빡이면 고정 배경, 큰 그림자, 필터와 겹치는 요소를 줄여 범위를 비교합니다. Layout Shift Regions는 실제로 이동한 영역을 찾는 데 사용합니다.

transform과 opacity는 합성 단계만으로 처리될 가능성이 높지만 항상 별도 레이어가 이득인 것은 아닙니다. will-change를 많은 요소에 상시 적용하면 메모리와 합성 비용이 늘 수 있으므로 애니메이션 대상에 제한하고 기록으로 확인하세요. 글꼴 교체로 이동이 보이면 웹폰트 CLS 점검을 함께 진행합니다.

30분 수정과 원복 순서

시간작업남길 기록
0~5분재현 동작과 CPU·네트워크 조건 고정기준 Performance 기록
5~12분가장 긴 Main 이벤트와 원인 함수 선택이벤트 종류·시간·파일명
12~20분읽기·쓰기 분리 또는 큰 Paint 범위 축소변경 파일과 원복 위치
20~25분같은 조건으로 다시 기록Self time·Layout·Paint 전후값
25~30분기능·모바일·CLS 확인유지 또는 원복 결정

TIP

초록색 점수가 아니라 재현 동작 하나의 기록을 남기세요. “메뉴 열기 1회, CPU 4배 느림, Layout 42ms”처럼 조건과 이벤트 시간을 적어야 다음 수정이 실제 개선인지 판단할 수 있습니다.

자주 묻는 질문

Layout 이벤트가 있으면 모두 문제인가요?

아닙니다. 화면 변화에는 레이아웃이 필요할 수 있습니다. 한 프레임에 반복되거나 넓은 범위를 계산하고 사용자 동작 지연과 겹칠 때 Initiator를 추적하세요.

모바일에서만 느리면 어떻게 측정하나요?

먼저 현장 데이터에서 문제가 큰 기기·페이지를 찾고 DevTools CPU·네트워크 제한으로 재현합니다. 제한은 실제 기기와 같지 않으므로 가능하면 중저가 안드로이드 기기의 원격 디버깅 결과도 비교하세요.

공식 자료

마무리

렌더링 최적화는 속성 암기가 아니라 기록에서 원인 이벤트를 찾는 작업입니다. 재현 동작을 고정하고 가장 긴 Main 이벤트의 Initiator를 확인한 뒤, 한 원인만 수정해 같은 조건으로 비교하세요. Layout·Paint 시간과 기능이 함께 좋아졌을 때 변경을 유지합니다.

깨비
SJSBiz 운영자 깨비입니다. Windows, 워드프레스, 웹 서버와 데이터베이스에서 발생하는 문제를 공식 문서와 재현 가능한 점검 절차를 바탕으로 정리합니다. 직접 확인하지 않은 내용을 사용 후기처럼 표현하지 않으며, 테스트 환경과 버전·확인 날짜·주의사항을 가능한 범위에서 공개하고 오류 제보가 확인되면 내용을 수정합니다.

함께 보면 좋은 글

댓글 0

첫 댓글을 남겨보세요.