페이지 번호를 이용해 가져올 데이터의 위치를 파악하는 방식으로 아래 코드는 수정 전 사용했던 코드로, Pageable 인터페이스를 활용해 조회하는 방식
// Controller
@GetMapping("/users")
public ResponseEntity<UsersResponse> findAll(Pageable pageable) {
UsersResponse usersResponse = userService.findAllUsers(pageable);
return ResponseEntity.ok(usersResponse);
}
// Service
public UsersResponse findAllUsers(Pageable pageable) {
Page<Task> findUsers = userRepository.findAllUsersWithPaging(pageable);
return UsersResponse.from(findUsers);
}
// Repository
Page<Task> findAllUsersWithPaging(Pageable pageable);
Pageable 인터페이스를 활용하면 쉽게 페이지네이션을 구현할 수 있지만, 데이터의 양이 많아지면 쿼리 속도가 확연히 느려짐
이유는 오프셋의 동작방식과 실제 발생하는 쿼리를 보면 클라이언트에서 넘겨받는 페이지 번호와 페이지 사이즈를 가지고 서버에서 오프셋 값을 구함
오프셋 = (페이지 번호 - 1) * 페이지 사이즈 이기 때문에 페이지 사이즈가 20인 경우 아래와 같이 오프셋 값이 늘어남
// Query
SELECT * FROM user LIMIT 페이지사이즈 OFFSET 오프셋;
SELECT * FROM user LIMIT 20 OFFSET 0; # 1~20 출력
SELECT * FROM user LIMIT 20 OFFSET 20; # 21~40 출력
SELECT * FROM user LIMIT 20 OFFSET 40; # 41~60 출력
...
SELECT * FROM user LIMIT 20 OFFSET 999980; # 999981~100000 출력
offset을 사용하지 않고 데이터를 가져오는 방법으로 일반적으로 데이터베이스에서 이전 페이지의 마지막 아이템을 추적하고, 해당 아이템보다 큰 값을 기준으로 데이터를 가져오는 방식
No offset 페이징을 API로 구현된다면 다음과 같은 형태가 됨
Pageable 인터페이스를 활용한 위 코드를 QueryDSL을 통한 No Offset으로 변환
public List<MapResponseDto> findAllByMap(Long mapId, String sort, int pagesize) {
// 1. id < 파라미터를 첫 페이지에선 사용하지 않기 위한 동적 쿼리
BooleanBuilder dynamicLtId = new BooleanBuilder();
if (mapId != null) {
dynamicLtId.and(map.id.lt(mapId));
}
return queryFactory
.select(Projections.fields(
MapResponseDto.class,
map.mapNo,
map.category,
map.title,
map.address,
map.view,
map.content,
mapReview.countDistinct().as("reviewCount"),
wish.countDistinct().as("wishCount"),
mapImg.mapImgUrl,
map.createdAt,
map.modifiedAt
))
.from(map)
.leftJoin(mapImg)
.on(map.mapNo.eq(mapImg.map.mapNo))
.leftJoin(mapReview)
.on(map.mapNo.eq(mapReview.map.mapNo))
.leftJoin(wish)
.on(map.mapNo.eq(wish.map.mapNo))
.where(dynamicLtId)
.groupBy(map.mapNo)
.orderBy(boardSort(sort, "map"), map.mapNo.desc())
.limit(pagesize)
.fetch();
}
https://jojoldu.tistory.com/528
https://wonit.tistory.com/483?category=853673