[spring boot] JDK로 만든 당신의 컨테이너 이미지, 정말 JDK가 필요했나요? 🤔

2025. 1. 11. 13:26·Back-End/Spring boot
반응형

🤔 개요


많은 개발자들이 Spring Boot 프로젝트 배포 시 불필요하게 JDK(Java Development Kit)를 사용하고 있다.

개발 환경에서는 JDK가 필수적이지만,

실제 배포 환경에서는 JRE(Java Runtime Environment)만으로도 충분하다는 점을 간과하고 있다.

 

이러한 방식으로 인해 낭비되는 리소스는 애플리케이션의 성능과 효율성에 영향을 미칠 수 있다.

 

예를 들자면, 무료 호스팅 사이트의 컨테이너 이미지 제한이 있는 경우 배포가 불가능한 경우가 있다.

실제로 나는 Koyeb / Render라는 무료 호스팅 사이트에서 Spring boot 서버를 컨테이너 이미지 방식으로 배포하려고 했으나,

배포 이후 용량이 무료 버전의 최대 용량인 512MB를 넘어서 배포가 불가능했었다.

 

해당 포스팅은 다음과 같은 질문에 대해 벤치마크 결과로 답하고자 한다.

 

JDK와 JRE 중 어떤 Base Image가 효율적인가?

 

📃 배경 지식


Fig 1. JVM, JRE, JDK Diagram

JRE (Java Runtime Environment)

자바 프로그램을 실행하는 데 필요한 환경을 의미한다.

즉, 실행은 가능하지만, 빌드, 컴파일 등 개발과 관련된 작업은 불가능하다.

JDK (Java Development Kit)

자바 개발 키트로 개발에 필요한 기능이 존재한다.

당연히 실행할 수도 있다. (JRE가 포함되어 있기 때문)

컨테이너화 (Containerization)

Fig 2. The Comparison of the Bear metal, the Virtualization and the Containerization

 

Fig 2 (a)는 가상화가 전혀 적용되지 않은 일반적인 형태로,

운영체제에 애플리케이션에 필요한 요소를 설치하여 구동하는 경우를 보여준다.

 

Fig 2 (b)는 가상화를 나타낸다.

가상화는 하드웨어 리소스를 추상화하여 독립적인 가상 머신을 생성하는 기술이다.

이는 운영체제의 구동이 필요하기 때문에 애플리케이션을 구동시킬 목적으로는 적합하지 않은 경우가 많다.

 

Fig 2 (c)는 컨테이너화를 보여준다.

컨테이너화는 애플리케이션과 의존성을 패키징하는 기술로,

가상화의 문제점이었던 가상 머신의 운영체제와 환경 불일치 문제가 어느정도 감소된다.

 

Bare metal로 구동해도 문제는 없지만,

여러 자바 버전의 Spring boot가 구동되기 위한 여러 버전 설치, 관리 및 적용에서 어려움이 있을 수 있다.

🛠️ 설계


컨테이너화를 진행할 때 많은 사람들이 JDK를 기본 이미지로 사용하는데,

JDK도 여러 벤더 사에서 제공한다.

그 중 주로 사용하는 벤더 사들을 선정하여 테스트를 진행한다.

Fig 3. JDK Vendor Statistics

 

Fig 3은 솔루션 사이트에서 제공하는 벤더 별 사용 비율이다.

해당 자료와 DockerHub에서 열람 가능한 이미지를 기준으로,

다음과 같이 테스트할 JDK와 JRE를 선정했다.

  • openjdk (jdk, slim, alpine)
  • eclipse-temurin (jdk, jdk-alpine, jre, jre-alpine)
  • bellsoft/liberica (jdk-debian, jdk-alpine, jre-debian, jre-alpine)
  • amazoncorretto (jdk, jdk-alpine)

Fig 4.Benchmark Design

 

Fig 4는 벤치마크 방식을 나타낸다.

GitHub Actions의 matrix 설정을 활용하여

JDK, JRE 컨테이너 이미지를 기반으로 하는 Dockerfile을 병렬적으로 생성 후 컨테이너화를 진행한다.

이후 생성된 Spring boot 컨테이너 이미지를 tar로 저장하여 용량을 비교한다.

📊 평가


 

Vendor Name type tag Base Image size Spring boot size
Oracle Corporation
OpenJDK
JDK
<none> 231.9 MB 257.26 MB
slim 210.63 MB 236.02 MB
alpine 181.71 MB 207.16 MB
Eclipse Adoptium
Adoptium Eclipse Temurin
JDK
<none> 188.11 MB 214.23 MB
alpine 162.38 MB 187.72 MB
JRE
<none> 89.32 MB 115.52 MB
alpine 65.37 MB 90.79 MB
Amazon.com Inc.
Amazon Corretto
JDK
<none> 204.36 MB 229.72 MB
alpine 142.36 MB 167.82 MB
BellSoft
BellSoft Liberica
JDK
debian 149.26 MB 174.47 MB
alpine 79.93 MB 105.44 MB
JRE
debian 102.97 MB 128.35 MB
alpine 48.32 MB 73.85 MB

 

Table 1. Benchmark Result

벤치마크 결과는 Table 1과 같다.

이때 사용한 Spring boot 이미지는 개인 프로젝트로 진행한 파일을 jar로 만들어 공통으로 적용했고,

파일 크기의 경우 linux/amd64를 기준으로 측정했다.

 

