#Backend

Spring Boot Startup Time 최적화 : 90초에서 30초까지의 여정(feat. 오픈소스 기여)

Spring Boot Startup Time 최적화 : 90초에서 30초까지의 여정(feat. 오픈소스 기여)
01

Summary

90초에서 30초로! Spring Boot 부팅 속도를 66% 단축한 6단계 최적화 비법

비동기 프로파일링부터 Spring Data 오픈소스 버그 해결까지, 대규모 트래픽 환경의 콜드 스타트를 극복하는 실무 엔지니어링 가이드

본 아티클은 Kubernetes 환경에서 Spring Boot의 느린 스타트업 문제를 타파하기 위해 거쳐 간 심층적인 프로파일링 및 트러블슈팅 과정을 기술합니다. 프레임워크를 블랙박스로 두지 않고 소스 코드 수준에서 동작을 분석하여, 외부 API 병목과 무거운 JPA 초기화 문제를 하나씩 풀어나가는 과정을 담았습니다. 나아가 발견한 프레임워크 자체의 결함을 공식 오픈소스 기여로 해결하며 성능 향상과 생태계 기여를 동시에 완수한 성과를 전합니다.

  • 01Async Profiler의 Wall-clock 모드와 시각화 도구를 활용해 메인 스레드 병목의 명확한 데이터 분석
  • 02클래스 로딩 중 바이트코드 변환 오버헤드를 일으키는 Scavenger Java Agent 제거로 기동 시간 10초 즉시 단축
  • 03EntityManagerFactory 비동기 로딩을 가로막는 Spring Data의 Child Context 이벤트 수신 버그 제보 및 PR 머지 완료
  • 04JPA Repository 프록시 생성을 방해하는 코드 패턴(CrudRepository, 다중 상속) 리팩토링으로 DEFERRED 모드 완벽 적용
  • 05Spring Boot 3의 BACKGROUND 부트스트랩 어노테이션을 활용해 EMF 의존 빈의 메인 스레드 블로킹 해소

RECOMMENDATION

Kubernetes 기반 마이크로서비스 환경에서 스케일아웃 속도 저하로 가용성 위기를 겪고 있거나, Spring Data JPA와 수백 개의 도메인 빈들로 인해 애플리케이션 시작 시 병목이 발생하는 조직의 개발자 및 플랫폼 엔지니어들에게 필독을 권장합니다.

The Problem

Kubernetes 환경에서 Spring Boot 애플리케이션의 느린 스타트업 시간(평균 90초, 최대 130초 이상)으로 인해 HPA 스케일아웃 지연, 크론잡 구동 오버헤드, 스팟 인스턴스 전환 시 서비스 장애 위험 등의 문제가 발생했습니다. 특히 동일한 코드와 이미지임에도 불구하고 인스턴스(Pod)마다 부팅 시간의 편차가 심해 인프라 운영의 안정성을 저해하고 있었습니다.

The Solution

Async Profiler와 BufferingApplicationStartup을 사용하여 메인 스레드의 병목을 분석하고, 외부 API 호출의 비동기화(fire-and-forget), 불필요한 Scavenger Java Agent의 비활성화를 적용했습니다. 또한, EntityManagerFactory(EMF) 비동기 초기화 및 JPA bootstrapMode: DEFERRED 설정 중 발견된 Spring Data의 Feign Client Child Context 관련 버그를 우회하는 커스텀 리스너를 제작하여 오픈소스에 기여하였으며, EMF를 직접 주입받는 빈은 Spring Boot 3의 백그라운드 초기화 기능(@Bean(bootstrap = BACKGROUND))을 적용해 우회했습니다.

The Result

적용 이후 가장 구동이 빨랐던 Pod는 27초 만에 부팅에 성공하여 기존 평균 90초 대비 최대 66%의 부팅 시간 단축 성과를 얻었습니다. 또한 지연 편차가 심해 장애를 유발했던 120초 이상의 극단적인 병목 케이스가 완전히 제거되었으며, 수정 사항은 spring-data-commons v3.5.10 공식 릴리즈에 병합되었습니다.

Trade-off

특정 빈을 백그라운드 스레드에서 기동하게 하면서, 이를 참조하는 다른 빈들에 @Lazy나 ObjectProvider를 설정하고 @DependsOn 구조로 의존성을 인위적으로 설계해야 하는 코드 복잡성 및 휴먼 에러의 리스크가 존재합니다. 또한 다중 인터페이스 상속(Hexagonal Pattern)과 같은 기존의 특정 사내 아키텍처 컨벤션을 최적화를 위해 제거 및 타협해야 했습니다.

03

Key Concepts

Concept · 01

Async Profiler & Flame Graph

JVM 애플리케이션의 성능을 저비용으로 측정하는 샘플링 프로파일러입니다. 시스템의 스레드 상태와 무관하게 모든 스택 트레이스를 일정 주기로 샘플링하여, 전체 실행 시간 기준의 병목 지점을 시각화해 줍니다.

  • 애플리케이션 초기화 시 메인 스레드의 Wall-clock 프로파일링을 실행하여 병목 유발 지점을 타격하는 데 활용되었습니다.
Concept · 02

JPA Bootstrap Mode (DEFERRED)

Spring Data JPA에서 애플리케이션 시작 시점에 모든 Repository Bean을 즉시 초기화하는 대신, EMF 준비 과정과 별개로 Lazy Proxy를 먼저 주입하여 기동 시간을 줄이는 부트스트랩 옵션입니다.

  • 메인 스레드의 블로킹을 막아 EMF 초기화 완료 이전에 다른 빈들이 원활하게 생성될 수 있도록 기능적 다리를 놓았습니다.
Concept · 03

Background Bean Bootstrap

Spring Boot 3 버전부터 공식적으로 지원하며, 메인 스레드가 아닌 백그라운드 전용 스레드 풀에서 특정 빈을 생성 및 초기화할 수 있게 돕는 성능 최적화 기능입니다.

  • EMF를 직접 주입받아 초기 생성 시 DB 테이블을 직접 핸들링하는 무거운 커스텀 퍼블리셔 빈을 비동기로 로딩하는 데 사용되었습니다.