포스트

페이지네이션에서 count 쿼리 비용 줄이기

페이지네이션에서 count 쿼리 비용 줄이기

코드 리뷰에서 알게 된 사실

카카오테크캠퍼스에서 선물하기 API에 페이지네이션을 붙이면서 Spring Data JPA의 Page를 반환하도록 구현했다. 코드 리뷰 과정에서 다음 내용을 안내받았다.

“Page는 내부적으로 전체 데이터 개수를 알아야 해서 추가로 count 쿼리가 실행됩니다.”

이때 처음으로 Page를 쓰면 요청마다 SELECT COUNT(*)가 같이 나갈 수 있다는 걸 알았다.

count 쿼리가 왜 부담이 될 수 있나?

데이터가 적을 땐 별 문제 없다. 하지만 데이터가 커지면 COUNT(*)가 생각보다 비싸질 수 있다(인덱스/조건/조인 형태에 따라).

특히 무한 스크롤 UI라면 전체 개수가 중요하지 않을 때가 많다. 그런데 Page를 쓰면 그 정보 때문에 쿼리가 추가로 발생한다.

멘토님 피드백:

“Page 객체 내부에는 불필요한 정보가 많이 노출됩니다. totalPages, totalElements, sort, numberOfElements 등. 클라이언트에서 일부 정보만 필요하다면, 불필요한 직렬화 비용이 생길 수 있어요.”

“이걸 피하려면 Slice를 쓰면 돼요. Slice는 다음 페이지 존재 여부만 판단하기 때문에 count 쿼리를 실행하지 않습니다.”

Page vs Slice

특성PageSlice
count 쿼리실행한다안 한다
전체 페이지 수알 수 있다모른다
다음 페이지 여부알 수 있다알 수 있다
적합한 UI페이지 번호 표시무한 스크롤, 더 보기

언제 뭘 쓰나?

Page

  • 1 2 3 4 5 식으로 페이지 번호가 필요할 때
  • 총 2,340개의 상품 같은 전체 개수가 필요할 때

Slice

  • 무한 스크롤
  • 더 보기 버튼만 있을 때
  • 전체 개수가 필요 없을 때

정리

  • 페이지 번호나 총 개수가 정말 필요하면 Page
  • 그렇지 않으면(더 보기, 무한 스크롤 등) Slice로 count 쿼리를 피하는 게 낫다
  • 프레임워크가 편하게 해주는 만큼, 뒤에서 어떤 쿼리가 나가는지는 한 번씩 확인하는 편이 안전하다

프로젝트: 카카오테크캠퍼스 3기 선물하기 API 클론 코딩 관련 링크

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.