React 성능과 디버깅

대규모 리스트 렌더링 병목 찾기

큰 리스트는 데이터가 많아서만 느린 것이 아닙니다. 화면에 필요한 항목 수, key 안정성, 행 높이, 필터 상태가 함께 렌더 비용을 만듭니다.

data pool

전체 데이터는 보관하되 화면에 전부 그리지 않는다

100k
원본 배열 검색·정렬 전 기준 데이터는 한 곳에 둔다.
filter
파생 목록 입력마다 전체 row를 DOM으로 만들지 않는다.
key
항목 정체성 index가 아니라 안정적인 id로 상태를 붙인다.
virtual window

스크롤 위치 주변의 작은 창만 commit한다

...
위쪽 spacer 보이지 않는 row는 높이만 대표한다.
paint 0
241
visible row viewport 안쪽 row만 실제 DOM을 가진다.
commit
242
active row 선택·입력 상태가 다른 row로 옮겨붙지 않는다.
state
243
overscan row 빠른 스크롤을 위해 주변 행만 조금 남긴다.
buffer
...
아래쪽 spacer 전체 높이 감각은 유지하고 paint 비용은 줄인다.
paint 0
id
stable
height
known
index
risk
memo
row
empty
state
evidence

최적화 여부는 숫자로 닫는다

data window commit evidence
rendered rows 100,000 → 38
commit time 72ms → 11ms
identity risk index key 발견 시 먼저 차단

판정: 스크롤이 부드러운지만 보지 말고, 필터 입력 후 visible row 수와 commit 시간이 같이 줄었는지 확인한다.

01

대규모 리스트 병목 판별 기준

stable key, windowing, item height, pagination, interaction latency 항목을 측정 관점에서 나누고, 화면 상태와 사용자 조작이 어느 컴포넌트에서 바뀌는지 표시합니다.

측정
02

가상화, key, 필터 상태 경계

긴 목록 성능은 리스트 컴포넌트, virtualization 라이브러리, key 생성, 필터/정렬 상태를 실제 스크롤 조작으로 나눠 측정합니다. 항목 수와 렌더 횟수를 함께 봅니다.

렌더 원인
03

대규모 리스트 렌더링 최적화의 실패 조건

스크롤마다 전체 아이템이 다시 렌더링되거나 index key 때문에 항목 상태가 뒤섞이면 리스트 경계가 불안정한 상태입니다. 빠른 스크롤과 필터 입력을 번갈아 실행해 row identity를 확인합니다.

최적화 경계
04

스크롤 FPS와 visible row 증거

마지막에는 FPS, commit time, visible item 수, key 안정성 테스트를 남겨 가상화 적용 뒤 실제 렌더 row 수가 줄었는지 다시 확인합니다.

close
병목 측정
큰 리스트는 전체 row 수보다 한 번에 렌더되는 row 수와 commit 시간이 핵심입니다 Profiler, 스크롤 FPS, 입력 지연을 먼저 재고 windowing, pagination, memo 중 어떤 교정이 맞는지 선택합니다.
FPS + commit
필터 흐름
필터 입력은 파생 목록, 정렬, visible row 계산 순서가 흔들리지 않아야 합니다 검색어 변경 뒤 전체 데이터는 보존하고, 화면에는 현재 viewport에 필요한 항목만 그려지는지 확인합니다.
visible rows
리스트 경계
최적화 적용 전에는 key 안정성, row 높이, 빈 결과, 빠른 입력을 따로 검증합니다 index key로 상태가 섞이지 않는지, 가변 높이 row에서 스크롤 위치가 튀지 않는지, 필터 결과가 0개일 때도 비용이 줄어드는지 확인합니다.
virtual list

대규모 리스트 렌더링 최적화 검증 지점

부드러운 스크롤 대량 데이터에서도 viewport 바깥 row는 렌더하지 않고, 빠른 스크롤과 필터 입력 중 FPS와 commit 시간이 안정적인지 확인합니다.
상태 뒤섞임 index key나 불안정한 item id를 쓰면 스크롤 뒤 선택 상태와 입력값이 다른 row에 붙을 수 있으므로 row identity를 고정합니다.
측정 기록 가상화 적용 전후의 visible row 수, FPS, commit duration, 필터 입력 지연을 같은 데이터 크기로 남깁니다.

성능 디버깅 점검

질문: 데이터 전체 크기와 viewport에 렌더할 row 수를 어떻게 분리할 것인가
순서: 스크롤 병목과 commit 시간 측정하기 -> 필터 입력과 visible row 갱신 흐름 맞추기 -> key 안정성과 가상화 적용 조건 검증하기
위험: index key와 전체 렌더를 그대로 두면 스크롤이 끊기고 row 내부 상태가 다른 항목으로 이동할 수 있습니다.