grep

Backend

GraalVM, Spring Native 맛보기

NHN

2021년 6월 7일

원문에서 보기 ↗

몇 년 전부터 Oracle에서 GraalVM 이란 jvm을 소개하기 시작했습니다. 1.png

위 그림은 공식 사이트에 있는 건데요. 기동 시간이 50배!, 메모리도 5배 작게 사용한다는데 확인을 안 할 수가 없었습니다.

우선 GraalVM이 무엇인지 알아보고 실전으로 들어가 보겠습니다.

GraalVM 이란?

탄생 배경

C++로 만들어진 OpenJDK JIT Compiler는 노후화되어 러닝 커브가 높아 인력을 구하기도 힘들고, 수정하는 것도 너무 어려워 더 이상 개선이 힘든 문제가 있다고 합니다. 해결책으로 Java로 JIT 컴파일러를 만들기로 했고, Java니 인력이나 개선을 위한 기능들을 쉽게 추가할 수 있게 되었다고 합니다.

실제로 openjdk8 에도 실행 시 옵션으로 Graalvm을 선택할 수 있게 되어 있다고 합니다.

좀 치사하지만 무/유료 구분으로 community edition과 enterprise edition이 있습니다. enterprise edition 이 메모리 관리가 더욱 우수하다고 하고 있습니다.

주요 기능

공식 사이트에서는 High Performance, Ahead-of-TIme Compilation, Language Choice, Advanced Tools 가 주요 기능으로 나와 있습니다.

High Performance 는 속도나 자원의 사용률에 대해서 성능을 좋게 했다고 합니다. 공식 사이트 벤치 마크를 보니 아래 그림처럼 나오는데요. ee를 사용해야 정말 많이 성능이 좋아지는 게 아닌가 싶습니다. 2.png

Ahead-of-TIme Compilation 는 Natvie Binary에 관련된 내용입니다. java의 약점인 인터프리터 실행 환경을 극복하고자 하는 목적으로 미리 타깃 OS에 맞는 실행 파일을 만들겠다는 의미입니다. 컴파일의 결과물이 특정 OS에 맞는 실행 파일로 만들어 줄 수 있기 때문에 타깃 OS에 java를 설치할 필요도 없게 되고, 실행 시 JIT가 동작을 할 필요가 없기 때문에 빠르게 실행이 될 수 있는 장점이 있습니다. 하지만 java가 인터프리터 실행 환경이기 때문에 실제 타깃에 맞게끔 실행 중 컴파일에 최적화를 해줘서 aot보다 더 성능이 좋아질 수 있는 가능성은 포기를 해야 합니다.

Language Choice 아래 그림처럼 GraalVM은 모든 언어를 실행할 수 있게 해 줄 수 있습니다. 3.png Ruby, Pyton, R 등을 실행시킬 수 있고, GraalVM 성능이 좋아지면 같이 좋아지는 효과가 있고, AOT와 같이 활용이 된다면 각 언어에 맞는 인터프리터 실행 환경을 설치를 하지 않고도 실행 파일만 배포해도 되는 장점을 가질 수 있습니다.

결국 AOT, Language Choice 가 클라우드 친화적인 기술이라고 미는 느낌입니다.

Advanced Tools 는 Dashboard, Chrome Debugger, VisualVM,.. 등 지원하는 툴이 있습니다.

나온 이야기들을 요약을 해보면

로 결론이 나서 업무에서 사용하고 프로젝트로 테스트를 시도를 해보았습니다.

참고


JIT만 변경해보기

Mac에서

4.png

이제 하라는 데로 명령어 수행하여 설치

5.png 잘 보이네요.

intellij에서

6.png 자기가 알아서 찾아주고 7.png 추가하고 이름 좀 변경해주고 프로젝트에서 8.png 변경을 했습니다.

SpringApplication 기동을 시키면 동일하게 뜨는데.. 9.png 걸린 시간이 동일했습니다! Spring의 initialize 시간이 줄었으면 좋겠다고 생각을 했는데 전혀 차이가 없었습니다.

API 호출을 하면서 성능 테스트를 해서 비교를 해보면 좋을 것 같긴 한데, 미리 구성한 부하 테스트가 없어서 나중에 시간 나면 해봐야 할 것 같습니다.

Native Binary로 만들어보자

