Skip to content

fix: Redis TTL 조회 실패 시 rate limit 응답 안정화#663

Merged
dh2906 merged 2 commits into
developfrom
fix/rate-limit-ttl-timeout
Jun 4, 2026
Merged

fix: Redis TTL 조회 실패 시 rate limit 응답 안정화#663
dh2906 merged 2 commits into
developfrom
fix/rate-limit-ttl-timeout

Conversation

@dh2906
Copy link
Copy Markdown
Contributor

@dh2906 dh2906 commented Jun 4, 2026

🔍 개요

  • Rate limit 제한 초과 응답이 Redis TTL 조회 timeout 때문에 500으로 전파될 수 있던 경로를 막습니다.
  • 카운터 증가로 제한 초과가 확인된 뒤에는 TTL 조회가 실패해도 기본 window 시간으로 429 응답을 유지합니다.

🚀 주요 변경 내용

  • 제한 초과 후 남은 시간 조회를 별도 메서드로 분리하고, Redis 조회 실패 시 timeWindowSeconds를 fallback 값으로 사용했습니다.
  • 카운터 증가 자체가 실패한 경우의 기존 fail-open 정책은 유지했습니다.
  • TTL 조회 timeout이 발생해도 TOO_MANY_REQUESTS 응답이 유지되는 단위 테스트를 추가했습니다.

💬 참고 사항

  • 검증 완료: CI=true ./gradlew test --tests '*RateLimitAspectTest'
  • 검증 완료: ./gradlew checkstyleMain
  • 검증 완료: git diff --check
  • push 전 hook에서 IntelliJ formatter, checkstyleMain, compileJava가 통과했습니다.
  • ./gradlew checkstyleTest는 기존 unrelated 테스트 파일의 line length 위반으로 실패합니다.

✅ Checklist (완료 조건)

  • 코드 스타일 가이드 준수
  • 테스트 코드 포함됨
  • Reviewers / Assignees / Labels 지정 완료
  • 보안 및 민감 정보 검증 (API 키, 환경 변수, 개인정보 등)

- 제한 초과 판단 이후 남은 시간 조회가 실패해도 servlet 예외로 전파되지 않도록 기본 window 값으로 대체한다
- 카운터 증가가 성공한 경우에는 제한 초과 상태를 유지해 Redis TTL 조회 장애가 요청 허용으로 바뀌지 않게 한다
- Redis timeout 재현 테스트를 추가해 동일한 500 전파가 재발하지 않도록 한다
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 4, 2026

Review Change Stack

Warning

Review limit reached

@dh2906, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 52 minutes and 17 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d3a56b0d-f00a-422d-96cb-908f86dcbafc

📥 Commits

Reviewing files that changed from the base of the PR and between b77ea84 and 1763c26.

📒 Files selected for processing (1)
  • src/test/java/gg/agit/konect/unit/global/ratelimit/aspect/RateLimitAspectTest.java
📝 Walkthrough

개요

RateLimitAspect에서 rate limit 초과 시 남은 시간을 조회하는 로직을 별도 메서드로 캡슐화하고 실패 시 폴백 처리를 추가했으며, 조회 실패 시나리오를 검증하는 테스트를 추가했습니다.

변경 사항

Rate Limit TTL 조회 복원력

Layer / File(s) 요약
TTL 조회 메서드 추가 및 통합
src/main/java/gg/agit/konect/global/ratelimit/aspect/RateLimitAspect.java
resolveRemainingSeconds(key, timeWindowSeconds) 메서드를 추가하여 Redis TTL 조회를 캡슐화합니다. 조회 결과가 null 또는 음수이거나 예외 발생 시 time window 값으로 폴백하며, 예외 생성 지점에서 이 메서드를 호출하도록 변경합니다.
TTL 조회 실패 시나리오 테스트
src/test/java/gg/agit/konect/unit/global/ratelimit/aspect/RateLimitAspectTest.java
QueryTimeoutException import를 추가하고, Redis TTL 조회에서 timeout 발생 시에도 429 응답을 반환하는 동작을 검증하는 신규 테스트 메서드 throwsRateLimitExceptionWhenRemainingTimeLookupFails()를 작성합니다.

관련 PR

코드 리뷰 난이도

🎯 2 (Simple) | ⏱️ ~12분

마치며

