스프링 - ECS JVM 힙 메모리 증가시키기
작성일자 : 2025년 04월 06일
(이미지)
발생한 문제
AWS ECS에서 Spring Boot 애플리케이션을 실행할 때, JVM 힙 메모리가 부족하여 애플리케이션이 비정상 종료되는 문제가 발생했습니다.
로그
Exception in thread "http-nio-8080-Acceptor" java.lang.OutOfMemoryError: Java heap space
해결 방법
현재 ECS Task Definition
ECS Task Definition은 아래와 같이 설정되어 있습니다.
Task Size
- CPU: 0.9vCPU
- Memory: 0.9GB
Container - Resource allocation limits
- CPU: 0.9vCPU
- Memory hard limit: 0.9GB
- Memory soft limit: 0.7GB
Spring Boot Actuator를 통한 JVM 메모리 확인
Spring Boot Actuator를 사용하여 JVM 메모리를 확인할 수 있습니다.
Actuator의 /actuator/metrics/jvm.memory.used
, /actuator/metrics/jvm.memory.max
엔드포인트를 통해 현재 JVM 메모리 사용량을 확인하였습니다:
Current Memory Usage
- Used total: 395.91MB
- Used heap: 153.62MB
- Used nonheap: 249.12MB
Max Memory Limits
- Max total: 1.56GB
- Max heap: 235.21MB
- Max nonheap: 1.33GB
왜 Max heap 메모리가 235.21MB인가?
JVM의 기본 힙 메모리 설정은 -Xms
와 -Xmx
옵션을 통해 조정할 수 있습니다.
다만, Java 10부터는 -XX+UseContainerSupport
옵션이 기본값으로 설정되어 있으며, Java 8u191 버전에도 백포팅 되었습니다. 이를 이용하면 JVM이 호스트 머신의 물리적 메모리를 사용하는 대신 컨테이너 메모리 제한을 감지하고 이를 기반으로 힙 메모리를 설정합니다.
최대 힙 메모리 퍼센트는 -XX:MaxRAMPercentage
옵션을 통해 조정할 수 있습니다. 기본값은 25%입니다.
즉, 컨테이너의 메모리 제한이 0.9GB인 경우, 최대 힙 메모리는 약 0.225GB(=0.9GB * 25%)로 설정되며, 위에서 확인한 것처럼 235.21MB와 일치합니다.
Dockerfile 수정
-XX:MaxRAMPercentage
옵션을 50%로 설정하여 최대 힙 메모리를 50%로 조정하였습니다.
FROM amazoncorretto:17-al2023
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Dspring.profiles.active=prod","-XX:MaxRAMPercentage=50.0","-jar","/app.jar"]
조정 이후의 JVM 메모리 확인
Dockerfile 수정 후, Spring Boot Actuator를 통해 JVM 메모리를 다시 확인하였습니다.
Current Memory Usage
- Used total: 450.65MB
- Used heap: 169.95MB
- Used nonheap: 243.16MB
Max Memory Limits
- Max total: 1.79GB
- Max heap: 468.32MB
- Max nonheap: 1.33GB
Max heap 메모리가 468.32MB로 증가한 것을 확인할 수 있습니다.