개념 : 몇 번째 페이지인지 기준으로 데이터를 잘라 가져오는 방식
- 요청 예시 :
GET /엔드포인트?page=4&size=20
-> 5번째 페이지의 20개 가져와줘
Spring Data JPA의 Pageable 인터페이스로 구현이 가능하다.
응답 정보
- 현재 페이지 번호
- 전체 페이지 수
- 전체 데이터 수
- 첫번째/마지막 페이지 여부
단점
데이터가 많을수록 느려질 수 있다.
정적인 데이터에는 적절하지만, 실시간으로 변경되는 데이터가 있는 경우 문제가 생긴다.
이처럼 데이터가 실시간으로 변경될 수 있다면 offset 방식은 데이터 누락 문제로 이어질 수 있다.
예를 들어, 관리자 권한으로 대기 ➔ 승인으로 상태를 변경할 시, 실시간으로 데이터가 빠지는 등, 데이터 변동이 잦기 때문에
정확한 이어보기와 부드러운 무한스크롤을 위해 cursor 기반 페이지네이션을 사용하는 게 낫다.
개념 : 특정 데이터(커서)를 기준으로 그 이후의 데이터를 가져오는 방식
즉, 마지막으로 본 데이터를 기준으로 삼고, 그 다음 데이터를 가져오는 방식이다.
응답에 포함되는 정보:
요청 :
최초 요청 시: 커서 없이 요청 → 첫 번째 커서 기준으로 응답
이후 요청 시: 마지막으로 받은 커서 값을 기준으로 다음 데이터 요청
특징 :
주의할 점
커서로 사용하는 값은 정렬 가능한 고유한 값이어야 함
커서 값이 동일한 데이터가 여러 개 있을 경우, 중복 조회되거나 누락되는 문제 발생 가능
→ 두 번째 정렬 기준 필요 (ex. 첫 번째 커서 - createdAt, 두 번째 커서 - id)
구현 방식 :
Page 처럼 공식적으로 정해진 클래스가 없으니
각자의 서비스에 맞게 CursorPageResponse 커스텀 응답 클래스를 정의해서 사용해야 한다.
@Getter
@AllArgsConstructor
public class CursorPageResponse<T> {
private List<T> content; // 데이터들
private LocalDateTime nextCreatedAt; // 마지막 인증의 생성시간
private Long nextCertificationId; // 마지막 인증의 ID
private boolean hasNext; // 더 많은 데이터가 있는지 여부
}