← 목록으로AWS

EC2 메모리 사용률 82% → 86% 지속 상승, Java 프로세스 분석 및 대응

t3.large EC2 인스턴스에서 메모리 사용률이 비정상적으로 높아진 원인을 분석하고, Java 프로세스별 메모리 점유를 추적한 트러블슈팅 기록

AWSEC2TroubleshootingMemoryJavaMonitoring
2025-09-01

문제 인식

운영 중인 EC2 인스턴스(t3.large)에서 CloudWatch Agent 기반 메모리 모니터링 중 82.4% 의 높은 메모리 사용률을 확인했습니다.

DB 서버도 아닌 애플리케이션 서버에서 이 정도 메모리 사용률은 비정상적이었고, 이 상태가 지속되면 메모리 누수나 스왑 의존으로 인한 성능 저하가 우려되었습니다.

CloudWatch 대시보드 - CPU 6.65%, 메모리 82.4%


서버 사양 확인

항목
인스턴스 타입t3.large
vCPU2개
메모리8 GiB
네트워크 성능Moderate
EBS 최적화지원 (최대 2,250 Mbps)
CPU 모델크레딧 기반 버스트

t3.large는 간헐적 부하에 적합한 버스트 가능 인스턴스로, 웹 서버나 마이크로서비스 운영에 주로 사용됩니다. 8GB 메모리에서 82%를 상시 점유하는 것은 정상적인 운영 패턴이 아니었습니다.


메모리 상태 분석 (free -m)

free -m 명령어 결과

$ free -m
              total    used    free    shared  buff/cache  available
Mem:          7719     6359     142      64       1216        996
Swap:        10239     1719    8520

물리 메모리

항목비고
Total7,719 MB (~7.7 GB)
Used6,359 MB (~6.4 GB)앱 + 캐시/버퍼 포함
Free142 MB (~0.14 GB)실질적으로 여유 없음
Buff/Cache1,216 MB (~1.2 GB)Linux 캐시 (필요 시 해제 가능)
Available996 MB (~1 GB)실제 사용 가능한 메모리

스왑 메모리

항목
Total10,239 MB (~10.2 GB)
Used1,719 MB (~1.7 GB)
Free8,520 MB (~8.5 GB)

스왑 사용량이 1.7GB에 달한다는 것은 물리 메모리가 충분하지 않아 디스크 기반 스왑에 의존하고 있다는 의미입니다. 스왑 I/O는 물리 메모리 대비 수십~수백 배 느리므로 성능 저하의 직접적 원인이 됩니다.


프로세스별 메모리 점유 분석 (top / ps aux)

top 명령어와 ps aux | grep java 를 통해 메모리를 많이 사용하는 프로세스를 식별했습니다.

Java 프로세스별 메모리 사용량

주요 프로세스 목록

순위PID프로세스메모리 사용률CPU 사용률메모리 크기
113596Java App (메인 서비스)47.9%14.0%~3.6 GB
216314Java App (Java 1.8)9.7%--
325611Java App (에이전트)7.8%0.3%~616 MB
47331Partner Agent (OpenJDK 18)3.3%--
58889Proxy Service (OpenJDK 18)2.7%--
62748CloudWatch Agent0.4%0.7%~31 MB

핵심 원인: PID 13596 Java 프로세스 하나가 시스템 메모리의 절반(47.9%) 을 차지하고 있었습니다. 여러 Java 프로세스가 동시에 실행되면서 총 메모리 사용률이 82%를 넘긴 상황이었습니다.


PID 16314 실행 파일 확인

$ sudo ls -l /proc/16314/exe
lrwxrwxrwx 1 root root 0 Oct 14 00:34 /proc/16314/exe -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64/jre/bin/java

PID 16314 실행 파일 확인

해당 프로세스는 시스템에 설치된 OpenJDK 1.8 런타임으로 실행된 Java 프로세스였습니다.


나머지 1GB의 행방 (cat /proc/meminfo)

Java 프로세스들의 합산 메모리와 buff/cache를 제외하고도 약 1GB가 어디에 사용되는지 확인했습니다.

cat /proc/meminfo 분석 결과:

  • 커널 메모리(Slab): 커널 내부 데이터 구조 캐싱
  • Inactive 메모리: 최근 사용되지 않았지만 아직 해제되지 않은 페이지
  • 시스템 관련 메모리 관리 오버헤드

이 1GB는 커널과 시스템 레벨에서 사용하는 메모리로, 애플리케이션이 직접 제어할 수 없는 영역입니다.


모니터링 추이

초기 확인 시 82.4% 였던 메모리 사용률이 며칠 후 86.6% 로 상승했습니다.

메모리 사용률 86.6%로 상승

일주일간 평균 메모리 사용량은 약 81.7%, 스왑 사용량은 1.7GB/10.2GB 수준을 유지했습니다.

메모리 사용률이 지속적으로 우상향하는 패턴은 메모리 누수 가능성을 시사합니다.


분석 결과 및 대응 방향

원인 요약

  1. 다수의 Java 프로세스 동시 실행: 메인 서비스(47.9%) + 에이전트(7.8%) + 기타 Java 프로세스들이 8GB 메모리를 거의 소진
  2. 스왑 의존: 물리 메모리 부족으로 1.7GB 스왑 사용 중 → 디스크 I/O 기반이므로 성능 저하 유발
  3. Available 메모리 1GB 미만: 새로운 프로세스 실행이나 부하 증가 시 OOM 위험

대응 방안

  • JVM Heap/Non-Heap 메모리 모니터링 도입: 각 Java 프로세스의 -Xmx, -Xms 설정 확인 및 적정 값 조정
  • 불필요한 Java 프로세스 정리: 동일 서버에서 실행 중인 프로세스 중 통합 가능한 것 검토
  • 인스턴스 타입 업그레이드 검토: t3.large(8GB) → t3.xlarge(16GB) 등
  • 메모리 사용률 알람 설정: CloudWatch 기반 80% / 90% 임계치 알람 구성
  • 주기적 메모리 트렌드 리포트: 메모리 누수 여부 장기 추적

마무리

단순히 "메모리 사용률이 높다"에서 끝나지 않고, free -mtopps aux/proc/meminfo 순서로 단계적으로 원인을 추적했습니다.

인프라 운영에서 메모리 이슈는 즉각적인 장애로 이어지지 않더라도, 스왑 의존 → 성능 저하 → OOM Kill 순서로 점진적으로 악화되기 때문에 조기 발견과 대응이 중요합니다.