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-backDB 반영 시점을 제어하는 전략이고,

벌크 업데이트DB 처리 효율을 높이는 방식이라는 점을 실제 코드에 적용하며 명확히 이해할 수 있었다.


2️⃣

✏️ Keep 코드