🐰 TTL은 망가져도 괜찮아,
기본값이 우릴 구해줄 테니까!
rate limit의 우산처럼,
언제나 429로 준비됐어! ☂️✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 PR의 주요 변경사항을 명확하게 반영하고 있습니다. Redis TTL 조회 실패 시 rate limit 응답 안정화라는 핵심 목표를 간결하게 표현했습니다.
Description check ✅ Passed PR 설명이 변경사항과 목적을 명확하게 관련지어 설명하고 있습니다. 개요, 주요 변경 내용, 검증 결과, 체크리스트를 포함하고 있어 충분한 맥락을 제공합니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/rate-limit-ttl-timeout

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/test/java/gg/agit/konect/unit/global/ratelimit/aspect/RateLimitAspectTest.java`:
- Around line 133-160: The test throws RateLimit exception but doesn't assert
that the TTL fallback (timeWindowSeconds = 60) is present in the exception
detail; update the assertion inside
throwsRateLimitExceptionWhenRemainingTimeLookupFails to also check the exception
detail message (e.g., call customEx.getDetail() or customEx.getFullMessage())
contains "60" to verify rateLimit.timeWindowSeconds() is used as the fallback
when rateLimitAspect.around fails to read TTL.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 840249dd-753a-4fe7-9308-3e229136e802

📥 Commits

Reviewing files that changed from the base of the PR and between b9d8bdc and b77ea84.

📒 Files selected for processing (2)
  • src/main/java/gg/agit/konect/global/ratelimit/aspect/RateLimitAspect.java
  • src/test/java/gg/agit/konect/unit/global/ratelimit/aspect/RateLimitAspectTest.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: coverage
  • GitHub Check: Code Style Check
  • GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.java

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.java: Java 코드에서 import로 해결할 수 있는 경우 FQCN(Full Qualified Class Name)을 사용하지 않도록 지적한다
JPA/QueryDSL 조회 변경 시 N+1, 잘못된 fetch join, count 쿼리 왜곡, pagination 깨짐, distinct 누락을 확인한다
권한 로직은 관리자 우회, 요청자와 대상자 관계, 클럽/채팅방/공지/일정의 소속 검증이 빠지지 않았는지 확인한다
soft delete, 탈퇴 사용자, 차단/제외 조건, 중복 제거가 필요한 조회에서는 응답에 노출되면 안 되는 데이터가 포함되는지 확인한다
DTO 응답 변경은 기존 클라이언트가 기대하는 필드명, nullability, enum/string 값, 정렬 순서를 깨지 않는지 확인한다
조건이 2개 이상 결합된 비즈니스 규칙, 권한 조건, soft delete 제외, 중복 제거, fallback 우선순위, 대표값 선택, DTO 변환, count 쿼리 분리, fetch join 선택 이유처럼 코드만으로 의도가 숨겨지는 지점에는 주석을 권장한다
단순 생성자 호출, 필드 매핑, 컬렉션 반환, 이름만으로 명확한 분기에는 주석을 요구하지 않는다

Files:

  • src/main/java/gg/agit/konect/global/ratelimit/aspect/RateLimitAspect.java
  • src/test/java/gg/agit/konect/unit/global/ratelimit/aspect/RateLimitAspectTest.java
**/*.{sql,java}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

데이터베이스 변경에서는 마이그레이션 순서, 기존 데이터 호환성, nullable/default 처리, 롤백 난이도, 인덱스 필요성을 확인한다

Files:

  • src/main/java/gg/agit/konect/global/ratelimit/aspect/RateLimitAspect.java
  • src/test/java/gg/agit/konect/unit/global/ratelimit/aspect/RateLimitAspectTest.java
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.

  • 코멘트는 반드시 한국어로 작성한다.
  • 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
  • 각 코멘트 첫 줄에 심각도를 [LEVEL: high|medium|low] 형식으로 반드시 표기한다.
  • 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
  • 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
  • 가능하면 재현 조건 및 실패 시나리오도 포함한다.
  • 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
  • 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
  • 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
  • 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
  • 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.

Files:

  • src/main/java/gg/agit/konect/global/ratelimit/aspect/RateLimitAspect.java
**/*

⚙️ CodeRabbit configuration file

**/*: 공통 리뷰 톤 가이드:

  • 모든 코멘트는 첫 줄에 [LEVEL: ...] 태그를 포함한다.
  • 과장된 표현 없이 사실 기반으로 작성한다.
  • 한 코멘트에는 하나의 이슈만 다룬다.
  • 코드 예시가 필요하면 최소 수정 예시를 제시한다.
  • 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.

Files:

  • src/main/java/gg/agit/konect/global/ratelimit/aspect/RateLimitAspect.java
  • src/test/java/gg/agit/konect/unit/global/ratelimit/aspect/RateLimitAspectTest.java
🔇 Additional comments (1)
src/main/java/gg/agit/konect/global/ratelimit/aspect/RateLimitAspect.java (1)

74-74: LGTM!

Also applies to: 128-140

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 4, 2026

🧪 JaCoCo Coverage Report (Changed Files)

Summary

  • Overall Coverage: 78.6% ✅
  • Covered Lines: 44 / 56
  • Changed Files: 1

Coverage by File

Class Coverage Lines Status
RateLimitAspect
gg.agit.konect.global.ratelimit.aspect
78.6% 44/56

📊 View Workflow Run

- 리뷰 피드백에 따라 TTL 조회 실패 시 기본 window 값이 예외 detail에 반영되는지 확인한다
- 429 에러 코드만 검증하던 테스트를 보강해 fallback 시간이 응답 메시지에서 누락되는 회귀를 막는다
@dh2906 dh2906 self-assigned this Jun 4, 2026
@dh2906 dh2906 merged commit 49cbf7f into develop Jun 4, 2026
5 checks passed
@dh2906 dh2906 deleted the fix/rate-limit-ttl-timeout branch June 4, 2026 03:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant