헬창 개발자

페이지네이션 본문

공부방

페이지네이션

찬배 2026. 2. 25. 10:53

페이지네이션이란?

OLTP 환경에서 사용자에게 반환되는 데이터들은 대부분 특정 기준으로 정렬된 일부 데이터이다. 

예를 들면 웹개발의 가장 흔한 예시인 게시판이 그렇다. 게시판은 일반적으로 한 페이지에 약 20개의 게시글들을 최신순으로 노출시키고, 사용자가 다음 페이지로 넘어가게 되면 21 ~ 40번째 데이터가 그제서야 조회되는 방식으로 구현된다.

이 상황에서 서버는 사용자에게 전체 게시글 데이터를 전달하는 것이 아닌, 사용자가 위치한 페이지에 해당하는 데이터만을 반환하도록 API 설계가 이루어지는데 이를 페이지네이션 방법론이라고 부른다.

Offset Pagination

Offset Pagination은 원하는 데이터가 전체 데이터에서 몇 번째(offset) 위치에 있는지 지정하고, 그 위치에서부터 몇 개(limit)의 데이터를 가져올지 정하는 방식이다.

우리가 알고 있는 일반적인 Pagination 이 Offset Pagination 이다.

장점과 그 원인

  • 직관적이고 간단한 구현
    • 원인: offset 값만 알면 바로 특정 위치를 찾아서 데이터를 가져올 수 있어서 직관적이다.
  • 페이지 번호로 직접 접근이 쉬움
    • 원인: offset이 페이지 번호를 곱해서 얻어지기 때문에 원하는 페이지로 바로 이동하는 기능을 쉽게 구현할 수 있다.

단점과 그 원인

  • 데이터가 많아질수록 속도가 크게 느려짐
    • 원인: offset이 커질수록 데이터베이스는 앞쪽 데이터를 계속해서 읽고 건너뛰어야 한다. 따라서 데이터가 많아질수록 성능이 떨어진다.
  • 데이터가 추가되거나 삭제되면 중복 또는 누락이 발생할 수 있음
    • 원인: offset은 데이터의 고정된 위치를 기반으로 하기 때문에, 중간에 데이터가 추가되거나 삭제되면 데이터의 위치가 바뀌어 중복 또는 누락이 발생할 수 있다.

Cursor Pagination

Cursor 페이지네이션은 페이스북의 무한 스크롤 또는 더보기 버튼을 클릭해 다음 데이터를 불러오는 방식이다.

 

 

장점과 그 원인

  • 데이터가 많아져도 성능이 거의 변하지 않음
    • 원인: 특정 키(cursor)를 기준으로 데이터를 바로 가져오기 때문에, 데이터를 처음부터 스캔할 필요가 없어서 성능 저하가 거의 없다.
  • 데이터가 실시간으로 추가/삭제되더라도 중복이나 누락이 없음
    • 원인: 명확한 키 값을 기준(cursor)으로 데이터를 가져오기 때문에 중간에 데이터가 변하더라도 데이터를 놓치거나 중복으로 가져오는 문제가 발생하지 않는다.

단점과 그 원인

  • 특정 페이지로 바로 이동하는 것이 어려움
    • 원인: cursor를 기반으로 움직이기 때문에 중간 페이지로 바로 이동하려면, 그 페이지까지 cursor를 계속 따라가야 한다. 페이지 번호를 바로 찾아가는 것이 어렵다.
  • 커서(cursor)가 될 수 있는 키 값이 반드시 유일하고 정렬 가능한 값이어야 함
    • 원인: cursor가 명확히 정렬되지 않거나 중복이 있으면 데이터를 제대로 가져올 수 없기 때문에 안정적인 키 값을 반드시 사용해야 한다.

Cursor 기반 방법이 Offset 기반보다 빠를까?

그 이유는 각 쿼리의 동작 방식에 있다.
Offset 기반 pagination은 Table full scan이 발생하고 있다. 위 쿼리에 대한 나의 의도는 n번째 데이터에 곧바로 접근하여 그 뒤 데이터들을 반환하는 것이었다. 하지만 이와 다르게, 실제로는 테이블을 맨 위부터 훑으면서 n번째 데이터를 찾고, 그 뒤에 반환을 하고 있다.

 

반면에 Cursor 기반 pagination은 Index range scan이 발생하고 있다. MySQL은 PK를 기준으로 Clustered index를 기본으로 생성한다. 따라서 현재 ID를 기준으로 index가 존재하는 것이고, 이 index를 통해서 n번째 데이터를 찾은 후에 나머지 데이터를 반환하고 있는 것이다. 게다가 MySQL InnoDB 기준, Clustered index에는 실제 행 데이터를 저장하고 있기 때문에 다른 요소를 방문해야 하는 추가적인 연산이 필요하지 않다.

 

 

정리하자면, index를 타느냐 안 타느냐에 따라서 성능 차이가 크게 발생하고 있는 것이다.

 



참고

https://eunajung01.tistory.com/170

https://velog.io/@ygreenb/Paginationoffset-vs-cursor