Cursor기반 Pagination 구현

박종하·2025년 8월 28일
post-thumbnail

위 글에서 페이지네이션의 두 가지 구현 방식을 알아보았다. 이해를 돕기 위해 이번 글에서는 Java 환경에서 커서 기반으로 페이지네이션을 구현해보겠다.


PageInfo

가장 먼저 페이지네이션을 적용한 데이터들을 담을 응답 객체를 정의해야 한다.

import java.util.List;
import java.util.function.Function;

public record PageInfo<T>(
        String pageToken,
        List<T> data,
        boolean hasNext
) {
    public static <T> PageInfo<T> of(
            List<T> data,
            int expectedSize,
            Function<T, Object> pageTokenFunction
    ) {
        if (data.size() <= expectedSize) {
            return new PageInfo<T>(null, data, false);
        }

        var lastValue = data.get(expectedSize - 1);
        var pageToken = pageTokenFunction.apply(lastValue).toString();
        return new PageInfo<T>(pageToken, data.subList(0, expectedSize), true);
    }
}
  • <T>: 제너릭 타입을 통해 선언 시 구체 타입을 정할 수 있게 한다.
    ex) PageInfo<PostDetailResponse>
  • pageToken: 다음 페이지 요청 기준이 되는 cursor 값.
  • List<T> data: 응답 데이터들이 담길 곳.
  • hasNext: 다음 페이지 존재 여부. null일 시 첫 페이지 조회.

정적 팩토리 메서드 부분

  • expectedSize: 다음 페이지 여부를 확인하기 위한 페이지 크기(기대하는 페이지 크기보다 작으면 다음 페이지가 없다는 뜻)
  • Function<T, Object> pageTokenFunction: T 타입을 받아 Object로 변환 후, 문자열 형태로 pageToken 생성

ex)

PageInfo.of(data, DEFAULT_PAGE_SIZE, PostDetailResponse::createdAt);

PostDetailResponse를 받아서 createdAt으로 변환해 pageToken 생성.

Query 생성

쿼리를 작성하는 부분은 구현 환경에 따라 다르니 sql 형식으로 작성하겠다.

SELECT 응답 객체 (위의 T타입에 해당하는 객체)
FROM ~
ORDER BY 정렬기준 (id, createdAt 등등)
WHERE id > pageToken
LIMIT pageSize + 1 (정해논 페이지 크기보다 하나 더 가져와서 다음 pageToken으로 사용)

이렇게 조회해온 데이터로 PageInfoof메서드를 통해 생성해 응답을 내려주면 된다.


정리

  1. 페이지네이션 응답 객체 정의.
  2. Cursor 기반 페이지네이션 쿼리 작성.

*페이지네이션은 도메인과 클라이언트 개발자와의 소통이 매우 중요하다고 생각한다. 언제나 상황에 적절한 방법을 쓰자.

profile
Ex Pilot, Now Developer

0개의 댓글