
JPA를 쓰면서 동적 페이징처리가 매우 쉬워졌다.
PageRequest 객체가 자동으로 limit, offset으로 페이징하던 이전 쿼리를 자동으로 생성해주기 때문이다.
Page 와 Slice
PageRequest 객체를 통해 페이징을 할 때, 반환 타입으로 Page와 Slice를 사용한다.
두 객체의 결과물과 성능이 어떤 차이가 있는지 비교 해보자.
1. 우선 Page 와 Slice를 반환해주는 레포지토리를 만든다.
//MemberRepository
...
Page<Member> findPageBy(Pageable pageable);
Slice<Mebmer> findSliceBy(Pageable pageable);
...
2. 아래 테스트 코드를 실행시킨다.
@Test
public void paging() throws Exception {
//given
memberRepository.save(new Member("member1", 10));
memberRepository.save(new Member("member2", 10));
memberRepository.save(new Member("member3", 10));
memberRepository.save(new Member("member4", 10));
memberRepository.save(new Member("member5", 10));
PageRequest pageRequest = PageRequest.of(1, 2, Sort.by(Sort.Direction.ASC, "age"));
//when
Page<Member> page = memberRepository.findPageBy(pageRequest);
Slice<Member> slice = memberRepository.findSliceBy(pageRequest);
//then
...
}
3.
Page
select
member0_.member_id as member_i1_0_,
member0_.age as age2_0_,
member0_.team_id as team_id4_0_,
member0_.username as username3_0_
from
member member0_
order by
member0_.age asc limit ? offset ?
select
count(member0_.member_id) as col_0_0_
from
member member0_
select member0_.member_id as member_i1_0_, member0_.age as age2_0_, member0_.team_id as team_id4_0_, member0_.username as username3_0_ from member member0_ order by member0_.age asc limit 2 offset 2;
Slice
select
member0_.member_id as member_i1_0_,
member0_.age as age2_0_,
member0_.team_id as team_id4_0_,
member0_.username as username3_0_
from
member member0_
order by
member0_.age asc limit ? offset ?
select member0_.member_id as member_i1_0_, member0_.age as age2_0_, member0_.team_id as team_id4_0_, member0_.username as username3_0_ from member member0_ order by member0_.age asc limit 3 offset 2;
4. 결론
- 두 쿼리를 비교해 보면, Page는 조회 쿼리 이후 전체 데이터 갯수를 한번 더 조회하는 카운트 쿼리가 실행된다.
//Page에만 존재
select
count(member0_.member_id) as col_0_0_
from
member member0_
- Slice는 limit(size)+1 된 값을 가져오는것을 확인할 수 있다.
//Page
limit 2 offset 2;
//Slice
limit 3 offset 2;
| 특징 | Page | Slice |
| 전체 데이터 개수 제공 | 제공 (getTotalElements(), getTotalPages()) | 제공하지 않음 |
| 추가적인 페이징 정보 | 제공 (전체 페이지 수, 전체 데이터 개수 등) | 제공하지 않음 |
| 성능 | 성능이 상대적으로 느림 (두 개의 쿼리 실행: 데이터 조회 + 전체 개수 조회) |
성능이 좋음 (Only 데이터조회 쿼리 실행) |
| 다음 페이지 존재 여부 | 제공 (hasNextPage()) | 제공 (hasNext()) |
| 사용 적합 상황 | - 전체 데이터 개수나 페이지 수가 필요한 경우 - 페이지 하단에 "전체 페이지 수" 또는 "총 데이터 개수" 표시 필요 |
- 성능이 중요한 대용량 데이터 처리 - 무한 스크롤 또는 "더보기" 기능 구현 |
| 단점 | - 쿼리 성능이 느려질 수 있음 (두 개의 쿼리 실행) | - 전체 데이터 수나 페이지 수 정보를 제공하지 않음 |
'Develop > Spring 공략' 카테고리의 다른 글
| [Spring] 카카오맵 API를 활용하여 GeoCoding (0) | 2025.04.25 |
|---|---|
| [Spring] 카카오맵 API 사용 초기 세팅 (0) | 2025.04.22 |
| [Kiosk] 트러블슈팅 (0) | 2025.01.21 |
| [Calculator] Lv.2 트러블슈팅 (0) | 2025.01.10 |
| [Calculator] Lv.1 트러블슈팅 (0) | 2025.01.10 |