트러블슈팅

조회 성능 개선 2단계 - 캐시(Cache) 적용

sudaruuu 2026. 3. 17. 15:25

2026.03.17 - [Spring 2기 과제] - 조회 API 응답 속도가 느린 이유 분석 (Postman 테스트 기반)

 

조회 API 응답 속도가 느린 이유 분석 (Postman 테스트 기반)

문제 상황 식당 / 메뉴 / 리뷰 조회 API를 구현한 뒤 더미데이터를 `data.sql`로 넣고 Postman을 통해 테스트를 진행하였다.처음에는 단순히 정상 조회 여부만 확인하려 했지만 여러 번 호출하는 과정

sudaruuu.tistory.com

2026.03.17 - [분류 전체보기] - 조회 성능 개선 1단계 - Pageable 적용

 

조회 성능 개선 1단계 - Pageable 적용

2026.03.17 - [Spring 2기 과제] - 조회 API 응답 속도가 느린 이유 분석 (Postman 테스트 기반) 조회 API 응답 속도가 느린 이유 분석 (Postman 테스트 기반)문제 상황 식당 / 메뉴 / 리뷰 조회 API를 구현한 뒤

sudaruuu.tistory.com

 

문제 상황

Pageable을 적용한 이후

조회 API 응답 시간이
약 121ms → 77ms로 개선된 것을 확인하였다.

하지만 여전히 문제가 있었다.

동일한 조회 요청을 반복할 경우에도
매번 DB에 접근이 발생한다는 점이었다.

특히 식당 / 메뉴 / 리뷰 조회처럼
조회 비중이 높은 API의 경우

👉 반복 조회 시 DB 부하가 계속 발생하는 구조였다.


원인 분석

Pageable은

- 조회 데이터 양을 줄이는 데는 효과적이지만
- 반복 조회를 줄여주지는 못한다

즉,

👉 조회량은 줄였지만, 조회 횟수는 그대로였다

이로 인해 동일한 요청이 반복될 경우
DB에 계속 접근하는 비효율이 발생하고 있었다.


해결 과정

반복 조회 시 DB 접근을 줄이기 위해

Spring Cache를 적용하였다.

 

단건 조회

@Cacheable(value = "store", key = "#storeId")
@Transactional(readOnly = true)
public StoreResponse getStore(Long storeId) {
    Store store = findStoreById(storeId);
    return StoreResponse.from(store);
}

 

목록 조회

@Cacheable(value = "stores", key = "#keyword + '-' + #pageable.pageNumber + '-' + #pageable.pageSize")
@Transactional(readOnly = true)
public Page<StoreResponse> getStores(String keyword, Pageable pageable) {
    ...
}

 

데이터 변경 시 캐시 제거

@Caching(evict = {@CacheEvict(value = "stores", allEntries = true), @CacheEvict(value = "store", key = "#storeId")})
public void updateStore(...) {
    ...
}

결과

캐시 적용 후 테스트 결과

단계 응답 시간
기존 121ms
Pageable 77ms
Cache 적용 7ms

 

👉 반복 조회 시 DB 접근 없이
캐시에서 바로 데이터를 반환하면서
응답 속도가 크게 개선되었다.


결론

  • Pageable → 조회량 감소
  • Cache → 반복 조회 제거

👉 두 가지를 함께 적용해야
효과적인 성능 개선이 가능하다는 것을 확인하였다.


다음 문제

캐시 적용 과정에서

👉 DTO 직렬화 오류 발생 (NotSerializableException)


다음 단계

👉 DTO 직렬화 문제 해결 및
👉 대용량 데이터 환경에서 성능 검증 진행