diff --git a/_posts/2024-12-04-graal-vm.md b/_posts/2024-12-04-graal-vm.md new file mode 100644 index 0000000..15b4297 --- /dev/null +++ b/_posts/2024-12-04-graal-vm.md @@ -0,0 +1,182 @@ +--- +layout: post +title: "Graal VM 알아보기 (차세대 Java VM)" +categories: [스터디-자바, 개발] +tags: + [ + java, + graal, + graal vm, + native, + native image, + jvm, + oracle, + interpreter, + byte code, + machine code, + polyglot, + truffle, + graaljs, + graalpython, + ] +date: 2024-12-09 20:00:00 +0900 +toc: true +--- + +이번에 K-DEVCON 대전에서 연말을 맞아 행사를 진행했었다. ([관련 post](https://k-devcon.com/entry/Review-2024-11-30%ED%86%A0-K-DEVCON-%EB%8C%80%EC%A0%84-%EB%8C%80%EC%A0%84-%EA%B0%9C%EB%B0%9C%EC%9E%90-%ED%95%9C-%ED%95%B4-%EB%A7%88%EB%AC%B4%EB%A6%AC)) + +나는 이번 행사에서 **Java 8부터 21까지: 자바 주요 변화 알아보기** 라는 제목으로 발표를 진행하였는데, Graal VM 에 대해서도 이야기 할 수 있는 기회가 있었다. + +이번 글을 통해서는 발표를 준비하면서 알게 된 Graal VM 이 기존의 JVM 과 어떤 점이 다른지에 대해서 설명하고자 한다. + +# Graal VM + +## 기존의 Java VM + +> Write Once, Run Anywhere +> 한 번 작성해서 어디서나 실행 + +자바의 표어이다. 당시에는 매우 매력적인 표어였다고 한다. +이 부분은 플랫폼 독립성을 뜻하는데 이를 제공하기 위해 JVM (Java Virtual Machine) 이 핵심역할을 한다. +(플랫폼 독립성: 운영 체제와 관계없이 동일하게 바이트코드를 실행할 수 있음) + +![architecture](/assets/images/2024-12-04-graal-vm/architecture.png) + +JVM은 자바 바이트코드를 실행하는 가상 머신이다. JVM 을 통해서 Java Application 을 어디서든 실행시킬 수 있다. + +![how-java-work](/assets/images/2024-12-04-graal-vm/how-java-work.png) + +개발자가 작성한 .java 파일은 javac 를 거처 .class 파일에 바이트 코드로 저장된다. +저장된 바이트 코드는 jvm에 의해 로드되어 해석(인터프리트)된다. +최적화 될 수 있는 부분은 jvm 에서 JIT 컴파일러를 통해서 머신 코드(기계어)로 변경한다. + +이미지 출처 : well-grounded java developer + +JVM을 통한 플랫폼 동립성은 자바의 장점이였지만, 속도가 중요한 환경에서는 한계가 존재했다. + +## Graal VM + +Graal VM 은 이러한 문제를 해결해 줄 수 있는 솔루션이다. + +![graal vm logo](/assets/images/2024-12-04-graal-vm/graalvm_rabbit_icon.svg) + +Graal VM 은 Oracle 에서 만들고 있는 차세대 JVM 이다. [공식 홈페이지](https://www.graalvm.org/) 에서는 다음과 같은 표어를 사용하여 Graal VM 을 소개하고 있다. + +> Build faster, smaller, leaner applications +> An advanced JDK with **ahead-of-time Native Image compilation** + +번역해보면 다음과 같다. + +> 더 빠르고, 더 작고, 더 간결한 애플리케이션 빌드 +> **사전 네이티브 이미지 컴파일** 기능을 갖춘 고급 JDK + +Graal VM도 Java SE 표준을 준수하기 때문에 기존의 Java 애플리케이션 대부분을 실행할 수 있다고 한다. + +### Graal VM 의 주요 기능 + +Graal VM 의 주요 기능 2가지는 다음과 같다. + +- Native Image +- Polyglot Programming (multi language runtime) + +각각에 대해서 예시와 함께 좀 더 알아보도록 하자. + +### Native Image + +Native Image 는 사전(ahead-of-time, aot) 컴파일된 네이티브 이미지를 의미한다. + +#### 동작 방식 + +애플리케이션 코드를 컴파일 타임에 네이티브 코드로 변환하여 사용할 수 있도록 한다. 이를 통해 기존에 자바가 가지고 있었던 속도 문제를 해결할 수 있게 되었다. + +![how-native-image-work](/assets/images/2024-12-04-graal-vm/how-native-image-work.png) + +바이트코드를 네이티브 코드로 변환한다. + +#### 기존 JVM 기반 어플리케이션 과의 주요 차이점 + +GraalVM 네이티브 이미지는 사전에 생성된다. +이로 인해 기존의 JVM 기반 어플리케이션과 몇 가지 차이점들이 있게 된다. 주요 차이점은 다음과 같이 정리해볼 수 있다. + +- 애플리케이션의 정적 분석은 main 진입점에서 빌드 시점에 수행된다. +- 네이티브 이미지가 생성될 때 접근할 수 없는 코드는 제거한다. +- GraalVM은 코드의 동적 요소를 직접 인식하지 못하며 리플렉션, 리소스, 직렬화 및 동적 프록시 등에 대해 빌드시에 알려야 한다. (hint를 줘야 한다.) +- 애플리케이션 classpth는 빌드 시점에 고정되며 변경할 수 없다. +- 지연된 클래스 로딩은 없으며, 실행 파일에 포함된 모든 내용은 시작 시 메모리에 로드된다. +- 적절히 힌트를 주면 대부분 해결 가능하긴 하지만 Java 애플리케이션의 일부 측면에서 완전히 지원되지 않는 몇 가지 제한 사항이 있을 수 있다. + +#### Spring 과의 호환성 + +기존에는 spring native 라는 별도 프로젝트로 관리되고 있다가 Spring Boot 3 부터는 자체적으로 Graal VM 과 사용할 수 있도록 통합되었다. +더 자세한 내용은 [spring-boot doc 의 native-image 파트](https://docs.spring.io/spring-boot/reference/packaging/native-image/introducing-graalvm-native-images.html) 에서 잘 설명해주고 있다. + +#### 사용해보기 + +우선 `javac` 로 컴파일을 진행하여 class 파일을 만든 후 `native-image`를 만든다. + +![create-native-image](/assets/images/2024-12-04-graal-vm/create-native-image.png) + +![create-native-image-log](/assets/images/2024-12-04-graal-vm/create-native-image-log.png) + +생성이 완료되면 다음과 같이 실행파일이 생긴다. 해당 파일을 실행시키면 java application 이 실행된다. + +![native-image-created](/assets/images/2024-12-04-graal-vm/native-image-created.png) + +#### 요약 + +native image의 장점과 단점은 다음과 같이 정리해볼 수 있을 것 같다. + +- 장점 + - 실행 환경에서 JVM이 없어도 실행 가능하다. + - 컴파일 된 실행파일이기 때문에 실행 속도가 기존 대비 엄청 빠르다. + - 용량도 경량화 할 수 있다. +- 단점 : + - 동적으로 런타임에 실행되던 부분들에서 이슈가 생긴다. (reflect, proxy 등) + - 힌트를 통해 대부분 해결 가능하다. + - 플랫폼 종속성이 생긴다. 실행이 필요한 플랫폼에 맞게 빌드를 진행해야 한다. + +### Polyglot Programming (multi language runtime) + +Graal VM 은 자체 인터프리터(Truffle)를 통해 다중 언어 런타임을 제공한다. 이를 기반으로 Graal VM 런타임에서는 다양한 언어들을 통합하여 실행할 수 있다. + +#### 지원 언어 + +[Language Implementations](https://www.graalvm.org/latest/graalvm-as-a-platform/language-implementation-framework/Languages/) + +![language-implementations-page-screenshot](/assets/images/2024-12-04-graal-vm/language-implementations-page-screenshot.png) + +javascript, python 등 다양한 언어들을 제공한다. + +#### 사용해보기 + +graal-sdk, truffle-api 와 함께 사용하고자 하는 언어에 대한 dependency를 추가해준다. + +![polyglot-dependencies](/assets/images/2024-12-04-graal-vm/polyglot-dependencies.png) + +![polyglot-example-code](/assets/images/2024-12-04-graal-vm/polyglot-example-code.png) + +![polyglot-output](/assets/images/2024-12-04-graal-vm/polyglot-output.png) + +다른 언어의 코드를 실행시켜 자바에 통합한 것을 볼 수 있다. (따로 세팅 없이 한거라 warning이 많이 보이긴 하지만) + +자체 인터프리터를 사용하기 때문에, 별도의 환경 세팅을 하지 않더라도 문제없이 다른 언어를 실행시킨다. + +#### 어디에 사용할까? + +처음에는 굳이 다른 언어를 JVM 위에서 실행시킬 필요가 있을까 생각하였다. +하지만 다음과 같은 장점을 얻을 수 있을 것 같다. + +한 언어에서 다른 언어로의 상호 운용성이 생기게 된다. +Java 에서 다른 언어의 코드를 호출할 수 있고, 또 반대로 다른 언어에서 Java 의 데이터에 접근할 수 있다. +서로 직접 상호 작용하고 동일한 메모리 공간에서 데이터를 주고받을 수 있다. +이를 통해 별도의 외부 통신 수단(예: HTTP API, 메시지 큐 등)을 사용하지 않고도 언어 간의 경계를 허물 수 있다. + +좀 더 구체적인 예시를 들어보면 다음과 같을 것이다. + +- Java 애플리케이션에 Python 기반의 AI 모델을 통합한다. +- Java 애플리케이션에 Python의 NumPy 라이브러리를 사용한 복잡한 수학 계산 처리를 진행한다. +- react.js 와 Java 백엔드 을 함께 통합하여 운영 + +## 마무리 + +말로만 듣던 Graal VM 에 대해서 이번 발표를 준비하면서 알아볼 수 있었다. 자바 생태계는 자바를 더욱 경량화하고 최적화될 수 있는 방법을 만들어 나가고 있다. 앞으로의 자바 생태계도 어떻게 될지 기대된다. diff --git a/assets/images/2024-12-04-graal-vm/architecture.png b/assets/images/2024-12-04-graal-vm/architecture.png new file mode 100644 index 0000000..229208c Binary files /dev/null and b/assets/images/2024-12-04-graal-vm/architecture.png differ diff --git a/assets/images/2024-12-04-graal-vm/create-native-image-log.png b/assets/images/2024-12-04-graal-vm/create-native-image-log.png new file mode 100644 index 0000000..fb88517 Binary files /dev/null and b/assets/images/2024-12-04-graal-vm/create-native-image-log.png differ diff --git a/assets/images/2024-12-04-graal-vm/create-native-image.png b/assets/images/2024-12-04-graal-vm/create-native-image.png new file mode 100644 index 0000000..06a0118 Binary files /dev/null and b/assets/images/2024-12-04-graal-vm/create-native-image.png differ diff --git a/assets/images/2024-12-04-graal-vm/graalvm_rabbit_icon.svg b/assets/images/2024-12-04-graal-vm/graalvm_rabbit_icon.svg new file mode 100644 index 0000000..cde989b --- /dev/null +++ b/assets/images/2024-12-04-graal-vm/graalvm_rabbit_icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/2024-12-04-graal-vm/how-java-work.png b/assets/images/2024-12-04-graal-vm/how-java-work.png new file mode 100644 index 0000000..3a23424 Binary files /dev/null and b/assets/images/2024-12-04-graal-vm/how-java-work.png differ diff --git a/assets/images/2024-12-04-graal-vm/how-native-image-work.png b/assets/images/2024-12-04-graal-vm/how-native-image-work.png new file mode 100644 index 0000000..52096b2 Binary files /dev/null and b/assets/images/2024-12-04-graal-vm/how-native-image-work.png differ diff --git a/assets/images/2024-12-04-graal-vm/language-implementations-page-screenshot.png b/assets/images/2024-12-04-graal-vm/language-implementations-page-screenshot.png new file mode 100644 index 0000000..390f91f Binary files /dev/null and b/assets/images/2024-12-04-graal-vm/language-implementations-page-screenshot.png differ diff --git a/assets/images/2024-12-04-graal-vm/native-image-created.png b/assets/images/2024-12-04-graal-vm/native-image-created.png new file mode 100644 index 0000000..972898d Binary files /dev/null and b/assets/images/2024-12-04-graal-vm/native-image-created.png differ diff --git a/assets/images/2024-12-04-graal-vm/polyglot-dependencies.png b/assets/images/2024-12-04-graal-vm/polyglot-dependencies.png new file mode 100644 index 0000000..e8943be Binary files /dev/null and b/assets/images/2024-12-04-graal-vm/polyglot-dependencies.png differ diff --git a/assets/images/2024-12-04-graal-vm/polyglot-example-code.png b/assets/images/2024-12-04-graal-vm/polyglot-example-code.png new file mode 100644 index 0000000..a66e658 Binary files /dev/null and b/assets/images/2024-12-04-graal-vm/polyglot-example-code.png differ diff --git a/assets/images/2024-12-04-graal-vm/polyglot-output.png b/assets/images/2024-12-04-graal-vm/polyglot-output.png new file mode 100644 index 0000000..02ceb78 Binary files /dev/null and b/assets/images/2024-12-04-graal-vm/polyglot-output.png differ