blog

대용량 리스트 최적화: 가상화와 페이지네이션, 언제 무엇을 쓸까

Front-end / React#가상화#페이지네이션#성능#TanStack Virtual

둘 다 "데이터가 많을 때"의 최적화지만, 줄이는 대상이 다르다.

  • 가상화(Virtualization): 데이터는 많이 갖고 있되, 화면에 보이는 항목만 DOM으로 그린다. 렌더링 비용을 줄인다.
  • 페이지네이션(Pagination): 데이터 자체를 나눠서 요청한다. 네트워크·메모리·서버 부하를 줄인다.

그래서 먼저 "문제가 API 응답량인가, DOM 렌더링인가"를 구분해야 한다.

가상화

장점

  • 부드러운 스크롤: 수천~수만 개 항목이라도 실제 DOM은 수십 개만 유지하므로 스크롤 성능이 안정적이다.
  • 끊김 없는 탐색: 페이지 이동 없이 하나의 긴 리스트로 탐색할 수 있어 피드·타임라인·로그 뷰에 어울린다.
  • 리스트 안의 인터랙션: 드래그 앤 드롭, 인라인 편집, 섹션 접기처럼 리스트 안에서 많이 조작하는 UI와 잘 맞는다.

단점

  • 구현 복잡도: 스크롤 위치, 항목 높이(특히 동적 높이), overscan, 계층 데이터 평탄화 등을 관리해야 한다. 라이브러리(TanStack Virtual, react-window, react-virtuoso)를 써도 동적 높이·무한 스크롤·그룹핑이 섞이면 디버깅이 어렵다.
  • 데이터는 여전히 메모리에: 그리는 양만 줄일 뿐, 클라이언트가 들고 있는 데이터 양은 그대로다.
  • 브라우저 기본 기능 손실: 화면 밖 항목은 DOM에 없으므로 브라우저 찾기(Ctrl+F)에 걸리지 않고, 스크린 리더가 전체 개수를 알기 어렵다(aria-setsize, aria-posinset 보완 필요).
  • 위치 공유·복원: "N번째 항목"을 URL로 공유하거나 뒤로 가기 시 정확한 스크롤 위치로 돌아오게 하려면 인덱스와 스크롤 위치를 직접 관리해야 한다.

페이지네이션

장점

  • 데이터량 자체 감소: 한 번에 50~100개만 받으므로 응답이 가볍고 메모리 사용이 적다.
  • 단순한 구현: page, pageSize, total 정도만 관리하면 된다.
  • 예측 가능한 UX와 공유 가능한 URL: "3 / 10페이지"처럼 위치가 명확하고, ?page=3으로 공유·북마크·검색 엔진 노출이 쉽다.
  • 서버 부하 제한: 요청마다 일정한 양만 조회한다. 데이터가 아주 크면 OFFSET 방식은 뒤쪽 페이지로 갈수록 느려지므로 커서 기반 페이지네이션을 고려한다.

단점

  • 연속 탐색이 끊긴다: 피드형 UX에는 맞지 않는다.
  • 페이지 이동마다 로딩: prefetch와 캐시로 줄일 수는 있지만 완전히 없애기 어렵다.
  • 페이지를 넘나드는 인터랙션: "1페이지 항목을 3페이지로 드래그" 같은 동작은 페이지 간 상태 동기화가 필요해 복잡해진다.

무엇을 고를까

가상화가 유리한 경우

  • 피드, 로그, 채팅, 백로그 보드처럼 한 화면에서 많이 스크롤하는 UI
  • 데이터를 한 번에 받아도 되는 크기(수천~수만 건)이고, 문제의 핵심이 DOM 렌더링인 경우
  • 저사양 기기에서도 스크롤이 부드러워야 하는 경우

페이지네이션이 유리한 경우

  • 수십만 건 이상으로 계속 늘어나는 데이터(어드민 그리드 등)
  • 사용자가 주로 앞쪽 일부나 검색 결과만 보는 경우
  • URL 공유, SEO, 필터·정렬이 중요한 검색 결과·대시보드
  • 서버 쿼리와 네트워크 비용이 병목인 경우

함께 쓰기

실무에서는 둘을 함께 쓰는 경우가 많다.

  • 서버·네트워크·메모리는 페이지네이션(또는 무한 스크롤 단위 로딩)으로 1차 통제
  • 한 번에 받은 묶음이 수백~수천 개라면 그 안의 DOM은 가상화로 2차 통제

무한 스크롤(TanStack Query의 useInfiniteQuery) + 가상화 조합이 대표적이다. 계층형 데이터라면 섹션 단위로 페이지네이션하고 각 섹션 내부 리스트에만 가상화를 적용하는 식으로 복잡도를 통제할 수 있다.

정리

항목가상화페이지네이션
줄이는 것DOM 렌더링데이터·네트워크·서버 부하
탐색 경험끊김 없는 스크롤구간 단위 이동
구현 난이도높음낮음
URL 공유·SEO어려움쉬움
메모리데이터만큼 사용페이지 크기만큼 사용

참고