티스토리 뷰

최근, 스프링 부트 3 버전이 출시됐다. 메이저 버전이 바뀐 만큼 다양한 변화가 있겠지만 그 중에서도 AOT 엔진을 사용한 스프링 네이티브 이미지가 가장 많이 언급되는 것 같다. 공식 문서에 따르면, 네이티브 이미지를 사용하는 것은 빠른 시작, 준수한 성능, 그리고 메모리 사용량 감소와 같은 장점을 제공한다.

새 프로젝트에 적용이 가능할 정도인가 싶어, 바로 테스트를 해봤다.
내 환경은 아래와 같다.

  • M1 Mac
  • Graalvm CE 19
  • Gradle

어떤 방법으로 네이티브 이미지를 빌드할까?

스프링 네이티브 이미지를 빌드하는 방법에는 두 가지가 있다. 하나는 도커 이미지를 사용하는 것, 다른 하나는 Graalvm을 통해 바이너리 파일을 직접 빌드하는 것이다.

도커를 사용하면 간단하겠지만, 신기술의 경우 내가 개발하는 환경에서는 작동하지 않는 경우가 생각보다 많아서 도커 없이도 쉽게 사용가능한지 직접 바이너리 파일을 빌드해서 테스트해봤다.

GraalVM 설치

IntelliJ에서 Graalvm 다운로드를 제공하기에 다른 특별한 설정없이 다운로드 받기만 했다.

프로젝트 생성하고 빌드하기

IntelliJ를 통해 Spring boot 3 간단한 프로젝트를 생성했다.

달리 설정할 것이 없이, 바로 빌드해봤다. 바이너리 파일로 빌드하려면 gradle에서 nativeCompile task를 실행하면 된다. 비교를 위해 executable jar도 빌드했다.

역시 한번에 빌드가 되지는 않는다.

nativeCompile 테스크에서 Graalvm을 찾지 못하고, Cannot query the value of property 'javaLauncher' because it has no value available.
에러가 발생했다. 이 Github Issue를 보니 JAVA_HOME이 설정되지 않아서 발생한 문제로 보여서, Run/Debug Configuration에서 설정한 뒤에는 빌드가 잘 됐다.

빌드하는데만 약 3분 17초 정도 소요됐다.

환경변수 말고 다른 방법이 없을까?

Run/Debug Configuration에서 환경변수를 설정하게 되면, 테스트를 돌려야해서 실행 환경을 바꾸게 되면 또 다시 설정해줘야 하고 사소한 일로도 해당 설정이 지워질수 있다. 또한 같은 프로젝트를 공유하는 사람들에게 같은 실수를 방지하기 위해서 이 이슈가 있음을  반드시 공유해야 하는 점이 불편하다.

Gradle로 처리할 수 있는 방법이 있나 찾아보니, Native build plugin 문서에서 설명하는 toolchain 설정하니, 환경변수 없이도 작동했다.

테스트 결과

Jar 패키지 실행 결과
네이티브 이미지 실행 결과
빌드 결과물 사이즈

Startup time은 약 5.5배 감소했고 메모리 사용량은 약 4배 감소했으며, 용량의 경우 약 3.6배 증가했다. 여러 블로그를 보면 이미지 사이즈가 감소한다고 하던데, 도커 이미지 이야기인건지 아니면 내가 뭘 잘못한지 모르겠다. 생각해보면 native 빌드할때 byte code metadata나, JVM 없이 자체 실행이 가능하게 하는 유틸리티 등이 포함됨을 고려하면 용량이 커지는게 이상하진 않은 것 같다.

정리

다음 프로젝트부터 적용해볼 예정인데 한가지, Golang처럼 환경변수로 크로스 플랫폼 빌드를 할 수 없는게 솔직히 많이 아쉽다. 그러나 도커로 대체할 수 있고, 바이너리 빌드시에는 Github action에서 OS를 선택해서 빌드하면 배포 OS에도 맞출 수 있으니 사용하는데는 무리가 없을 것 같다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함