MySQL pagination performance 가이드: 페이지가 뒤로 갈수록 느려지는 이유
DB

MySQL pagination performance 가이드: 페이지가 뒤로 갈수록 느려지는 이유


목록 화면을 만들다 보면 pagination은 거의 필수로 들어갑니다. 그런데 처음에는 잘 되던 쿼리가 페이지가 뒤로 갈수록 점점 느려지는 경우가 자주 있습니다. 특히 MySQL에서는 OFFSET 기반 페이지네이션이 커질수록 성능 문제가 드러나는 일이 많습니다.

이 글에서는 아래 내용을 정리합니다.

  • pagination 쿼리가 왜 느려지는지
  • LIMIT ... OFFSET ... 방식의 한계
  • 어떤 경우에 더 나은 방식이 필요한지
  • 실무에서 어떤 기준으로 선택하면 좋은지

핵심은 페이지네이션은 단순 UI 문제가 아니라, MySQL이 얼마나 많은 row를 건너뛰고 읽어야 하는지와 직접 연결된 성능 문제라는 점입니다.

왜 뒤 페이지가 느려질까

예를 들어:

SELECT id, title, created_at
FROM posts
ORDER BY created_at DESC
LIMIT 20 OFFSET 10000;

같은 쿼리는 결국 앞쪽 row들을 많이 건너뛴 뒤 필요한 일부를 가져옵니다. 즉, 뒤 페이지로 갈수록 읽고 버리는 양이 계속 커질 수 있습니다.

OFFSET 방식의 한계

OFFSET 방식은 구현이 단순해서 초반에는 매우 편합니다. 하지만:

  • 페이지가 깊어질수록 느려질 수 있고
  • 정렬 기준이 흔들리면 중복/누락처럼 보일 수 있으며
  • 큰 트래픽에서 비효율이 커질 수 있습니다

즉, 단순하고 익숙하다는 장점은 있지만, 항상 확장성이 좋은 방식은 아닙니다.

어떤 대안이 있을까

대표적으로는 cursor 기반 접근이 자주 언급됩니다.

예를 들어:

  • 마지막으로 본 created_at, id 이후 데이터를 가져오기

같은 방식입니다.

이 방식은 “몇 페이지째인가”보다는 “어디까지 읽었는가”를 기준으로 이어 읽는 구조에 가깝습니다.

cursor 방식이 왜 유리할 수 있을까

cursor 기반 접근은 깊은 페이지로 갈수록 건너뛰는 비용이 커지는 문제를 줄이기 쉽습니다. 특히 정렬 기준이 분명한 목록에서는 훨씬 안정적인 경우가 많습니다.

다만:

  • 페이지 번호 UI와 바로 맞추기 어려울 수 있고
  • 정렬 기준 설계가 중요하며
  • 구현이 조금 더 복잡할 수 있습니다

즉, 성능과 사용성 사이의 선택이 함께 들어갑니다.

어떤 기준으로 선택하면 좋을까

OFFSET이 잘 맞는 경우

  • 데이터 양이 크지 않음
  • 뒤 페이지 접근이 많지 않음
  • 단순한 페이지 번호 UX가 중요함

cursor가 잘 맞는 경우

  • 데이터가 많음
  • 뒤로 깊게 탐색하는 경우가 많음
  • 무한 스크롤이나 “더 보기” UX와 잘 맞음

인덱스는 왜 중요할까

페이지네이션도 결국 정렬과 범위 조회이기 때문에 인덱스가 중요합니다. 특히 정렬 기준 컬럼과 조건 컬럼이 인덱스와 잘 맞지 않으면 성능이 더 나빠질 수 있습니다.

즉, pagination 문제는 SQL 구조만이 아니라 정렬 인덱스 설계와도 연결됩니다.

자주 하는 오해

1. LIMIT이 있으니 항상 빠르다

뒤쪽 OFFSET이 크면 앞부분을 많이 건너뛰는 비용이 여전히 큽니다.

2. 페이지네이션은 프론트 문제다

실제로는 DB 접근 방식과 쿼리 비용 문제입니다.

3. cursor 방식은 무조건 더 좋다

성능에는 유리할 수 있지만, 페이지 번호 기반 UX에는 불편할 수 있습니다.

FAQ

Q. 페이지 번호 UI가 꼭 필요하면 cursor는 못 쓰나

완전히 못 쓰는 것은 아니지만, 설계가 더 복잡해질 수 있습니다.

Q. 뒤 페이지가 느리면 무엇부터 봐야 하나

OFFSET 크기, 정렬 기준, 인덱스 설계를 먼저 보는 것이 좋습니다.

Q. 작은 서비스도 이 문제를 신경 써야 하나

초반에는 단순하게 가도 되지만, 목록 데이터가 빨리 커지는 서비스라면 미리 감을 잡아두는 것이 좋습니다.

먼저 읽어볼 가이드

검색 유입이 많은 핵심 글부터 이어서 보세요.