Spring Boot Cold Start 문제해결 k8s startup probe 웜업 구축 - 1탄

Choi Wang Gyu·2025년 5월 22일

🔍 문제 상황

운영 배포를 자주 하다 보면, 배포 후 사이트에 접속했을 때 첫 데이터가 늦게 나오는 현상이 종종 있었다.
"문제가 있나?" 싶은 조바심이 생기고, 특히 K8s 스케일아웃 환경에서는

  • 사용자가 느려서 새로고침 → 다른 서버에 요청
  • 또 느린 응답
    이런 구조가 반복되면 유저 이탈로 이어질 수 있다.

구글 연구(2018)에 따르면, 페이지 로딩 시간이 1초에서 5초로 늘어나면 이탈률이 90% 이상 증가한다.


원인 분석

첫 요청 시 느려지는 원인을 분석한 결과, 콜드 스타트 현상 때문이다

1. JVM의 Lazy 클래스 로딩

클래스는 실제 호출될 때 JVM이 메모리에 로드함.
따라서 최초 요청 시 Controller, DTO, Entity 등이 늦게 로딩됨 → 지연 발생.

2. Spring의 Lazy Bean 초기화

기본은 Eager 초기화지만, @Lazy 또는 spring.main.lazy-initialization=true 설정 시 요청이 올 때까지 초기화를 미룸.

3. 외부 리소스 초기화 지연

JPA EntityManager, Redis, Kafka, 외부 API 등은 요청 시점까지 연결이 지연됨.


🛠 해결 방법: 웜업 + startupProbe 활용

서버가 "띄워졌다"와 "요청을 받아도 되는 상태"는 다르다.
Kubernetes의 StartupProbe를 활용해 "진짜 준비된 서버"만 트래픽을 받게 한다.

Warmup 동작 흐름 요약

[Spring Boot 시작]
    ↓
[ApplicationReadyEvent 발생]
    ↓
[Warmup 실행]
    ↓
[모든 웜업 성공 → /health/startup = 200 OK]
    ↓
[Kubernetes startupProbe 통과 → 트래픽 수신 시작]

🚀 결과

  • 60% 이상의 초기 응답 속도 개선 체감
  • 배포 직후 로딩표시 사라짐

🔍 의문

기본 CompileThreshold=10000인데 왜 500번만에 빨라졌을까?

JVM의 Tiered Compilation이 기본 활성화되어 있기 때문이다.
JVM은 Tiered Compilation을 사용하여 아래 표대로 1단계씩 점진적으로 최적화한다.

Tier 단계컴파일러특징
Tier 0인터프리터느리지만 빠른 시작 가능
Tier 1C1 컴파일러기본적인 최적화 적용
Tier 2~3C1 + Profile히트 정보 수집
Tier 4C2 컴파일러강력한 최적화 (JIT 핵심)

즉, CompileThreshold까지 가지 않더라도, Tier 1~3 단계에서 이미 성능 최적화가 일부 이뤄진다.

웜업 기준은 어떻게 정할까?

웜업이 되었다는 건 단순히 "1번 호출"이 아니라,

  • 외부 리소스 연결이 완료되었는지
  • JIT 컴파일이 어느 정도 진행되었는지를 기준으로 본다.

CompileThreshold는 우리가 수치로 직접 설정 가능하지만 Tiered Compilation은 아래 명령어를 통해 언제 어떤 단계로 올라갔는지 알 수 있다

java -XX:+PrintCompilation -jar myapp.jar

ApplicationReadyEvent vs CommandLineRunner

항목CommandLineRunnerApplicationReadyEvent
실행 시점Spring Context 초기화 직후애플리케이션이 완전히 실행된 후 (@EventListener)
빈 초기화 여부대부분 완료된 상태모든 Runner, @PostConstruct, CommandLineRunner 실행 후
실행 순서 제어@Order 또는 Ordered 인터페이스로 지정 가능이벤트 리스너 간의 우선순위는 지정하기 어려움
용도초기 데이터 로딩, 인자 기반 처리, 테스트용서버 포트 오픈 이후 수행할 로직 (ex. 알림, 웜업 등)
애플리케이션 준비 상태아직 WebServer가 완전히 리스닝하지 않을 수도 있음완전히 준비됨 (트래픽 받을 준비 완료)

요약

Spring Boot + Kubernetes 환경에서의 콜드 스타트 문제는 단순히 "배포 완료"가 아니라 "처리 준비 완료" 여부를 확인하는 것으로 해결 가능하다.
이를 위해 @Warmup 기반 로직과 startupProbe를 연동한 시스템을 구축했고, 초기 응답 속도를 60% 이상 개선했다.

0개의 댓글