[Spring] 페이징 성능 개선하기 3-2. 첫 페이지 조회 결과 캐시하기
3-2. 첫 페이지 조회 결과 캐시하기
처음 검색 시 조회된 count 결과를 응답 결과로 내려주어 JS에서 이를 캐싱하고 매 페이징 버튼마다 count 결과를 함께 내려주는 것이다.
Repository에서는 요청에 넘어온 항목 중 캐싱된 count 값이 있으면 이를 재사용하고, 없으면 count 쿼리를 수행한다.
- 첫 1페이지 요청 시 count 쿼리를 날려서 totalCount를 가져온다.
- 2페이지 이상 요청 시 JS에서 캐싱한 totalCount를 같이 보내서 count 쿼리를 날리지 않고 기존의 totalCount를 같이 보내서 count 쿼리를 날리지 않는다.
이 방식은 다음과 같은 상황에서 도움이 된다.
- 조회 요청이 검색 버튼과 페이지 버튼 모두에서 골고루 발생하고
- 실시간으로 데이터가 적재되지 않고, 마감된 데이터를 사용할 경우
물론 JS에서 캐싱하고 있기 때문에 브라우저를 새로고침하게 되면 count는 다시 초기화가 되어 첫 조회시 다시 쿼리가 수행되게 된다.
3-2-1. 구현 코드
기존 페이징 쿼리는 동일하다.
public Page<BookPaginationDto> paginationCount(Pageable pageable, String name) {
JPQLQuery<BookPaginationDto> query = querydsl().applyPagination(pageable,
queryFactory
.select(Projections.fields(BookPaginationDto.class,
book.id.as("bookId"),
book.name,
book.bookNo,
book.bookType
))
.from(book)
.where(
book.name.like(name + "%")
)
.orderBy(book.id.desc()));
List<BookPaginationDto> items = query.fetch(); // 데이터 조회
long totalCount = query.fetchCount(); // 전체 count
return new PageImpl<>(items, pageable, totalCount);
}
private Querydsl querydsl() {
return Objects.requireNonNull(getQuerydsl());
}
검색 / 페이징 버튼 클릭시 cache 된 count를 사용하도록 개선하기 위해서는 다음의 코드가 추가되어야 한다.
- 프론트 영역에서 넘겨준 count 값이 요청 필드에 포함시킨다.
- Repository에서는 해당 count 값이 있을 경우엔 그대로 페이징 결과에 포함시키고, 없으면 실제 count 쿼리를 실행한다.
public Page<BookPaginationDto> paginationCountCache(Long cachedCount, Pageable pageable, String name) {
// cacheCount는 프론트 영역에서 넘겨준 count 값이다.
JPQLQuery<BookPaginationDto> query = querydsl().applyPagination(pageable,
queryFactory
.select(Projections.fields(BookPaginationDto.class,
book.id.as("bookId"),
book.name,
book.bookNo,
book.bookType
))
.from(book)
.where(
book.name.like(name + "%")
)
.orderBy(book.id.desc()));
List<BookPaginationDto> elements = query.fetch(); // 데이터 조회
long totalCount = cachedCount != null ? cachedCount : query.fetchCount(); // 전체 count: cacheCount가 없으면 실제 count 쿼리를 수행시킨다.
return new PageImpl<>(elements, pageable, totalCount);
}
private Querydsl querydsl() {
return Objects.requireNonNull(getQuerydsl());
}
3-2-2. 결론
한번 조회된 동일 조건의 count에서는 클라이언트 영역에서 저장 후 요청시마다 재사용하는 방식을 사용하면 추가 쿼리 요청이 최소화된다.
단점은
- 첫번째 페이지 조회가 대부분일 경우 효과가 없다.
- 실시간으로 데이터 수정이 필요해서 페이지 버튼 반영이 필요한 경우 사용할 수 없다.
결국 새로고침(또는 버튼 클릭을 통한 페이지 이동)을 하기 전까지 실시간성이 떨어진다.
출처
https://jojoldu.tistory.com/531
'web > Spring' 카테고리의 다른 글
[Spring] 도메인 객체 검증하는 방법 -> Validation (0) | 2022.11.18 |
---|---|
[Spring] MapStruct - Entity와 DTO 매핑하기 (0) | 2022.11.07 |
[Spring] 페이징 성능 개선하기 3-1. 검색 버튼 사용시 페이지 건수 고정하기 (0) | 2022.07.20 |
[Spring] 페이징 성능 개선하기 2. 커버링 인덱스 사용하기 (0) | 2022.07.19 |
[Spring] 페이징 성능 개선하기 1. No Offset 사용하기 (0) | 2022.07.18 |
댓글 개