직접 offset, limit 등 변수를 선언하여 JPARepository의 메서드인 findByPage, totalCount을 이용하여 페이징 코드를 작성하는 것으로, totalCount를 먼저 불러와서 그에 맞도록 동적 페이징 코드를 작성하는 것이다.
마지막 페이지가 애매하게 되었을 때는 불러오는 값이 굉장히 정합성이 떨어지기도 한다.
위에서 순수 JPA를 사용하게 되면 totalCount를 뽑아와서 현재 내가 몇번째 페이지인지를 계산해서 표시를 해주어야 한다. 이런 계산은 매우 복잡하다. 이 복잡한 계산을 해결해주기 위해 Spring Data JPA는 페이징과 정렬을 표준화 해두었다.
org.springframework.data.Sort : 정렬 기능
org.springframework.data.Pageable: 페이징 기능 (내부에 Sort 포함)
org.springframework.data 내부에 Sort와 Pageable 클래스가 존재한다. 즉, 모든 DB의 페이징이 공통화 되있음을 의미한다.
org.springframework.data.domain.Page : 페이지 + Total Count 쿼리 포함
org.springframework.data.domain.Slice : 페이지만 확인, 내부적으로 limit + 1조회
List : 추가 count 쿼리 없이 결과만 반환(페이징 기능 없음)
Page 형태로 값을 반환받으면 내부적으로 Total Count가 포함되어있다. 편리하지만, 이 때의 문제점은 복잡한 Count 쿼리가 나갈 수 있다는 점이다. 예를 들어 Count 쿼리에 쓸데없는 Join 쿼리가 덕지덕지 붙어 나갈 때가 있는데, 이것이 실제로는 필요 없을 수가 있다. 이런 부분의 최적화가 필요하다.
Slice는 Total Count 쿼리는 나가지 않는다. 대신에 내부적으로 Limit + 1로 페이징을 해준다. 그래서 내부적으로 다음 페이지가 있다 없다를 표현해줄 수 있다. 객체를 Limit + 1만큼 표현해주지는 않고, 내부적으로 다음 페이지가 있는지를 표현하는데 사용한다.
Page나 Slice 인터페이스를 사용하게 되면, 마지막 페이지의 애매한 부분까지 잘 처리되어 가져오는 것이 확인되었다. 따라서 페이징 기능을 위해 Page나 Slice를 적극 활용하는 것이 좋을 것 같다.
위의 예시는 스프링 데이터 JPA가 자동으로 생성해주는 메서드 쿼리를 이용한 기능이다. QUERY DSL을 이용해 직접 사용자 리포지토리에 쿼리를 작성하고 그것을 이용하는 방법이 있는데 자세한 내용은 생략한다.