<aside> <img src="/icons/reorder_gray.svg" alt="/icons/reorder_gray.svg" width="40px" />

목차


</aside>

1. 문제 상황


<aside> ⚠️

문제상황


경매 메인 화면에서 호출되는 /api/v2/auctions/overview API는

추천 옥션 + 일반 옥션 목록을 함께 반환하는 통합 API였다.

부하 테스트 결과, 다음 문제가 발생했다:

2. 원인 분석


<aside> 📌

원인


원인 항목 상세 내용
추천 경매 ID는 Redis에 있으나 상세 정보는 DB에서 조회 → 추천 경매 ID는 빠르게 불러오지만, AuctionListItem 전체 정보는 다시 RDB에서 조회해야 했음
반복적인 currentPrice, bidCount 조회 각 경매마다 Redis에서 현재 가격과 입찰 수를 개별 조회 → N+1 성격의 Redis 요청 발생
정렬 + 페이징 + 추천 구분 로직 복잡 추천 목록과 일반 목록을 구분하여 반환하는 로직이 DB와 Redis를 모두 호출
캐싱 부재 /overview 응답 자체를 캐시하지 않아 매번 모든 조회 로직 수행

</aside>

3. 문제 해결 의사결정


<aside> 🛠

문제해결


해결 방안 설명 최종 결정
추천 경매 ID만 Redis → 상세 정보도 Redis화 고려 AuctionListItem 일부 필드 Redis 저장 검토 보류 (1단계에선 ID만 활용)
currentPrice, bidCount Redis Bulk 처리 N+1 Redis 요청 제거 → Pipeline 사용 고려 ✅ 적용
overview API 자체 결과 캐싱 Group별 추천 결과 TTL 캐싱 → 반복 요청 방어 ✅ 적용
DB 쿼리 조건 최적화 IN (ids) 조건 + 인덱스 확인 ✅ 적용

</aside>

4. 적용


<aside> ✅

적용


추천 목록 조회 로직

// Redis Sorted Set → 추천 Auction ID 상위 10개 조회
Set<String> redisIds = recommendRedisRepository.findTopAuctionIds(groupId, 10);
List<Long> recommendedIds = redisIds.stream().map(Long::valueOf).toList();

Redis 현재가격 & 입찰수 처리

// 각 auctionSeq에 대해 Redis 조회 (가능한 경우 pipeline 또는 캐시 로딩)
auctionList.forEach(a -> {
    Long price = auctionRedisRepository.findCurrentPrice(a.getAuctionSeq());
    Long bids = auctionRedisRepository.findBidCount(a.getAuctionSeq());
    a.updateBidInfo(price, bids);
});

DB 조회 방식 개선

// AuctionListItem은 커스터마이징된 Projection으로 ID 기반 조회
auctionRepository.findListItemsByIds(recommendedIds);

캐싱 전략

// overview API 자체 결과는 캐싱하지 않되,
// 추천 대상 경매 목록만 Redis TTL 적용 (5분)

</aside>

5. 결과