문제 상황
리뷰 좋아요 기능에서 DB 부하를 줄이기 위해
Redis에 좋아요 값을 누적한 뒤, 스케줄러를 통해 일정 주기로 DB에 반영하는 구조를 적용하였다.
이 방식은 사용자 요청 시 DB를 직접 업데이트하지 않기 때문에
응답 속도를 빠르게 만들고 DB 부하를 줄일 수 있다는 장점이 있다.
하지만 스케줄러 주기를 60초로 설정하면서 다음과 같은 고민이 생겼다.
- 주기 시간을 어느정도로 정하는 것이 좋을까?
- 데이터가 많아지면 성능 문제가 발생하지는 않을까?
즉, 스케줄러 주기와 처리 방식이 성능에 어떤 영향을 미치는지 고민하게 되었다.
개념 이해
1. JPA
JPA는 자바 객체를 DB에 저장하고 조회할 수 있도록 도와주는 기술이다.
다만 내부적으로는 엔티티 단위로 동작하기 때문에
데이터를 한 건씩 처리하는 방식에 가깝다.
즉, 대량 데이터를 한 번에 처리하는 데에는
최적화된 방식이라고 보기는 어렵다.
2. 벌크 인서트 vs 벌크 업데이트
벌크 인서트(Bulk Insert)
- 여러 데이터를 한 번에 DB에 저장하는 방식
- DB와의 통신 횟수를 줄여 성능을 개선할 수 있다.
벌크 업데이트(Bulk Update)
- 기존 데이터를 한 번에 수정하는 방식
- 대량 데이터 변경 시 DB 처리 효율을 높일 수 있다.
현재 좋아요 기능은 새로운 데이터를 생성하는 구조가 아니라
기존 likeCount 값을 증가시키는 방식이기 때문에,
벌크 인서트가 아니라 벌크 업데이트 개념에 더 가깝다고 판단했다.
현재 구현 방식
현재 구조는 다음과 같다.
1. 사용자 요청 시 Redis에서 좋아요 값을 increment 방식으로 누적
2. 스케줄러가 60초마다 실행되어 Redis 데이터를 조회
3. 반복문을 통해 각 리뷰를 조회하고 likeCount를 반영
public void unlikeReview(Long reviewId) {
...
.increment(REVIEW_LIKE_KEY, String.valueOf(reviewId), -1);
}
for (Map.Entry<Object, Object> entry : entries.entrySet()) {
Review review = reviewRepository.findById(reviewId).orElseThrow(...);
review.applyLikeDelta(delta);
}
이 방식은 데이터를 모아서 처리한다는 점에서
벌크 처리처럼 보일 수 있다.
하지만 실제로는
- 엔티티를 하나씩 조회하고
- 각각 update 쿼리가 실행되는 구조이기 때문에
엄밀히 말하면 진짜 벌크 업데이트 방식은 아니다.
고민한 점
스케줄러 주기 설정은 성능에 직접적인 영향을 준다.
1.주기가 너무 긴 경우
- Redis에 데이터가 많이 쌓임
- 한 번에 처리해야 하는 데이터 양 증가
- DB update 부담 증가
- JPA 구조상 성능 저하 가능성
2. 주기가 너무 짧은 경우
- DB 반영이 너무 자주 발생
- DB 부하 증가
- write-back 구조의 장점 감소
즉,
주기가 너무 짧아도 문제이고, 너무 길어도 문제인 상황이다.
해결 방향
현재는 중간 지점으로 60초 주기를 선택하였다.
또한 다음과 같은 이유로
아직 벌크 업데이트 방식은 적용하지 않았다.
- 현재 트래픽 규모가 크지 않음
- 구조가 단순하여 구현과 테스트가 쉬움
- 먼저 안정적으로 동작하는지 확인하는 것이 중요
즉,
복잡한 최적화보다 안정적인 구조를 먼저 확보하는 것이 우선이라고 판단하였다.
정리
Redis write-back 구조에서는
스케줄러 주기와 데이터 처리 방식이 성능에 큰 영향을 미친다.
특히 JPA는 대량 데이터를 한 번에 처리하는 데 한계가 있기 때문에,
데이터 누적량, 처리 방식(벌크 여부), 주기 설정을 함께 고려하는 것이 중요하다.
느낀 점
처음에는 단순히 DB 부하를 줄이기 위한 구조로 시작했지만,
구현을 진행하면서 성능에 영향을 주는 다양한 요소를 함께 고려하게 되었다.
특히,
- 데이터가 얼마나 쌓이는지
- 한 번에 처리할 수 있는 양은 어느 정도인지
- JPA의 처리 방식에는 어떤 한계가 있는지
를 고민하면서,
성능 개선은 단순히 기술을 적용하는 것이 아니라
전체 흐름과 트레이드오프를 함께 고려하는 과정이라는 것을 느꼈다.
'트러블슈팅' 카테고리의 다른 글
| Redis write-back 구조에서 데이터 유실 문제 (0) | 2026.03.19 |
|---|---|
| 리뷰 개수 조회 성능 개선 및 동시성 문제 해결 (0) | 2026.03.19 |
| 캐시 적용 후 데이터 정합성 문제 해결 (CacheEvict 적용) (0) | 2026.03.18 |
| 캐시를 적용했는데 왜 첫 조회는 느릴까? (0) | 2026.03.18 |
| 리뷰 좋아요 기능의 DB 직접 반영 구조를 Redis write-back 방식으로 개선한 과정 (0) | 2026.03.18 |