Skip to Content
BackendJVM GC 튜닝 시작 전 필수 준비: 모니터링 활성화와 튜닝 필요성 판단
💻 Backend2018년 10월 11일

JVM GC 튜닝 시작 전 필수 준비: 모니터링 활성화와 튜닝 필요성 판단

#jvm#java#gc#monitoring#backend#performance

대규모 백엔드 시스템을 운영하다 보면 무턱대고 JVM Heap 옵션(-Xms, -Xmx)부터 건드리고 보는 이른바 ‘묻지마 튜닝’ 의 유혹에 빠지기 쉽습니다. 사내 빅데이터 모니터링 플랫폼의 대용량 데이터 콜렉터 데몬을 개발할 때, 저희는 튜닝에 돌입하기 전 “지금 우리 시스템이 정말 튜닝이 필요한 상태인가?” 를 철저히 검증하는 사전 단계를 거쳤습니다.

튜닝은 완벽히 동작하는 코드를 망가뜨릴 위험을 내포하고 있어, 객관적인 모니터링 데이터를 바탕으로 결정을 내려야 합니다.


1. GC 튜닝이 (아직) 필요 없는 조건

로그와 프로파일링 도구를 붙여 며칠간 관찰했을 때, 아래 지표 안에 들어온다면 GC 튜닝보다 인프라 스케일 아웃이나 로직 개선을 먼저 고민하는 것이 좋습니다.

지표양호한 기준위험 신호
Minor GC 처리 시간평균 50ms 이내100ms 초과
Minor GC 발생 주기10초 이상2~3초 이하
Full GC 처리 시간1초 이내수 초 이상 (STW 체감)
Full GC 발생 주기10분에 1회 미만수 분마다 발생
Heap 사용률 (Old Gen)80% 이하 안정 유지지속적으로 90%↑

이 기준을 벗어나서 STW(Stop-The-World) 현상 때문에 장애 알람이 계속 울린다면 GC 튜닝 실전 단계로 진입할 차례입니다.


2. jstat으로 현재 GC 상태 진단

튜닝 전 가장 빠르게 현황을 파악하는 방법은 jstat입니다.

shell
# PID 확인 $ jps -l # 1초(1000ms) 간격으로 GC 통계 출력 $ jstat -gcutil <PID> 1000
plaintext
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 47.02 83.14 32.01 95.72 92.11 152 6.343 3 1.512 7.855
컬럼의미체크 포인트
EEden 영역 사용률(%)100%에 닿으면 Minor GC 발생
OOld 영역 사용률(%)지속 상승 → 메모리 릭 의심
YGC / YGCTMinor GC 횟수 / 총 소요 시간YGCT/YGC 로 평균 시간 계산
FGC / FGCTFull GC 횟수 / 총 소요 시간FGC가 자주 올라가면 위험

3. 모니터링 도구 활성화 설정

jstatd 원격 접속 허용

GUI 모니터링 툴(VisualVM 등)이 에이전트 없이 JVM 힙 상태를 원격으로 가져갈 수 있도록 tools.policy 파일을 설정합니다.

shell
$ vi /tmp/tools.policy
text
grant codebase "file:${java.home}/../lib/tools.jar" { permission java.security.AllPermission; };
shell
# jstatd 백그라운드 실행 $ jstatd -J-Djava.security.policy=/tmp/tools.policy &

② Tomcat setenv.sh: JMX 및 GC 로그 활성화

catalina.sh 또는 setenv.sh에 추가하여 JVM 구동과 동시에 내부 모니터링 포트(9898)를 열고 이벤트 단위로 GC 로그를 파일에 기록합니다.

shell
# JMX 원격 접속 허용 (VisualVM 연결용) -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9898 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false # GC 로그 파일 기록 (GCEasy 등 분석 도구의 입력값) -verbose:gc -Xloggc:../logs/gc.log -XX:+PrintGCDateStamps -XX:+PrintGCDetails # GC 로그 로테이션 (로그 무한 증가 방지) -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20m # OOM 발생 시 Heap Dump 자동 생성 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=../logs/heap-dump.hprof

[실무 팁] STW로 갑자기 서버가 내려갔을 때, 뒤늦게 “아 GC 로그 켜둘걸!” 하고 후회하는 상황이 자주 있습니다. 운영 서버에 올리기 전, 기본 템플릿으로 위 옵션들을 반드시 심어두는 것을 강력히 권장합니다.


4. GC 로그 파일 읽기

활성화한 GC 로그는 아래 형태로 쌓입니다. 패턴을 익혀두면 눈으로 대략적인 이상 상황을 감지할 수 있습니다.

plaintext
2018-10-11T14:23:01.452+0900: 52.123: [GC (Allocation Failure) [PSYoungGen: 131072K->12345K(153600K)] 143210K->24511K(503808K), 0.0231450 secs] [Times: user=0.09 sys=0.01, real=0.02 secs]
항목의미
Allocation FailureEden이 꽉 찼을 때 Minor GC 발생(정상)
PSYoungGen: 131072K→12345KMinor GC 전후 Young 영역 사용량
0.0231 secs이번 GC에 걸린 STW 시간
user=0.09GC 스레드가 실제 CPU를 쓴 시간

[위험 신호 패턴]

plaintext
[Full GC (Ergonomics) ...] 2.345 secs ← 2초 넘는 Full GC [Full GC (System.gc()) ...] ← 코드에서 강제 GC 호출 (안티패턴!) [GC (GCLocker Initiated GC) ...] ← JNI 코드가 GC를 막고 있음

5. GCEasy로 자동 분석

GC 로그 파일을 GCEasy 에 업로드하면 처리량(Throughput), 최대 STW 시간, 메모리 효율 등을 시각화된 리포트로 받아볼 수 있습니다. 튜닝 전/후 로그를 각각 올려 효과를 수치로 비교하는 데 특히 유용합니다.


참고 자료

Last updated on