어 나 갱수.

[JPA] 페이징 처리, JPA Pagination 이란 🦫 본문

JPA

[JPA] 페이징 처리, JPA Pagination 이란 🦫

김경수 2024. 2. 25. 02:17
728x90

페이징 처리란?

페이징 처리는 한 번에 모든 데이터를 가져오면 시간도 많이 걸리고 데이터베이스에도 무리가 갈 수 있으니 나눠서 데이터를 가져올 수 있도록 하는 것을 의미합니다.

우리가 가장 많이 사용하는 웹 사이트 중 하나인 구글도 아래와 같이 페이지네이션 처리를 해두었습니다.

기본적인 동작 원리는 조회할 때 얼마큼 조회할지(size), 어디서부터 조회할지(offset)을 정해서 서버에 요청하면 서버가 해당 페이징 조건에 맞게 반환해 줍니다.

PagingAndSortingRepository 인터페이스

JPA에서는 Pageable 클래스를 이용한다면 간단하게 페이징 처리를 할 수 있습니다.

Spring Data JPA의 PagingAndSortRepository 인터페이스는 CrudRepository 인터페이스를 상속받아 CRUD 작업을 지원하며, 추가적으로 페이지 정렬 기능까지 제공한다. JpaRepository가 상속하고 있는 PagingAndSortingRepository를 살펴보면 아래와 같은 메서드를 제공합니다.

 

페이징 처리와 정렬을 findAll() 메서드로 처리가능하며, 인수로는 Pageable 타입의 객체를 넘겨주어야 합니다.

반환할 때도 기존의 List <T> 타입이 아니라 Page <T> 타입의 객체를 반환합니다.

 

저 findAll 메서드를 이용해서 데이터 쿼리를 수행하면 목록의 데이터를 조회하기 위한 select 쿼리와 페이징 정보를 생성하기 위한 count 쿼리가 한 번씩 발생합니다.

 

Page <T>을 반환할 때는 내부적으로 count 쿼리를 발생시킵니다. 이것이 List <T>와 Page <T>의 차이점입니다.

count는 쿼리문에서 데이터의 개수를 세는 데 사용됩니다. 지금 반환하는 데이터의 개수를 알아야지 페이징 처리가 가능하기 때문에 count쿼리문이 발생하게 되는 겁니다.

여기서 발생하는 문제점은 count 쿼리가 full scan을 하는 방식이기에 시간이 걸려 성능상에 문제가 발생할 수 있습니다.

Hibernate: 
    select
        movieentit0_.idx as idx1_9_,
        movieentit0_.account_idx as account_9_9_,
        movieentit0_.created_at as created_2_9_,
        movieentit0_.crowd_true as crowd_tr3_9_,
        movieentit0_.description as descript4_9_,
        movieentit0_.genre as genre5_9_,
        movieentit0_.movie_url as movie_ur6_9_,
        movieentit0_.thumbnail_url as thumbnai7_9_,
        movieentit0_.title as title8_9_ 
    from
        movie movieentit0_ 
    where
        movieentit0_.title like ? escape ? 
    order by
        movieentit0_.created_at desc limit ?
Hibernate: 
    select
        count(movieentit0_.idx) as col_0_0_ 
    from
        movie movieentit0_ 
    where
        movieentit0_.title like ? escape ?

 

페이징 처리를 하지 않고 데이터를 반환하면 Page 객체를 사용하지 않기 때문에 데이터 목록을 조회하는 select 쿼리만 실행되는 것을 볼 수 있습니다.

Hibernate: 
    select
        movieentit0_.idx as idx1_9_,
        movieentit0_.account_idx as account_9_9_,
        movieentit0_.created_at as created_2_9_,
        movieentit0_.crowd_true as crowd_tr3_9_,
        movieentit0_.description as descript4_9_,
        movieentit0_.genre as genre5_9_,
        movieentit0_.movie_url as movie_ur6_9_,
        movieentit0_.thumbnail_url as thumbnai7_9_,
        movieentit0_.title as title8_9_ 
    from
        movie movieentit0_ 
    where
        movieentit0_.title like ? escape ?

동작 원리

다음과 같은 영화의 목록을 반환하는 API에 페이징 처리를 해보겠습니다.

입력받는 메서드 매개변수에 Pageable를 추가해 주고 반환하는 타입을 Page <T> 타입으로 받아주면 됩니다.

Controller에서 @PageableDefault 어노테이션은 page와 size를 따로 선언하지 않을 경우 defalut로 전달할 값입니다.

 

@PageableDefault

이 어노테이션을 이용하면 pageable 객체의 디폴트 값을 지정할 수 있습니다.

  • page : 페이지의 번호입니다. 설정하지 않으면 디폴트 값은 0입니다.
  • size : 한 페이지에 반환할 데이터의 개수를 의미합니다. 디폴트 값은 20입니다.
  • sort : 가져올 데이터를 어떻게 정렬할지 설정합니다.
728x90

'JPA' 카테고리의 다른 글

[JPA] 더티 체킹 (Dirty Checking)  (0) 2024.08.09
[JPA] JPA와 Hibernate에 대해 알아보자 😏  (0) 2024.03.17
[JPA] 즉시로딩과 지연로딩 🐥  (0) 2024.02.01