Skip to content

[Feature] /questions/today 집계 캐시 적용 및 캐시 스탬피드 방지#70

Merged
qkrcodus merged 2 commits intodevfrom
feature/today-question-cache-stampede
Jan 16, 2026
Merged

[Feature] /questions/today 집계 캐시 적용 및 캐시 스탬피드 방지#70
qkrcodus merged 2 commits intodevfrom
feature/today-question-cache-stampede

Conversation

@qkrcodus
Copy link
Collaborator

적용

🔗 Issue Link

#69

🎯 What I Did

  • 캐시 스탬피드 방지를 위해 sync=true 옵션 및 pre-warm 적용
  • 투표 통계/댓글 수 집계 데이터에 짧은 TTL 캐싱 추가
  • 데이터 성격별(불변/집계/개인화) 캐싱 전략 분리

@qkrcodus qkrcodus self-assigned this Jan 16, 2026
@qkrcodus qkrcodus added the enhancement New feature or request label Jan 16, 2026
@qkrcodus qkrcodus linked an issue Jan 16, 2026 that may be closed by this pull request
1 task
@gemini-code-assist
Copy link

Summary of Changes

Hello @qkrcodus, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 /questions/today 엔드포인트의 성능과 안정성을 향상시키기 위해 캐싱 메커니즘을 구현합니다. 투표 통계 및 댓글 수와 같은 집계 데이터에 짧은 TTL을 가진 캐시를 도입하여 데이터베이스 부하를 줄입니다. 또한, sync=true 옵션을 사용하여 캐시 스탬피드를 방지하고, 애플리케이션 시작 시 캐시를 미리 채워 초기 부하를 완화함으로써 동시성 환경에서의 효율적인 데이터 처리를 목표로 합니다.

Highlights

  • 캐시 적용: /questions/today 엔드포인트에 집계 데이터 캐싱을 적용했습니다.
  • 캐시 스탬피드 방지: sync=true 옵션과 애플리케이션 시작 시 캐시를 미리 채우는 pre-warm 전략을 통해 캐시 스탬피드를 방지했습니다.
  • 짧은 TTL 캐싱: 투표 통계(5초) 및 댓글 수(10초)와 같은 집계 데이터에 짧은 Time-To-Live(TTL) 캐싱을 추가했습니다.
  • 캐싱 전략 분리: 데이터 성격(불변/집계/개인화)에 따라 캐싱 전략을 분리하여 효율성을 높였습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@claude
Copy link

claude bot commented Jan 16, 2026

PR 리뷰

캐시 스탬피드 방지를 위한 sync=true 적용과 집계 데이터 캐싱 전략이 잘 구현되었습니다. 다만 몇 가지 개선이 필요한 부분이 있습니다.

P2 (적극적으로 고려해주세요)

  • LocalCacheConfig.java:32-42 - 생성자에서 CacheManager를 직접 생성하고 있어 Spring의 빈 생명주기 관리와 충돌할 수 있습니다. @Bean 메서드에서 직접 생성하도록 변경하거나, 생성자를 제거하고 cacheManager 필드를 final이 아닌 방식으로 주입받는 것이 좋습니다.

  • LocalCacheConfig.java:3 - java.util.Objects import가 사용되지 않습니다.

  • LocalCacheConfig.java:49-56, 62-69 - 스케줄러가 전체 캐시를 clear()하는 방식은 TTL 기반 만료와 다르게 동작합니다. 특정 질문의 통계만 조회했어도 모든 questionId의 캐시가 삭제되므로 비효율적입니다. Caffeine 같은 TTL 지원 캐시 라이브러리 사용을 고려하거나, 최소한 주석에 이 동작 방식을 명시해주세요.

P3 (웬만하면 반영해주세요)

  • CacheWarmupRunner.java:25 - pre-warm 실패 시 애플리케이션 구동은 계속되지만, 실패 원인(예: 오늘의 질문 미등록)을 로그에 상세히 남기면 디버깅에 도움이 됩니다. 현재는 e.getMessage()만 출력합니다.

  • TodayQuestionCacheService.java:99-102, 113-116 - 새로 추가된 캐시 메서드들에 대한 단위 테스트가 누락되었습니다. sync=true 동작과 캐시 hit/miss를 검증하는 테스트 추가를 권장합니다.

  • QuestionService.java:78-84 - 투표 통계와 댓글 수의 TTL이 다른데(5초 vs 10초), 이 차이에 대한 근거나 주석 설명이 있으면 좋겠습니다.

P4 (반영해도 좋고 넘어가도 좋습니다)

  • TodayQuestionCacheServiceTest.java:31-33 - 테스트 포맷팅이 전체 파일에 걸쳐 변경되었는데(인덴트 2칸), 이 변경이 PR의 핵심 내용과 무관하여 diff를 읽기 어렵게 만듭니다.

  • TodayQuestionCacheServiceTest.java:148 - 기댓값이 3에서 4로 변경되었는데, setUp()에서 호출되는 mock 설정 때문인 것으로 보입니다. 주석으로 이유를 명시하면 좋겠습니다.


