1️⃣
✏️ Keep 코드
// ReviewLikeDelta
@Getter
@AllArgsConstructor
public class ReviewLikeDelta {
private Long reviewId;
private Long delta;
}
// ReviewLikeFlushScheduler
List<ReviewLikeDelta> deltas = new ArrayList<>();
for (Map.Entry<Object, Object> entry : entries.entrySet()) {
Long reviewId = Long.parseLong(entry.getKey().toString());
Long delta = Long.parseLong(entry.getValue().toString());
if (delta == 0L) continue;
deltas.add(new ReviewLikeDelta(reviewId, delta));
}
// ReviewLikeFlushScheduler
reviewBulkRepository.bulkUpdateLikeCount(deltas);
✏️ Keep 하고 싶은 이유
기존에는 Redis에 누적된 리뷰 좋아요 증감값을 스케줄러를 통해 DB에 반영할 때, for문으로 각 리뷰를 하나씩 조회하고 업데이트하는 방식으로 처리하고 있었다.
for (Map.Entry<Object, Object> entry : entries.entrySet()) {
Review review = reviewRepository.findById(reviewId);
review.applyLikeDelta(delta);
}
이 방식은 데이터가 많아질수록 리뷰 개수만큼 DB 접근이 반복적으로 발생하게 되고, 결국 DB 호출 횟수가 증가하여 성능 저하로 이어질 수 있는 구조라는 문제가 있었다.
이를 개선하기 위해 리뷰 ID와 좋아요 증감값을 담는 ReviewLikeDelta DTO를 생성하고, Redis에 누적된 데이터를 리스트 형태로 변환한 뒤 bulkUpdateLikeCount(deltas) 메서드를 통해 한 번의 벌크 업데이트 쿼리로 DB에 반영하도록 변경하였다.
그 결과 기존에는 DB 호출 횟수가 N번 발생하던 구조를, 1번의 벌크 update 쿼리로 처리할 수 있도록 개선할 수 있었다. 이를 통해 불필요한 DB 접근을 줄이고, 대량의 데이터 처리 시 더 효율적인 구조로 개선할 수 있었다.
또한 이 과정을 통해
Redis write-back은 DB 반영 시점을 제어하는 전략이고,
벌크 업데이트는 DB 처리 효율을 높이는 방식이라는 점을 실제 코드에 적용하며 명확히 이해할 수 있었다.
2️⃣
✏️ Keep 코드