본문 바로가기
웹개발

[CSS Rendering Path][4편](마지막) 웹이 느려질 때 DevTools로 성능 문제 찾는 방법

by 냉정한망치 2026. 3. 18.
반응형

CSS Rendering Path 썸네일 일러스트


1편부터 3편까지 우리는 브라우저가 화면을 만드는 과정을 살펴봤다.

HTML을 읽는다.
CSS를 읽는다.
DOM과 CSSOM을 만든다.
Render Tree를 생성한다.
Layout을 계산한다.
Paint를 수행한다.
Composite 단계에서 레이어를 합친다.

그리고 중요한 사실 하나를 확인했다.

브라우저 렌더링 과정에서
Layout 계산은 가장 비용이 큰 작업 중 하나다.

그래서 많은 프론트엔드 성능 문제는
결국 레이아웃 계산이 너무 많이 발생하는 것에서 시작된다.

하지만 실제 서비스에서는 이런 질문이 생긴다.

어디서 문제가 발생하는지 어떻게 찾을 수 있을까?
그리고 실제 코드에서는 어떤 방식으로 해결할 수 있을까?

이번 글에서는 실제 웹 서비스에서 성능 문제를 분석하는 방법을 살펴본다.


실제 서비스에서 자주 발생하는 성능 문제

웹 서비스에는 다음과 같은 UI가 자주 등장한다.

뉴스 피드
채팅 목록
상품 리스트
댓글 목록
알림 목록

 

이 UI들의 공통점이 있다.

DOM 요소가 많다
스크롤이 계속 발생한다
데이터가 실시간으로 업데이트된다

이 조건이 겹치면 렌더링 비용이 빠르게 증가한다.

특히 DOM 요소가 많아질수록
Layout 계산 비용도 함께 증가한다.

예시 상황 – 채팅 메시지 목록

채팅 애플리케이션을 생각해보자.

새 메시지가 도착하면
DOM에 새로운 요소가 추가된다.

예를 들어 다음과 같은 코드다.

const message = document.createElement("div")
message.textContent = text
chatList.appendChild(message)
 

코드는 간단해 보인다.

하지만 브라우저 내부에서는 다음 과정이 발생할 수 있다.

DOM 변경
Layout 계산
Paint
Composite
 

메시지가 하나 추가될 때마다
레이아웃 계산이 발생할 가능성이 있다.

요소 개수가 많아질수록
이 비용도 함께 증가한다.

DevTools로 성능 문제를 확인하는 방법

이런 문제를 분석할 때 가장 많이 사용하는 도구가
Chrome DevTools Performance 패널이다.

확인 방법은 다음과 같다.

  1. Chrome DevTools를 연다
  2. Performance 탭을 선택한다
  3. Record 버튼을 누른다
  4. 페이지에서 문제 상황을 재현한다

그러면 렌더링 타임라인이 기록된다.

타임라인에는 다음 단계가 표시된다.

Scripting
Rendering
Painting
 

여기서 Rendering 단계 안에
Layout 이벤트가 반복적으로 나타난다면
레이아웃 계산이 과도하게 발생하고 있다는 의미다.

실제로 자주 발견되는 문제 – Layout Thrashing

많은 경우 성능 문제의 원인은
Layout Thrashing이다.

예를 들어 다음 코드를 보자.

for (let i = 0; i < items.length; i++) {
items[i].style.width = items[i].offsetWidth + 10
}
 

이 코드에서는 다음 작업이 반복된다.

레이아웃 값 읽기
스타일 변경
레이아웃 값 읽기
스타일 변경
 

이 패턴이 반복되면
브라우저는 Layout 계산을 계속 다시 수행하게 된다.

그래서 성능이 크게 떨어진다.

해결 방법 1 – DOM 읽기와 쓰기 분리

가장 기본적인 해결 방법은 이것이다.

DOM 읽기와 DOM 쓰기를 분리한다

예를 들어 다음 코드다.

const widths = []

for (let i = 0; i < items.length; i++) {
widths.push(items[i].offsetWidth)
}

for (let i = 0; i < items.length; i++) {
items[i].style.width = widths[i] + 10 + "px"
}
 

이렇게 하면 Layout 계산이 한 번만 발생한다.

해결 방법 2 – transform 애니메이션 사용

레이아웃 속성을 변경하는 대신
Composite 단계에서 처리되는 속성을 사용하는 것도 중요하다.

예를 들어 다음 코드다.

left: 100px
 

이 속성은 Layout 계산을 발생시킨다.

하지만 다음 코드는 다르다.

transform: translateX(100px)
 

이 속성은 대부분 Composite 단계에서 처리된다.

그래서 훨씬 부드럽다.

해결 방법 3 – Virtual Scrolling

리스트 UI에서는 DOM 개수를 줄이는 것이 매우 중요하다.

예를 들어 메시지가 1000개 있다고 가정해보자.

하지만 실제로 화면에 보이는 것은
약 10~20개 정도다.

그래서 실제 DOM에는
이 요소들만 유지한다.

스크롤이 이동하면
DOM 내용을 교체한다.

이 기술을 Virtual Scrolling 또는 Windowing이라고 부른다.

대표적인 라이브러리는 다음과 같다.

React Window
React Virtualized

 

이 방법을 사용하면 DOM 개수와 Layout 계산 비용을 크게 줄일 수 있다.

해결 방법 4 – requestAnimationFrame

DOM 업데이트가 많을 때는
requestAnimationFrame을 사용하는 것이 좋다.

예를 들어 다음 코드다.

requestAnimationFrame(() => {
element.style.transform = `translateX(${x}px)`
})
 

이 함수는 브라우저의 렌더링 타이밍과 맞춰 실행된다.

그래서 애니메이션이 훨씬 자연스럽게 동작한다.

브라우저 화면이 렌더링 되는 4단계 과정 일러스트

실제 성능 개선에서 나타나는 변화

이런 최적화를 적용하면 다음과 같은 변화가 나타난다.

Layout 발생 횟수 감소
스크롤 성능 개선
애니메이션 부드러움 증가
모바일 환경에서 프레임 드랍 감소

 

특히 DOM 요소가 많은 페이지에서는
이 차이가 매우 크게 나타난다.

CSS Rendering Path 시리즈 핵심 정리

이 시리즈에서 살펴본 핵심 내용은 다음과 같다.

브라우저는 HTML과 CSS를 바로 화면으로 그리지 않는다.
Layout 계산은 비용이 큰 작업이다.
DOM 읽기와 쓰기를 섞으면 Layout Thrashing이 발생할 수 있다.
transform과 opacity는 Composite 단계에서 처리될 수 있다.
대규모 리스트 UI에서는 Virtual Scrolling이 중요하다.

 

이 원칙들을 이해하면
프론트엔드 성능 문제를 훨씬 구조적으로 분석할 수 있다.

여기까지 이해했다면 충분하다

이 시리즈에서 다룬 내용은
프론트엔드 개발자가 렌더링 성능을 이해하는 데 필요한 핵심 개념들이다.

DOM이 어떻게 만들어지는지
Layout과 Paint가 무엇인지
Reflow가 언제 발생하는지
Composite와 GPU가 어떤 역할을 하는지

 

이 정도만 이해해도 대부분의 CSS 성능 문제는 설명할 수 있다.

더 궁금하다면 이런 키워드를 찾아보면 좋다

이 글에서 다룬 내용은 브라우저 렌더링 구조의 핵심 부분이다.

만약 이 주제가 더 궁금하다면
다음 키워드들을 찾아보면 좋다.

Chrome Rendering Pipeline
Blink Rendering Engine
GPU Rasterization
Layer Compositing
Core Web Vitals

 

특히 다음 공식 문서들이 좋은 출발점이 된다.

MDN Web Docs
Chrome Developers Rendering Performance Guide

 

이 글을 읽은 독자라면
이 문서들도 훨씬 쉽게 이해할 수 있을 것이다.


결국 CSS는 성능을 설계하는 언어다

CSS를 처음 배울 때는
단순히 화면을 꾸미는 언어처럼 보인다.

하지만 브라우저 렌더링 구조를 이해하면
CSS는 전혀 다른 의미를 가지게 된다.

어떤 속성을 사용하느냐에 따라

레이아웃 계산이 발생할 수도 있고
픽셀을 다시 그릴 수도 있고
GPU에서 처리될 수도 있다.

그래서 CSS Rendering Path를 이해하는 순간
CSS는 단순한 스타일 언어가 아니라

브라우저 성능을 설계하는 언어가 된다.

그리고 바로 그 순간부터
프론트엔드 개발을 보는 시각도 완전히 달라진다.

 

반응형