AI Briefing

Micrometer 객체 증가로 발생한 메모리 문제 회고

·2025.05.29 00:00

Spring Boot 3의 LoadBalancer Micrometer 태그가 쌓여 Old 영역 메모리가 증가했다.

최대할인가 구조를 JDK 21, Spring Boot 3.2.1, CompletableFuture 기반의 병렬 처리로 개편하면서 예상치 못한 메모리 문제가 드러났다. 쿠폰 API를 내부 서비스로 이관한 뒤 상품, 회원, 기획전 정보를 각각 조회하는 호출이 늘었고, 그 과정에서 Micrometer 관련 객체가 계속 누적됐다.

핵심 증상은 Meter$Id, Tag, **ImmutableTag**가 GC 이후에도 Old 영역에 남아 계속 증가한 점이었다. /actuator/metrics/http.client.requests 에서는 URI가 {} 형태로 정규화되어 보였지만, 실제로는 spring.cloud.loadbalancer.stats.micrometer.enabled: true 설정 때문에 LoadBalancer 계층에서 정규화되지 않은 URI가 태그로 수집되며 서로 다른 Meter가 계속 생성되고 있었다.

원인 검증 과정에서는 다른 태그인 status_code, host, error도 확인했지만 availableTags는 매 요청 동일하게 유지돼 제외됐다. 결국 LoadBalancer, Feign, Resilience4j 메트릭 수집을 application.yml에서 선택적으로 끄고, 필요 시 @SpringBootApplication에서 Micrometer 관련 자동 설정까지 제외하는 방식으로 객체 생성을 차단했다.

이후에는 메모리 증가 현상을 추적하다가 GC 전략도 함께 조정했다. Micrometer 객체가 계속 쌓이면서 ZGC의 컨커런트 수거만으로는 Old 영역 증가와 CPU 부하를 감당하기 어려워 G1GC로 임시 전환했지만, Mixed GC가 돌더라도 Old 영역이 충분히 줄지 않아 힙 사용률이 점진적으로 상승했다.

jmap -histo:live로 강제 Full GC를 수행했을 때는 Old 영역 객체 수가 유의미하게 줄었고, jmap -histo에서도 시간이 지나며 일부 객체 수가 감소해 보였다. 이를 통해 누수보다는 G1GC의 수거 강도 부족에 가까운 현상으로 판단했고, 결국 기존의 ZGC로 복귀했다.

복귀 시에는 -XX:+UseZGC, -XX:ZUncommitDelay=60, -XX:ConcGCThreads=4, -Xms6g -Xmx10g 설정을 적용했다. 이후 모니터링에서는 Heap 사용률이 안정적이고 평탄하게 유지됐고, TPS가 높고 객체 생성이 많은 환경에서는 ZGC가 더 적합하다는 결론에 도달했다.

정리하면 다음 두 가지가 핵심이었다.

  • Spring Boot 3.x + LoadBalancer Micrometer 설정이 PathVariable 기반 호출에서 Meter 객체를 과도하게 늘렸다.
  • G1GC는 해당 패턴의 객체를 충분히 빨리 수거하지 못했고, ZGC가 더 안정적인 운영 선택이었다.

이 요약은 원문 이해를 돕기 위한 큐레이션입니다. 저작권은 원저작자에게 있으며, 정확한 내용과 맥락은 원문을 확인하세요.

요약 오류, 출처 표기 문제, 삭제 요청은 문의 · 건의로 알려주세요.