JIT만 변경해서는 안된다면 Native Binary로 만들어서 빨리 실행이 되는지 확인해보기로 했습니다. Spring과 같은 Framework를 사용한다면 Framework에서 먼가 지원을 더 해줘야 한다고 합니다. (Framework에서는 Reflection을 사용하기 바이너리를 만들 때 포함시킬 대상을 모르기 때문에 대상을 알려줄 수 있는 도움이 필요하다고 합니다.) Spring을 보니 Spring Native라는 프로젝트가 있었습니다.

Spring Native

클라우드 환경에서 배포를 쾌적하기 위해 docker image나 native binary를 쉽게 만들어 줄 수 있게 해주는 프로젝트입니다. https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/에 공식 문서가 있는데 아직 버전이 0.9.2라 잘 안될 것 같은 느낌에 간단한 프로젝트로 변경을 하고 시도를 해보았습니다. docker는 만들 생각이 없어서 Native Binary만 만드는 것을 시도해 보았습니다.

설정

10.png 우선 boot 버전을 2.4.5로 올려야 합니다.

pom.xml에 pluginRepository, repository 추가

        <pluginRepository>
            <id>maven2-spring</id>
            <name>Spring Release Repository</name>
            <url>https://maven.springframework.org/release/</url>
        </pluginRepository>

        <repository>
            <id>maven2-spring</id>
            <name>Spring Release Repository</name>
            <url>https://maven.springframework.org/release/</url>
        </repository>

dependecy에 추가

<dependencies>
    <dependency>
        <groupId>org.springframework.experimental</groupId>
        <artifactId>spring-native</artifactId>
        <version>0.9.2</version>
    </dependency>
</dependencies>

aot를 위한 plugin추가

<plugin>
                <groupId>org.springframework.experimental</groupId>
                <artifactId>spring-aot-maven-plugin</artifactId>
                <version>0.9.2</version>
                <executions>
                    <execution>
                        <id>test-generate</id>
                        <goals>
                            <goal>test-generate</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>generate</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

native-image라는 profile 추가하면서 부분을 Appliation 경로로 변경을 해주어야 합니다.

        <profile>
            <id>native-image</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.graalvm.nativeimage</groupId>
                        <artifactId>native-image-maven-plugin</artifactId>
                        <version>21.0.0.2</version>
                        <configuration>
                            <!-- The native image build needs to know the entry point to your application -->
                            <mainClass>org.test.Application</mainClass>
                        </configuration>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>native-image</goal>
                                </goals>
                                <phase>package</phase>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

기존 것을 주석 처리하고

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <classifier>exec</classifier>
        </configuration>
    </plugin>

필요한 유틸리티들 설치

gu install native-image

요것만 하면 된다는데 PATH를 안 잡아놔서.. 풀 패스로 실행

/Library/Java/JavaVirtualMachines/graalvm-ce-java11-21.1.0/Contents/Home/bin/gu install native-image

만들기

11.png 로 만들어보면 아래와 같은 에러가 납니다. 12.png 의존성에서 못 찾은 것 같은데 일단 dependency에 추가를 해봅니다.

        <dependency>
            <groupId>javax.cache</groupId>
            <artifactId>cache-api</artifactId>
            <version>1.1.1</version>
        </dependency>

다시 실행을 해보면. 와우 무려 9분 16초가 걸렸습니다 ㅡㅡ;; target 디렉터리에 아래 그림처럼 실행 파일이 하나 생겼습니다. 13.png

실행을 하면 에러가 나서 일단 logback-spring.xml 삭제, Swagger 삭제하고 나서 다시 빌드하고 실행을 해보았습니다. 배너가 나오는 데까지 5초 정도 걸렸습니다.(그냥 띄울 때는 10초 정도 걸렸었습니다만 완전하게 뜬 게 아니라서 더 빠르다고 할 수는 없을 것 같았습니다) 14.png 멋지게 실행이 되는 것처럼 보였지만.. 아래처럼 에러가 발생을 했습니다. AspectJ 가 문제가 있는 것 같은데 해결을 못하겠어서 안타깝지만 여기서 포기를 했습니다. 15.png

마무리

JIT만 변경하는 것은 어렵지 않고 문제도 없는 것 같지만 부트 시간이 개선이 되지 않았습니다. Native Binary는 적용하기 어렵고, 아직 갈길이 먼 것 같다는 느낌이었습니다. 정상 동작하는 것을 보려면 좀 시일이 걸릴 것 같았습니다.


이미지 출처