본문 바로가기
웹개발

[CSS Rendering Path][3편] DOM이 많아질수록 웹이 느려지는 이유 (Virtual DOM과 리스트 UI 성능)

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

CSS Rendering Path 썸네일 일러스트


1편에서는 브라우저가 화면을 만드는 구조를 살펴봤다.

HTML을 읽는다.
CSS를 읽는다.
Render Tree를 만든다.
Layout을 계산한다.
Paint를 수행한다.

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

레이아웃(Layout) 계산은 브라우저에서 비용이 큰 작업이다.

2편에서는 렌더링 성능을 개선하는 방법을 살펴봤다.

transform 애니메이션
GPU Composite
requestAnimationFrame

이제 다음 질문이 생긴다.

이런 개념들이 실제 서비스에서는 어떻게 문제를 만들까?

특히 다음 상황에서 성능 문제는 더 자주 나타난다.

DOM 요소가 매우 많을 때
스크롤이 계속 발생할 때
UI가 실시간으로 업데이트될 때

이번 글에서는 대규모 UI에서 성능 문제가 발생하는 이유와 해결 방법을 살펴본다.


실제 서비스에서 가장 흔한 UI

많은 웹 서비스에는 다음과 같은 화면이 존재한다.

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

이 UI들의 공통점이 있다.

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

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

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

DOM 요소가 많아지면 왜 느려질까

브라우저의 Layout 단계는 단순히 하나의 요소만 계산하는 것이 아니다.

다음 요소들도 함께 계산해야 한다.

부모 요소의 크기
형제 요소의 위치
줄바꿈 위치
flex / grid 계산

즉 하나의 요소가 바뀌면
주변 레이아웃도 함께 다시 계산될 수 있다.

그래서 DOM 트리가 커질수록
Layout 계산 비용도 함께 증가한다.

React가 Virtual DOM을 만든 이유

React 같은 프레임워크가 등장한 이유도 바로 이 문제 때문이다.

브라우저에서 직접 DOM을 많이 변경하면
렌더링 비용이 크게 증가한다.

그래서 React는 Virtual DOM이라는 개념을 사용한다.

Virtual DOM은 실제 DOM이 아니라
메모리 안에 존재하는 가상의 DOM 구조다.

예를 들어 다음 HTML이 있다고 생각해보자.

<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
 

React는 이 구조를 메모리 안에서
객체 형태로 저장한다.

그리고 상태가 변경되면
새로운 Virtual DOM을 만든다.

그 다음 이전 Virtual DOM과 비교한다.

이 과정을 Diffing이라고 부른다.

Virtual DOM이 하는 일

Virtual DOM의 목적은 하나다.

실제 DOM 변경을 최소화하는 것

예를 들어 이런 상황을 생각해보자.

기존 목록
A
B
C
새 목록
A
B
D
 

브라우저가 직접 처리하면
모든 요소를 다시 렌더링할 수도 있다.

하지만 Virtual DOM은 이렇게 판단한다.

A 동일
B 동일
C → D 변경
 

그래서 실제 DOM에서는
C만 변경된다.

이렇게 하면 DOM 변경 횟수가 줄어든다.

하지만 Virtual DOM도 모든 문제를 해결하지는 않는다

Virtual DOM은 DOM 업데이트를 줄여준다.

하지만 다음 작업은 여전히 발생한다.

Layout
Paint
Composite

즉 렌더링 비용 자체는 여전히 존재한다.

그래서 대규모 UI에서는
추가적인 전략이 필요하다.

CSS 렌더링 과정을 4단계로 표현한 일러스트

리스트 UI에서 자주 발생하는 성능 문제

웹 서비스에서 가장 흔한 UI가 바로 리스트다.

예를 들어 다음과 같은 화면이다.

채팅 메시지 목록
뉴스 피드
상품 목록
댓글 목록

이런 화면에서는 수백 개 또는 수천 개의 DOM 요소가 존재할 수 있다.

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

브라우저는 1000개의 DOM 요소를 생성해야 한다.

그리고 Layout 계산도 수행해야 한다.

이 순간 성능 문제가 발생할 수 있다.

해결 방법 – Virtual Scrolling

이 문제를 해결하기 위해 등장한 기술이 있다.

Virtual Scrolling 또는 Windowing이다.

이 기술의 핵심 아이디어는 단순하다.

화면에 보이는 요소만 렌더링한다.

예를 들어 리스트가 1000개라도
실제로 화면에 보이는 것은 약 10~20개 정도다.

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

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

이렇게 하면 DOM 개수가 크게 줄어든다.

그래서 Layout 계산도 훨씬 가벼워진다.

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

React Window
React Virtualized

Layout Thrashing을 구조적으로 막는 방법

1편에서 우리는 Layout Thrashing을 살펴봤다.

예를 들어 이런 코드다.

element.style.width = element.offsetWidth + 10
 

이 패턴이 반복되면
Layout 계산이 계속 발생한다.

대규모 UI에서는 이 문제가 더 심각해질 수 있다.

그래서 구조적인 해결 방법이 필요하다.

대표적인 방법은 다음과 같다.

DOM 읽기와 쓰기 분리
requestAnimationFrame 사용
batch DOM update
CSS transform 활용

이 방법들을 사용하면 Layout 계산 횟수를 크게 줄일 수 있다.

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

Chrome DevTools에서는 렌더링 성능을 직접 확인할 수 있다.

방법은 다음과 같다.

DevTools 열기
Performance 탭 선택
Record 클릭
페이지에서 문제 상황 재현

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

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

Scripting
Rendering
Painting

Rendering 단계 안에 Layout 이벤트가 반복된다면
Layout 계산이 과도하게 발생하고 있다는 의미다.

핵심 정리

대규모 UI에서는 DOM 요소가 많아질수록 Layout 비용이 증가한다.
Virtual DOM은 DOM 변경 횟수를 줄여준다.
리스트 UI에서는 Virtual Scrolling이 매우 중요하다.
DOM 읽기와 쓰기를 분리하면 Layout Thrashing을 줄일 수 있다.

이 구조를 이해하면
대규모 UI 성능 문제를 훨씬 쉽게 분석할 수 있다.


다음 글에서 다룰 내용

지금까지는 브라우저 렌더링 구조와
대규모 UI에서 발생하는 성능 문제를 살펴봤다.

마지막 글에서는 다음 내용을 살펴본다.

실제 서비스에서 성능 문제를 찾는 방법
DevTools로 Layout 문제 분석하기
실제 코드에서 성능 최적화 적용하기
렌더링 성능 체크리스트

이제 렌더링 구조와 UI 성능을 이해했으니
다음 단계는 실제 성능 분석 사례다.

 

반응형