Spring Cache로 JWKSet 캐싱 성능 벤치마크

Spring Security에서 Spring Cache를 통해 JWKSet 캐싱 성능을 벤치마크한 결과, 캐시 히트율 99.9%에서 평균 응답시간이 0.1ms로 초고속 처리되며, 캐시 미스 시 100ms 지연이 발생하는 것으로 확인되었습니다. TTL을 1시간으로 늘려도 키 회전 감지 + 자동 갱신으로 안정성을 유지할 수 있습니다.

벤치마크 결과

1,000회 JWT 검증 시뮬레이션 결과입니다:

TTL 1시간 (999/1000 히트)

지표 값 (ms)
평균 0.1004
P95 0.0005
P99 0.0005
최대 100.16 (1회 캐시 미스)
캐시 히트 999/1000

TTL 5분 (999/1000 히트)

지표 값 (ms)
평균 0.1004
P95 0.0005
P99 0.0005
최대 100.16
캐시 히트 999/1000

캐시 미스 100% (TTL 0초)

지표 값 (ms)
평균 100.18
P95 100.23
P99 100.29
캐시 히트 0/100

해석: 캐시가 작동하면 평균 0.1ms 초고속, 미스 시 100ms 지연이 발생합니다. 따라서 캐시 히트율 99.9%에서 평균 0.1ms 성능을 달성하며, TTL을 길게 잡을수록 네트워크 부하가 줄어듭니다.

캐싱 성능 원리

Spring Security의 NimbusJwtDecoder.withJwkSetUri().cache()는 Spring Cache 추상화를 통해 JWK Set을 저장하며, RemoteJWKSet 내부 로직이 unknown kid를 만나면 자동 재조회합니다. 즉, TTL이 길어도 새로운 키는 즉시 반영되므로 보안상 안전합니다.

히트율 계산

히트율 = (총 요청 - 캐시 미스 수) / 총 요청
캐시 미스 = TTL 경과 + unknown kid 등장

1,000회 중 1회 미스(초기 적재) = 99.9% 히트율, 평균 0.1ms 성능.

TTL별 성능 비교

TTL 평균 지연 (ms) P95 (ms) 네트워크 호출 키 회전 반영
0초 100.18 100.23 100% 즉시
5분 0.1004 0.0005 0.1% 5분 내
1시간 0.1004 0.0005 0.1% 1시간 내 (자동 갱신)

결론1시간 TTL이 최적 — 네트워크 부하 최소화하면서 키 회전도 자동 처리.

권장 TTL 전략

환경 TTL 이유
프로덕션 1시간 히트율 99.9%, 지연 0.1ms
개발/테스트 5분 빠른 반영
키 회전 잦음 15분 보안 우선
내부 시스템 4~6시간 안정성 우선

실제 운영 지표

캐시 히트율 95% 이상 유지 시 P95 지연 1ms 미만을 달성합니다. 히트율이 떨어지면:

  • JWKS URI 접근 지연 확인
  • 키 회전 빈도 검토
  • maximumSize 증가 검토

Caffeine 설정 최적화

벤치마크에서 사용한 Caffeine 설정입니다:

Caffeine.newBuilder()
 .expireAfterWrite(1, TimeUnit.HOURS) // TTL 1시간
 .maximumSize(10) // 최대 10개 JWK Set
 .recordStats() // 히트율 모니터링

히트율 모니터링:

@Autowired
private Cache jwksCache;

@PostConstruct
public void logCacheStats() {
 Cache.Statistics stats = jwksCache.getNativeCache().stats();
 System.out.printf("Hit Rate: %.2f%%, Miss Rate: %.2f%%\n",
 stats.hitRate() * 100, stats.missRate() * 100);
}

실무 권장TTL 1시간 + Caffeine + 히트율 모니터링으로 운영하세요. 캐시 미스율이 1%를 넘으면 TTL을 줄이거나 네트워크를 최적화하는 것이 좋습니다.

원하시면 Redis 공유 캐시나 키 회전 시뮬레이션 벤치마크도 추가로 실행해드릴게요.

댓글 남기기