Java 성능 최적화 + JVM 튜닝 / 가비지 컬렉션(GC) 조정
자바(Java) 애플리케이션을 운영하다 보면 “왜 이렇게 느려졌지?”라는 순간을 마주하게 됩니다.
대부분의 경우 원인은 메모리 관리와 가비지 컬렉션(GC)에 있어요.
오늘은 Java 성능 최적화와 함께 JVM 튜닝, 그리고 GC 조정 방법을 구체적으로 살펴보겠습니다.
1. JVM 메모리 구조 이해하기
JVM은 크게 Heap, Stack, Metaspace 등으로 나눠집니다. 성능 문제는 대부분 Heap 영역과 관련이 있어요.
- Young Generation → 새로 생성된 객체가 머무는 공간
- Old Generation → 오래 살아남은 객체가 이동하는 공간
- Metaspace → 클래스 메타데이터 저장 공간
GC는 주기적으로 Heap을 정리하는데, 이 과정에서 Stop-the-world가 발생해 애플리케이션이 잠시 멈출 수 있습니다.
2. GC 종류와 특징
자바는 다양한 GC 알고리즘을 제공합니다. 각각의 특징을 정리해볼게요.
① Serial GC
단일 스레드로 동작하는 GC. 간단하지만 멀티코어 환경에서는 비효율적입니다.
주로 소규모 애플리케이션이나 테스트 환경에서 사용됩니다.
② Parallel GC
멀티스레드를 사용하여 Young GC를 병렬로 처리합니다.
Throughput(처리량)이 중요한 애플리케이션에 적합합니다.
③ CMS (Concurrent Mark-Sweep) GC
애플리케이션 실행과 병행하여 Old 영역을 청소합니다.
Stop-the-world 시간이 짧지만, 메모리 단편화가 발생할 수 있어요.
④ G1 GC
Java 9 이후 기본 GC. Heap을 작은 Region 단위로 나눠 관리해 예측 가능한 응답 시간을 보장합니다.
대규모 애플리케이션에 적합합니다.
⑤ ZGC / Shenandoah
최신 GC로, 수백 GB 메모리를 가진 대규모 시스템에서도 매우 짧은 Stop-the-world 지연 시간을 제공합니다.
Java 11 이후 ZGC가 도입되었고, 최신 LTS 버전에서는 실무에서도 많이 활용됩니다.
3. GC 튜닝 실전 포인트
GC 튜닝은 단순히 “좋은 GC를 선택한다”에서 끝나지 않습니다.
실제로는 서비스 특성에 따라 메모리 크기와 옵션을 조정해야 해요.
① Heap 크기 조정
-Xms2g -Xmx2g
최소/최대 Heap 크기를 동일하게 설정해 메모리 리사이징 비용을 줄입니다.
② GC 로깅 활성화
-Xlog:gc*:file=gc.log:time,uptime,level,tags
GC 로그를 남기면 어떤 GC가 얼마나 자주 실행되는지, 얼마나 시간이 걸리는지 확인할 수 있습니다.
③ GC 선택
-XX:+UseG1GC
서비스 특성에 따라 G1GC, ZGC 등을 직접 선택해볼 수 있습니다.
4. 성능 최적화 사례
예를 들어, 대규모 트래픽을 처리하는 웹 애플리케이션에서 GC 튜닝을 하지 않으면 응답 지연이나 OutOfMemoryError가 발생할 수 있습니다.
한 사례로, Heap 크기를 늘리고 G1GC로 변경한 뒤, Full GC 빈도가 크게 줄면서 응답 속도가 30% 이상 개선된 경우가 있었습니다.
5. 성능 최적화를 위한 추가 팁
- 불필요한 객체 생성을 줄이고, 재사용 가능한 객체는 캐싱하기
- Stream API나 람다식 사용 시 객체 박싱/언박싱 비용 고려하기
- 모니터링 툴(JVisualVM, JFR, Prometheus + Grafana)로 메모리 사용량 추적
- 애플리케이션 레벨 캐싱(Redis, Caffeine 등) 적극 활용
'java' 카테고리의 다른 글
Hibernate N+1 문제 해결 방법 (JPA 성능 최적화) (0) | 2025.10.05 |
---|---|
Java Project Loom 이해하기 (0) | 2025.10.03 |
Java 병렬처리 가이드: Thread, Executor, ForkJoinPool, Parallel Stream (0) | 2025.10.02 |
Spring Security + JWT 통합 인증 구현 방법 (0) | 2025.10.01 |
Spring Security OAuth2 설정 방법 - 단계별 가이드 (0) | 2025.09.30 |