(OpenJDK의 경우 Oracle이 프로젝트 소유권을 가지지만 개발 및 관리는 OpenJDK 커뮤니티에서 수행한다.

소유권과 container의 정보를 가져올 때의 값을 기반으로 Vendor 열을 작성하여 Oracle Corporation으로 작성했다.)

 

결과를 보면

JRE 이미지를 Base로 사용할 때 JDK 이미지의 경우보다 전체 용량이 적음을 확인할 수 있다.

✨ 결론


JDK와 JRE 중 어떤 Base Image가 효율적인가?

JRE를 Base Image로 사용하는 것이 효율적이다.

만약, 더 효율적인 방안을 찾는다면 JRE에서도 필요한 부분만 가져와 사용하는 방식을 활용할 수 있을 것이다.

 

운영 과정에서 컴파일, 동적 클래스 로딩 등 특수한 경우(JDK의 개발 기능이 필요한 경우) 가 있는 것이 아니라면

Base Image를 JRE 이미지, 그 중에서도 경량화된 이미지 (alpine 등) 로 선정하는 것을 적극 추천한다.

 

 

⛳ 향후 계획


Future Work로 생각중인 부분은 두 가지가 있다.

 

첫 번째는 해당 벤치마크를 진행하면서,

다른 컨테이너화 방법론도 해당 글과 같은 방식으로 비교해보는 것이 좋겠다고 판단했다.

추가로 GitHub Actions나 Dockerfile 설정에서 더 나은 결과를 얻을 수 있는 방법도 리뷰하고 싶어졌다.

가제는 "Spring boot 컨테이너화 방법론과 각각에 대한 최적화 방안" 이다.

 

두 번째는 컨테이너를 사용하는 현재,

Bare metal과의 차이점을 더 명확히 보고싶은 생각이 들었다.

실제로 해당 질문을 들었던 적도 있었고, 찾아보니 논문도 꽤 있었다.

그래서 "Base metal vs Container" 에 대한 내용을 다루고 싶다.

💡 새롭게 알게된 점


GitHub-Hosted Runner는 setup-java가 필요 없다 ?!

JDK를 사용하는 경우를 찾아보다가 setup-java action이 생각났다.

실제로 setup-java action은 v3부터 JRE를 지원하기 시작했다.

 

그래서 JRE로 설정하는 경우에 대한 측정을 진행했었는데,

빌드 과정에서 JDK가 필요하기 때문에 의미 없는 실험이었다.

 

그러나 JRE를 설정하고도 빌드가 되었고,

이유는 간단했다.

 

GitHub-Hosted Runner는 기본적으로 JDK를 가지고 있다!

 

GitHub Actions log

 

그래서 setup-java가 JRE여도, 없더라도 동작한 것이다.

 

회사에서는 사내 인스턴스로 Self-Hosted Runner를 구축했기 때문에,

setup-java를 없애니 JAVA_HOME 경로가 없다며 실패했다.

 

만약 당신이 Public Repository에서 GitHub-Hosted Runner로 action을 실행한다면 setup-java를 생략하는 것을 추천한다.

upload-artifact의 용량은 실제와 다를 수 있다 ?!

측정을 마치고 업로드된 아티팩트의 용량을 확인하는데,

bellsoft/liberica-openjre-alpine 이미지와

bellsoft/liberica-openjdk-alpine 이미지의 경우 오히려 JDK가 가벼운 결과가 나와서 당황했다.

 

GitHub Actions log

 

로그를 보니 file upload size를 알려준 후,

업로드 이후 사이즈를 알려준다.

 

이 업로드 이후 사이즈가 GitHub Actions 결과에 Size 값으로 나타난 것이다.

즉, 실제 사이즈와 다르게 나온 것이다.

 

그렇게 신경쓸 정도는 아니지만 꽤나 당황스러운 경험이었다.

📚 레퍼런스


  • https://pamyferret.tistory.com/45 (JDK, JRE 차이점)
  • https://whichjdk.com/ko/ (JDK Vendors)
  • https://newrelic.com/resources/report/2024-state-of-the-java-ecosystem (Fig 3 reference)
  • https://github.com/Juser0/github-actions-sandbox/actions/runs/12610933149 (benchmark result)
  • https://github.com/Juser0/github-actions-sandbox/actions/runs/12686293281/job/35358318452 (GitHub-Hosted Runner result)
반응형
저작자표시 비영리 변경금지 (새창열림)

'Back-End > Spring boot' 카테고리의 다른 글

[Spring boot] 우리 팀 application.yml은 과연 안전할까? - 컨테이너로 인한 환경변수 노출 시나리오와 예방법  (0) 2025.02.22
'Back-End/Spring boot' 카테고리의 다른 글
  • [Spring boot] 우리 팀 application.yml은 과연 안전할까? - 컨테이너로 인한 환경변수 노출 시나리오와 예방법
Justuser
Justuser
의미 있고, 계속 찾아보게 되는 내용을 기록합니다
  • Justuser
    나만의 해시 테이블
    Justuser
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 계획
      • 잡담
        • 회고
      • 서평
      • CS
      • Back-End
        • Spring boot
      • DevOps
        • Docker
      • 면접 질문
        • Spring boot
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
Justuser
[spring boot] JDK로 만든 당신의 컨테이너 이미지, 정말 JDK가 필요했나요? 🤔
상단으로

티스토리툴바