Skip to content

[Fix] McpRateLimiter의 windows 맵이 TTL 없이 무한정 커지는 문제 수정 #292

Description

@kangcheolung

📌 Description

McpRateLimiter(backend/src/main/java/com/opensource/docgrid/domain/mcp/security/McpRateLimiter.java)의
windows 맵(ConcurrentHashMap<String, Window>, key = "userId:toolName")은 한 번 등록된 조합을
절대 remove()하지 않는다. 60초가 지나면 Window.count는 다음 호출 때 리셋되지만, Window 객체와
그 키는 서버가 재시작되기 전까지 맵에 영구히 남는다.

🔍 문제 상황

사용자 수 × 도구 종류(3종) 조합만큼 맵이 계속 커지기만 하고 절대 줄어들지 않는 구조 — 흔히 말하는
메모리 누수 패턴이다.

  • #117 설계 문서(docs/design/kangcheolung-#117-rate-limiting-output-sanitization.md)의
    "남은 이슈"에 이미 알려진 한계로 기록돼 있음: "TTL 기반 정리(eviction)는 이번 MVP 범위에서
    하지 않음, 필요성이 생기면 별도 검토."
  • MVP 단계라 사용자 수가 적어 Window 객체(필드 2개, 몇십 바이트) 수준의 메모리 영향은
    현재는 무시할 만함. 사용자가 수만 단위로 늘면 결국 문제가 될 수 있음.

✅ To-do

  • ConcurrentHashMap → Caffeine 캐시(expireAfterAccess 등 TTL 옵션)로 교체
  • 교체 후 McpRateLimiterTest의 동시성 테스트(50스레드, 윈도우 만료 경계 레이스)가 여전히 통과하는지 확인
  • 로컬 서버 기동 후 MCP 토큰 발급 → Claude에 연동해 rate limit 동작이 기존과 동일한지 실측 확인

✅ 완료 기준

  • 일정 시간(TTL) 이상 호출이 없는 사용자·도구 조합은 맵/캐시에서 자동 제거된다.
  • 기존 rate limit 정확성(분당 N회 제한)이 그대로 유지된다.
  • ./backend/gradlew -p backend test 전체 통과.

📒 기타

  • #117 설계 문서에 이미 명시된 한계를 재확인·정리한 것. 신규 발견 아님.
  • 관련 메모리: project_mcp_rate_limiter_unbounded_map.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions