Contents
see List개요
GraalVM Native Image는 Java 애플리케이션을 네이티브 실행 파일로 사전 컴파일(AOT)하여, 밀리초 단위의 시작 시간과 극적으로 줄어든 메모리 사용량을 달성합니다. Spring Boot 3.x부터 공식적으로 GraalVM Native Image를 지원하며, Spring AOT 엔진이 빌드 타임에 리플렉션, 프록시, 리소스 접근 등을 분석하여 네이티브 컴파일을 자동화합니다. 서버리스, 컨테이너 환경에서 콜드 스타트 문제를 해결하는 핵심 기술입니다.
핵심 개념
AOT(Ahead-of-Time) 컴파일은 런타임에 수행하던 작업을 빌드 타임으로 이동시킵니다. Spring의 컴포넌트 스캔, 빈 정의 생성, 프록시 생성 등이 빌드 시점에 처리되어 런타임 오버헤드가 제거됩니다.
Closed-World Assumption은 네이티브 이미지의 기본 전제입니다. 빌드 시점에 도달 가능한 모든 코드가 확정되어야 하며, 런타임 동적 클래스 로딩이나 리플렉션은 별도 힌트가 필요합니다.
GraalVM Reachability Metadata는 네이티브 컴파일 시 필요한 리플렉션, 리소스, JNI, 직렬화 정보를 JSON으로 정의합니다. Spring Boot는 대부분의 메타데이터를 자동 생성하지만, 서드파티 라이브러리는 수동 설정이 필요할 수 있습니다.
실전 예제
Spring Boot 프로젝트에 Native Image 지원을 추가합니다.
<!-- pom.xml -->
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<buildArgs>
<buildArg>--no-fallback</buildArg>
<buildArg>-H:+ReportExceptionStackTraces</buildArg>
</buildArgs>
</configuration>
</plugin>
네이티브 이미지를 빌드하고 실행합니다.
# Maven으로 네이티브 이미지 빌드
./mvnw -Pnative native:compile
# 또는 Docker 컨테이너로 빌드 (GraalVM 미설치 환경)
./mvnw -Pnative spring-boot:build-image
# 실행 - 시작 시간이 약 0.05초
./target/my-application
리플렉션이 필요한 클래스에 대한 힌트를 등록합니다.
@Configuration
@ImportRuntimeHints(CustomRuntimeHints.class)
public class NativeConfig {
}
public class CustomRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
// 리플렉션 힌트
hints.reflection()
.registerType(ExternalDto.class,
MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS);
// 리소스 힌트
hints.resources()
.registerPattern("templates/*.html")
.registerPattern("static/**");
// 직렬화 힌트
hints.serialization()
.registerType(SessionData.class);
}
}
JVM 모드와 Native Image의 성능 비교입니다.
| 지표 | JVM (Spring Boot 3.4) | Native Image |
|---------------|----------------------|-------------------|
| 시작 시간 | ~2.5초 | ~0.05초 |
| 첫 응답 시간 | ~3.0초 | ~0.1초 |
| 메모리 (RSS) | ~350MB | ~80MB |
| 빌드 시간 | ~15초 | ~3분 |
| 실행 파일 크기 | JRE 포함 ~200MB | ~80MB |
| Peak 처리량 | 100% (기준) | ~85-95% |
활용 팁
- 서버리스 최적화: AWS Lambda, Google Cloud Functions에서 콜드 스타트를 0.1초 미만으로 줄일 수 있습니다.
- 테스트 먼저:
./mvnw -PnativeTest test로 네이티브 환경에서의 테스트를 빌드 파이프라인에 포함하세요. - 라이브러리 호환성: Spring Boot 공식 스타터는 대부분 호환되지만, 동적 프록시를 많이 사용하는 라이브러리는 확인이 필요합니다.
- 개발 워크플로우: 개발 중에는 JVM 모드로 빠르게 반복하고, CI/CD에서만 네이티브 빌드를 수행하는 전략이 효율적입니다.
- CDS 대안: 네이티브가 부담스러운 경우, Spring Boot 3.4의 CDS(Class Data Sharing) 지원도 시작 시간을 40-50% 개선합니다.
마무리
GraalVM Native Image는 Java의 가장 큰 약점이었던 시작 시간과 메모리 사용량을 극복하게 해줍니다. Spring Boot 3.x의 AOT 엔진 덕분에 대부분의 스프링 애플리케이션은 별다른 수정 없이 네이티브 이미지로 컴파일할 수 있습니다. 특히 컨테이너 기반 MSA와 서버리스 환경에서 비용 절감 효과가 뚜렷하므로, 새 프로젝트에서는 적극적으로 도입을 검토하시기 바랍니다.