전반적으로 캐시 전략이 명확하고 sync=true 적용도 적절합니다. P2 항목들만 반영하면 안정적인 캐싱 구조가 될 것 같습니다.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

이번 PR은 오늘의 질문 집계 데이터에 캐시를 적용하고 캐시 스탬피드를 방지하는 중요한 개선을 포함하고 있습니다. sync=true 옵션과 pre-warming을 통한 캐시 스탬피드 방지, 데이터 성격에 따른 캐싱 전략 분리 등 좋은 접근 방식을 사용하셨습니다. 다만, 몇 가지 개선할 점이 보입니다. 스케줄러를 이용한 TTL 구현 방식은 확장성 측면에서 문제가 될 수 있으며, 캐시 pre-warm 로직의 예외 처리와 테스트 코드의 정확성에 대한 검토가 필요합니다. 자세한 내용은 아래 주석을 참고해주세요.

 - CacheWarmupRunner: Exception → BusinessException으로 구체화
  - LocalCacheConfig: 생성자 제거, @bean에서 CacheManager 직접 생성
  - LocalCacheConfig: cache.clear() 동작 방식 주석 추가
  - TodayQuestionCacheServiceTest: clearInvocations() 추가로 테스트 격리 개선   # Please enter the commit message for your changes. Lines starting
@claude
Copy link

claude bot commented Jan 16, 2026

PR #70 코드 리뷰: /questions/today 집계 캐시 적용 및 캐시 스탬피드 방지

긍정적인 부분

sync=true로 캐시 스탬피드를 방지하고 pre-warm을 통해 초기 부하를 줄인 점이 좋습니다. 집계 데이터를 단기 캐싱하여 조회 부하를 분산시킨 접근도 합리적입니다.


P2 (적극적으로 고려해주세요)

  • LocalCacheConfig.java:47-50 - cache.clear()는 해당 캐시의 모든 키를 삭제합니다. 현재는 단일 질문만 캐싱하지만, 주석에서 "추후 여러 질문을 캐싱할 경우 Caffeine 전환 필요"라고 명시했다면 초기부터 Caffeine으로 구성하는 것이 낫습니다. clear() 방식은 다른 질문 ID가 추가될 때 의도치 않은 전체 캐시 삭제를 유발합니다.

  • LocalCacheConfig.java:26 - cacheManager 필드를 인스턴스 변수로 저장하지만, @Bean 메서드에서 할당하는 방식은 Spring의 빈 생명주기와 맞지 않습니다. 스케줄러 메서드에서는 @Autowired로 주입받거나 생성자 주입을 사용해야 합니다. 현재 방식은 빈 초기화 순서에 따라 NPE가 발생할 수 있습니다.

  • TodayQuestionCacheService.java:99 - getVoteStatsCached()의 javadoc에 "스케줄러에서 주기적 evict"라고 명시되어 있으나, 실제로는 LocalCacheConfig에 스케줄러가 있습니다. 캐시 TTL 정책이 설정 클래스에 분산되어 있어 유지보수 시 혼란을 줄 수 있습니다. 캐시 evict 로직을 서비스 클래스로 옮기거나, 설정 클래스 참조를 javadoc에 명시하는 것을 권장합니다.


P3 (웬만하면 반영해주세요)

  • CacheWarmupRunner.java:26 - pre-warm 실패 시 warn 로그만 남기고 넘어가는데, 이 경우 서버가 구동되자마자 대량의 동시 요청이 들어오면 캐시 스탬피드가 발생할 수 있습니다. 실패 시 재시도 로직이나 헬스체크 연동을 고려해보세요.

  • LocalCacheConfig.java:43-51, 53-62 - VoteStats(5초), CommentCount(10초) TTL이 하드코딩되어 있습니다. application.yml에서 설정 가능하도록 @Value로 외부화하면 환경별 튜닝이 용이합니다.


P4 (반영해도 좋고 넘어가도 좋습니다)

  • LocalCacheConfig.java:14 - javadoc 첫 줄이 줄바꿈 없이 나열되어 있어 가독성이 떨어집니다. 각 설명을 개행으로 구분하면 좋습니다.

  • TodayQuestionCacheServiceTest.java:33 - clearInvocations(questionRepository) 주석이 "CacheWarmupRunner 등 이전 호출 기록 초기화"인데, 테스트 격리를 위한 것이므로 "테스트 격리를 위한 mock 호출 기록 초기화"가 더 명확합니다.

@qkrcodus qkrcodus merged commit 659e1d0 into dev Jan 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] /questions/today 집계 캐시 적용 및 캐시 스탬피드 방지

1 participant