트러블슈팅

Redis write-back 구조에서 벌크 업데이트 적용하기

sudaruuu 2026. 3. 20. 17:30

2026.03.20 - [분류 전체보기] - Redis write-back 구조에서 스케줄러와 벌크 처리 개념 혼동

 

Redis write-back 구조에서 스케줄러와 벌크 처리 개념 혼동

문제 상황리뷰 좋아요 기능에서 DB 부하를 줄이기 위해Redis에 좋아요 값을 누적한 뒤,스케줄러를 통해 일정 주기로 DB에 반영하는 write-back 구조를 적용하였다. 이 과정에서Redis에 누적된 데이터를

sudaruuu.tistory.com

 

이전 글에서

write-back과 벌크 처리의 차이를 정리하며
두 개념이 서로 다른 역할을 가진다는 것을 이해하였다.

  • write-back → DB 반영 시점을 제어하는 전략
  • bulk 처리 → DB 처리 효율을 개선하는 방식

이번에는 이 개념을 실제 코드에 적용해보았다.


기존 구조

기존에는 Redis에 좋아요 값을 누적한 뒤
스케줄러를 통해 DB에 반영하는 구조를 사용하고 있었다.

하지만 DB 반영 로직은 아래와 같이
for문을 통해 개별적으로 처리되고 있었다.

for (Map.Entry<Object, Object> entry : entries.entrySet()) {
    Review review = reviewRepository.findById(reviewId);
    review.applyLikeDelta(delta);
}

 

이 방식은

  • 데이터가 많아질수록 DB 호출 횟수가 증가하고
  • 성능 저하로 이어질 수 있는 구조였다.

개선 목표

DB 호출 횟수를 줄이기 위해

벌크 업데이트 방식을 적용하였다.

 

즉,

  • N번의 update 쿼리를 실행하는 구조를
  • 1번의 벌크 update 쿼리로 처리하도록 개선하였다.

적용 과정

1. DTO 생성

벌크 처리를 위해

리뷰 ID와 좋아요 증감값을 담는 DTO를 생성하였다.

@Getter
@AllArgsConstructor
public class ReviewLikeDelta {

    private Long reviewId;
    private Long delta;
}

2. Redis 데이터 → 리스트 변환

Redis에 누적된 데이터를 조회한 뒤

벌크 처리를 위해 리스트 형태로 변환하였다.

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));
}

3. 벌크 업데이트 적용

변환된 리스트를 기반으로

DB에 한 번에 반영하는 벌크 업데이트를 수행하였다.

reviewBulkRepository.bulkUpdateLikeCount(deltas);

적용 결과

기존 방식

  • for문 기반 개별 업데이트
  • DB 호출 횟수 = N번

개선 방식

  • 벌크 업데이트 적용
  • DB 호출 횟수 = 1번

즉,

여러 번 DB에 요청하던 구조를
한 번의 요청으로 처리하도록 변경하여
DB 접근 횟수를 줄이고 성능을 개선할 수 있었다.


정리

이번 작업을 통해

개념으로 이해했던 내용을 실제 코드에 적용해보면서

다음과 같은 점을 확실히 체감할 수 있었다.

  • write-back은 DB 반영 타이밍을 제어하는 전략
  • bulk는 DB 처리 방식을 최적화하는 방법

두 방식을 함께 적용하면

더 효율적인 구조를 만들 수 있다.


⭐ 한 줄 정리

개념으로 이해한 bulk 처리를 실제 코드에 적용하여 DB 호출을 최적화하였다.