본문 바로가기
dev/spring

Spring Boot에서 Project Leyden을 사용하는 방법

by igooo 2025. 6. 9.
728x90

개요

Project Leyden은 얼리 액세스(Early Access) 빌드로 제공하고 있으며 Spring Boot와 함께 사용했을 때 startup 시간이 얼마나 빨라지는지 대하여 이번 포스팅에서 알아본다.

 

Leyden Project

Leyden Proejct는 Java 프로그램의 시작 시간, 최대 성능 도달 시간, 그리고 사용 공간을 개선하기 위한 프로토타입을 개발하는 것이고, 향후 JDK 릴리즈에 정식으로 통합되기를 기대한다.

참고 : https://github.com/openjdk/leyden/blob/leyden-ea1-release-notes/README.md

 

 

Performance

Leyden Project를 사용하여 Spring Boot의 시작 시간을 측정한 내용은 이미 Spring Blog에 포스팅(https://spring.io/blog/2024/08/29/spring-boot-cds-support-and-project-leyden-anticipation#spring-boot-and-project-leyden) 되었으며 다른 실행 옵션에 비하여 빠른 실행 시간을 보인다. 

 

Spring Blog에 문서에 있는 CDS와(https://blog.igooo.org/123) Runtime efficiency with Spring는(https://blog.igooo.org/115) 이전 포스팅을 참고한다.

 

Spring Boot에서 Project Leyden 사용하기

JDK는 Project Leyden의(https://jdk.java.net/leyden/) 얼리 액세스 빌드를 사용했고, spring initializr를 사용하여 Spring Web프로젝트를 생성한다. 테스트는 MacBook Pro M4를 사용했다.

프로젝트 생성

프로젝트를 생성하면 아래와 같이 기본 생성된 파일을 볼 수 있다.

% ls
build.gradle	gradlew		HELP.md		src
gradle		gradlew.bat	settings.gradle

 

BootJar 파일 생성

gradle의 bootJar task를 실행하여 jar 파일을 생성한다.

빌드가 성공적으로 완료되면 build 디렉터리 하위에 libs/spring-leyden-0.0.1-SNAPSHOT.jar 파일이 생성된다.

% ./gradlew clean bootJar

BUILD SUCCESSFUL in 564ms
5 actionable tasks: 4 executed, 1 up-to-date

% ls
build		gradle		gradlew.bat	settings.gradle
build.gradle	gradlew		HELP.md		src

 

Exploded JAR 생성

Spring에서 Production 환경에서 사용하기를 권장하는 exploded jar파일을 생성한다.

% java -Djarmode=tools -jar build/libs/spring-leyden-0.0.1-SNAPSHOT.jar extract
% ls
build				gradlew				settings.gradle
build.gradle			gradlew.bat			spring-leyden-0.0.1-SNAPSHOT
gradle				HELP.md

-Djarmode=tools 옵션을 사용하면 Spring은 다양한 레이아웃을 사용하여 애플리케이션을 디렉터리로 추출한다. 기본 레이아웃의 경우 다음 내용을 포함한다.

  • lib 하위 디렉터리에는 라이브러리가 포함되며
  • 애플리케이션 클래스와 lib 폴더의 라이브러리를 참조하는 manifest를 가진 애플리케이션 JAR도 포함된다.

Leyden 사용

 % java -XX:CacheDataStore=SpringLeyden.cds -jar spring-leyden-0.0.1-SNAPSHOT/spring-leyden-0.0.1-SNAPSHOT.jar                                                                 
OpenJDK 64-Bit Server VM warning: Cannot dump shared archive while using shared archive

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.5.0)

2025-06-10T00:12:11.977+09:00  INFO 12148 --- [spring-leyden] [           main] o.i.s.leyden.SpringLeydenApplication     : Starting SpringLeydenApplication v0.0.1-SNAPSHOT using Java 24-leydenpremain with PID 12148 (/Users/igooo/Documents/workspace/spring-leyden/spring-leyden-0.0.1-SNAPSHOT/spring-leyden-0.0.1-SNAPSHOT.jar started by igooo in /Users/igooo/Documents/workspace/spring-leyden)
2025-06-10T00:12:11.978+09:00  INFO 12148 --- [spring-leyden] [           main] o.i.s.leyden.SpringLeydenApplication     : No active profile set, falling back to 1 default profile: "default"
2025-06-10T00:12:12.290+09:00  INFO 12148 --- [spring-leyden] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2025-06-10T00:12:12.299+09:00  INFO 12148 --- [spring-leyden] [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2025-06-10T00:12:12.299+09:00  INFO 12148 --- [spring-leyden] [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.41]
2025-06-10T00:12:12.318+09:00  INFO 12148 --- [spring-leyden] [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2025-06-10T00:12:12.319+09:00  INFO 12148 --- [spring-leyden] [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 316 ms
2025-06-10T00:12:12.451+09:00  INFO 12148 --- [spring-leyden] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path '/'
2025-06-10T00:12:12.455+09:00  INFO 12148 --- [spring-leyden] [           main] o.i.s.leyden.SpringLeydenApplication     : Started SpringLeydenApplication in 0.645 seconds (process running for 0.846)

 

위 명령을 사용하여 애플리케이션을 실행하면 2개의 파일이 생성된다.

% ls
build				gradlew.bat			SpringLeyden.cds
build.gradle			HELP.md				SpringLeyden.cds.code
gradle				settings.gradle			src
gradlew				spring-leyden-0.0.1-SNAPSHOT
  • SpringLeyden.cds 파일은 클래스 메타 데이터, 힙 객체 및 프로파일링 데이터가 포함되어 있다.
  • SpringLeyden.cds.code 파일은 AOT(선행 컴파일)된 메서드들이 포함되어 있으며, 향후 SpringLeyden.cds 파일과 통합될 예정이다.

Leyden을 사용하여 재실행

위에 Leyden을 사용하여 애플리케이션을 사용했을 때는 0.846초가 걸렸지만, 생성된 cds파일을 사용하여 재실행했을 때는 0.232초가 걸렸다. 약 3배 정도 실행 속도가 빨라졌다.

% java -XX:CacheDataStore=SpringLeyden.cds -jar spring-leyden-0.0.1-SNAPSHOT/spring-leyden-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.5.0)

2025-06-10T00:13:02.837+09:00  INFO 12157 --- [spring-leyden] [           main] o.i.s.leyden.SpringLeydenApplication     : Starting SpringLeydenApplication v0.0.1-SNAPSHOT using Java 24-leydenpremain with PID 12157 (/Users/igooo/Documents/workspace/spring-leyden/spring-leyden-0.0.1-SNAPSHOT/spring-leyden-0.0.1-SNAPSHOT.jar started by igooo in /Users/igooo/Documents/workspace/spring-leyden)
2025-06-10T00:13:02.837+09:00  INFO 12157 --- [spring-leyden] [           main] o.i.s.leyden.SpringLeydenApplication     : No active profile set, falling back to 1 default profile: "default"
2025-06-10T00:13:02.934+09:00  INFO 12157 --- [spring-leyden] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2025-06-10T00:13:02.936+09:00  INFO 12157 --- [spring-leyden] [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2025-06-10T00:13:02.936+09:00  INFO 12157 --- [spring-leyden] [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.41]
2025-06-10T00:13:02.939+09:00  INFO 12157 --- [spring-leyden] [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2025-06-10T00:13:02.939+09:00  INFO 12157 --- [spring-leyden] [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 99 ms
2025-06-10T00:13:02.979+09:00  INFO 12157 --- [spring-leyden] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path '/'
2025-06-10T00:13:02.980+09:00  INFO 12157 --- [spring-leyden] [           main] o.i.s.leyden.SpringLeydenApplication     : Started SpringLeydenApplication in 0.177 seconds (process running for 0.232)

 

로그 살펴보기 

로깅을 활성화하면 Project Leyden 내부에서 어떤 작업들이 벌어지는지 확인할 수 있다.

로깅을 위해서는 생성된 CDS 파일을 삭제하고 -Xlog:cds=debug:file=log/cds.log 옵션을 사용하여 CDS 생성과정을 기록할 수 있다.

% rm -rf SpringLeyden.cds*
% mkdir log

% java -XX:CacheDataStore=SpringLeyden.cds -Xlog:cds=debug:file=log/cds.log -Dspring.context.exit=onRefresh -jar spring-leyden-0.0.1-SNAPSHOT/spring-leyden-0.0.1-SNAPSHOT.jar
OpenJDK 64-Bit Server VM warning: Cannot dump shared archive while using shared archive

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.5.0)

2025-06-09T22:50:32.769+09:00  INFO 10980 --- [spring-leyden] [           main] o.i.s.leyden.SpringLeydenApplication     : Starting SpringLeydenApplication v0.0.1-SNAPSHOT using Java 24-leydenpremain with PID 10980 (/Users/igooo/Documents/workspace/spring-leyden/spring-leyden-0.0.1-SNAPSHOT/spring-leyden-0.0.1-SNAPSHOT.jar started by igooo in /Users/igooo/Documents/workspace/spring-leyden)
2025-06-09T22:50:32.770+09:00  INFO 10980 --- [spring-leyden] [           main] o.i.s.leyden.SpringLeydenApplication     : No active profile set, falling back to 1 default profile: "default"
2025-06-09T22:50:33.067+09:00  INFO 10980 --- [spring-leyden] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2025-06-09T22:50:33.074+09:00  INFO 10980 --- [spring-leyden] [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2025-06-09T22:50:33.074+09:00  INFO 10980 --- [spring-leyden] [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.41]
2025-06-09T22:50:33.093+09:00  INFO 10980 --- [spring-leyden] [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2025-06-09T22:50:33.094+09:00  INFO 10980 --- [spring-leyden] [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 300 ms
[0.789s][warning][cds] Preload Warning: Verification failed for org.springframework.boot.http.client.HttpComponentsClientHttpRequestFactoryBuilder
[0.793s][warning][cds] Preload Warning: Verification failed for org.springframework.core.ReactiveAdapterRegistry$ReactorAdapter
[0.800s][warning][cds] Preload Warning: Verification failed for org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer
[0.800s][warning][cds] Preload Warning: Verification failed for org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
[0.800s][warning][cds] Preload Warning: Verification failed for org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
[0.801s][warning][cds] Preload Warning: Verification failed for org.springframework.http.codec.multipart.DefaultPartHttpMessageReader
.....
[0.722s][warning][cds,heap] [53] {0x00000003008e55b0} java.lang.invoke.LambdaForm$Name::function (offset = 20)
[0.722s][warning][cds,heap] [54] {0x00000003008723a8} java.lang.invoke.LambdaForm$NamedFunction::member (offset = 12)
[0.722s][warning][cds,heap] [55] {0x00000003008723c0} java.lang.invoke.MemberName
[0.722s][warning][cds,heap] [56] {0x0000000300bae578} java.lang.Class
[0.722s][warning][cds,heap] [57] {0x0000000300872568} jdk.internal.misc.Unsafe
[0.722s][warning][cds,heap] --- trace end ---
[0.722s][warning][cds,heap] 
[0.722s][warning][cds,heap] Scanned 120929 objects. Found 41 case(s) where an object points to a static field that may be reinitialized at runtime.
CacheDataStore dumping is complete

 

-Xlog:class+load=info:file=log/class-load.log을 사용하면 로드된 클래스 정보를 확인할 수 있다.

% java -XX:CacheDataStore=SpringLeyden.cds -Xlog:class+load=info:file=log/class-load.log  -Dspring.context.exit=onRefresh -jar spring-leyden-0.0.1-SNAPSHOT/spring-leyden-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.5.0)

2025-06-09T22:52:38.079+09:00  INFO 11007 --- [spring-leyden] [           main] o.i.s.leyden.SpringLeydenApplication     : Starting SpringLeydenApplication v0.0.1-SNAPSHOT using Java 24-leydenpremain with PID 11007 (/Users/igooo/Documents/workspace/spring-leyden/spring-leyden-0.0.1-SNAPSHOT/spring-leyden-0.0.1-SNAPSHOT.jar started by igooo in /Users/igooo/Documents/workspace/spring-leyden)
2025-06-09T22:52:38.080+09:00  INFO 11007 --- [spring-leyden] [           main] o.i.s.leyden.SpringLeydenApplication     : No active profile set, falling back to 1 default profile: "default"
2025-06-09T22:52:38.171+09:00  INFO 11007 --- [spring-leyden] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2025-06-09T22:52:38.172+09:00  INFO 11007 --- [spring-leyden] [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2025-06-09T22:52:38.172+09:00  INFO 11007 --- [spring-leyden] [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.41]
2025-06-09T22:52:38.175+09:00  INFO 11007 --- [spring-leyden] [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2025-06-09T22:52:38.175+09:00  INFO 11007 --- [spring-leyden] [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 91 ms

 

총 몇 개의 클래스가 로드되었는지는 아래 명령을 사용하여 확인할 수 있다.

% cat log/class-load.log | wc -l
6804

또한 아래 명령을 통해 공유 아카이브에서 로드된 클래스에 대한 데이터를 확인할 수 있다.

% grep -o 'source: shared' -c log/class-load.log
6705

 

마무리

Java에서는 클라우드 환경에서 Java를 사용 가능하도록 다양한 기능이 개발 중에 있다. 최근에는 Kotlin을 더 많이 사용하지만 Java도 꾸준히 새로운 기술들이 나오고 있고, JDK25 2025년 9월 출시 예정으로 현업에서 사용 가능한 기술들이 빠르게 추가되었으면 한다.

 

참고

728x90