Skip to content

userId별 애플리케이션 레벨 레이트리밋 (인증 사용자별 정밀 quota) #339

Description

@m-a-king

  • nginx IP별 레이트리밋(PR nginx IP별 레이트리밋 — 비싼 Gemini 경로 + 전역 2층 #332, 2층: 비싼 경로 piki_llm + 전역 piki_general)이 머지됐지만, IP는 거친 1차 방어다. CGNAT·공유망 오탐과 IP 변경 우회 한계로 정밀 제어엔 부적합하다.
  • 비싼 Gemini 경로(위시 등록·이미지 OCR, 토너먼트 link·images)는 전부 인증 필수라, userId 단위로 "기간당 N회" 정밀 quota를 걸어 비용·공정성을 정확히 제어할 수 있다.
  • nginx 429는 GlobalExceptionHandler를 안 거쳐 ApiResponseBody를 고정 JSON으로 흉내낼 뿐이다. 앱 레이어면 진짜 ApiResponseBody.fail로 일관 응답을 내려보낼 수 있다.

무엇을

  • 인증 사용자(userId)별 비싼 경로 요청 횟수를 기간 윈도우로 제한한다. 한도·윈도우 값은 구현 시 결정한다.
  • 저장소는 이미 가동 중인 Redis를 활용한다. 구현 방식(Bucket4j(+redis) / 직접 INCR+EXPIRE 등)은 설계 단계에서 선택한다.
  • 적용 지점: 인터셉터/필터에서 JWT 인증 이후 userId를 추출해 비싼 경로 quota를 검사한다.
  • 초과 시 커스텀 예외(429, HttpMappable) → GlobalExceptionHandler → ApiResponseBody.fail 로 일관 응답한다. Retry-After 헤더를 고려하고, *Api.kt/*ApiExamples 의 429 문서화를 동반한다.
  • nginx IP 2층은 그대로 두고 위에 얹는 보완 레이어다(대체가 아니라 IP=미인증·flood 1차, userId=인증 후 정밀 quota).

참고

Metadata

Metadata

Assignees

Labels

feat외부 가시적 새 기능

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions