JPA를 이용해서 Paging API를 만들어 보도록 하겠습니다. 페이징 처리는 거의 모든 웹 개발에서 사용하고 있습니다. 그렇게 복잡하고 어려운 구현은 아니나 실제 쿼리로 작성할 때는 상당히 번거로운 작업이 됩니다. 또 데이터베이스마다 페이징 쿼리가 조금씩 다르다는 점도 복잡도를 높이는 요인 중 하나입니다.
Spring Data JPA에서는 이러한 문제를 아주 쉽게 해결할 수 있어 핵심 비즈니스 로직에 집중할 수 있게 해줍니다. 지금부터 예제를 설명하겠습니다.
기초 작업
이전에 작성한 AccountRepository는 JpaRepository를 상속하고 있습니다. JpaRepository는 PagingAndSortingRepository 클래스를 상속 받고 있습니다. 페이징 작업을 위한 작업은 AccountRepository를 작성한 순간 대부분 끝난 것입니다.
CurdRepository를 상속하는 것보다 하위 클래스인 JpaRepository를 상속 받아 Repository를 구현하는 것이 좋습니다.
페이징 처리하는 메서드도 간단합니다. 매게변수로 Pageable 받아 Page<T>으로 리턴해줍니다.
Pageable은 다양한 요청 이용해서 기본적인 정렬 기능을 제공합니다. page는 실제 페이지를 의미하고 size는 content의 size를 의미합니다. sort는 페이징을 처리 시 정렬을 값을 의미합니다. id,DESC는 id 기준으로 내림차순 정렬을 하겠다는 것입니다.
아래는 실제 JPA에서 작성한 Query 입니다. 쿼리문을 코드로 작성하기 때문에 실제로 어떤 쿼리가 동작하는지 반드시 확인하는 습관을 갖는 것이 좋습니다.
select account0_.id as id1_0_, account0_.address1 as address2_0_, account0_.address2 as address3_0_, account0_.zip as zip4_0_, account0_.created_at as created_5_0_, account0_.email as email6_0_, account0_.first_name as first_na7_0_, account0_.last_name as last_nam8_0_, account0_.password_expiration_date as password9_0_, account0_.password_failed_count as passwor10_0_, account0_.password_ttl as passwor11_0_, account0_.password as passwor12_0_, account0_.update_at as update_13_0_ from account account0_ orderby account0_.id desclimit ?
select count(account0_.id) as col_0_0_ from account account0_
개선
위의 Pageable의 개선할 점이 있습니다. 우선 size에 대한 limit이 없습니다. 위의 API에서 size값을 200000을 넘기면 실제 데이터베이스 쿼리문이 200000의 조회할 수 있습니다. 그 밖에 page가 0 부터 시작하는 것들도 개선하는 것이 필요해 보입니다.
Spring Data JPA는 페이징 처리는 데이터베이스마다 페이징 쿼리가 다른 부분들은 신경 쓰지 않고 더 쉽게 구현할 수 있는 장점이 있습니다. 또 Pageable을 통해서 페이징 구현이 가능하지만, 별도의 Request 객체를 두어서 관리하는 것이 안전하고 효과적입니다.