우당탕탕
2026년 Java Garbage Collector 종류와 선택 기준 직접 써보니 본문
제가 최근에 Java 애플리케이션 성능 튜닝을 하면서 2026년 최신 Garbage Collector(GC) 변경점 때문에 한참 헤맸어요. 특히 작년과 달라진 GC 기본 설정과 각 GC가 가진 특성 차이를 제대로 몰라서 수차례 재설정을 했는데, 직접 부딪혀 보니 어떤 GC를 선택해야 할지 명확해지더라고요.
이번 글에서는 2026년 기준 Java Garbage Collector 종류별 특징부터 저도 직접 경험한 선택 기준과 설정 팁까지 한눈에 정리해보려고 해요. 실제로 코드를 돌리면서 마주친 문제와 해결 과정도 상세히 담았으니 GC 선택에 고민이 있는 분들께 도움이 될 거예요.
개발 환경 / 버전 정보
이번 테스트는 Java 21과 OpenJDK 21 환경에서 진행했습니다. 2026년 현재 이 버전이 대부분 최신 서버에 적용되는 추세더라고요. 그리고 JVM 옵션들은 주로 -XX:+UseG1GC, -XX:+UseZGC, -XX:+UseShenandoahGC를 기준으로 했어요.
Java Garbage Collector 종류와 선택 기준 관련 정보
Java GC 종류와 2026년 달라진 점 이렇게 확인했어요
사실 GC 종류가 이렇게 많은지 저도 처음에 몰랐는데요. 대표적으로 Go-to GC인 G1GC, 그리고 최근 주목받는 ZGC, Shenandoah GC, 그리고 아직 일부 환경에서 쓰이는 Parallel GC, Serial GC까지 다뤄야 해요. 그런데 2026년부터는 기본 GC가 G1GC로 완전히 정착하면서 Parallel GC가 예전처럼 활성화되지 않고, 특히 ZGC와 Shenandoah는 퍼포먼스와 메모리 관리 방식이 크게 개선됐다는 점이 가장 큰 변화예요.
작년만 해도 G1GC가 기본이긴 하지만 여전히 Parallel GC 쓰는 곳이 꽤 있었던 반면, 올해는 OpenJDK 배포판 기준으로 거의 G1GC와 ZGC로 양분되는 현상이 확실해졌더라고요. 저도 이 부분을 제대로 몰라서 성능 테스트할 때 예상과 다르게 메모리 이슈가 나서 한참 고생했어요.
GC별 특징 간단 비교
- G1GC: 기본 GC. 힙을 여러 영역(Region)으로 나누고 병렬, 동시 마크를 지원. 메모리 단편화 및 긴 멈춤 시간 관리에 최적화.
- ZGC: 대규모 메모리에서 낮은 지연 시간 보장. 이제는 Linux, Windows 모두 완전 지원되며, 메모리 접근 방식 크게 최적화됨.
- Shenandoah GC: Red Hat 지원 GC로, ZGC와 비슷하게 짧은 멈춤 시간을 보장하지만 메모리 요구량이 ZGC보다 조금 더 낮은 편.
- Parallel GC: 멀티코어 환경에서 멈춤 시간 짧게 하려고 설계되었으나, 요즘은 G1GC에 밀려 점점 쓰임새가 줄어드는 추세.
- Serial GC: 단일 스레드로 동작하는 GC라 작은 애플리케이션이나 임베디드에서 극히 제한적으로 사용.
Java Garbage Collector 종류와 선택 기준 관련 정보
저는 이렇게 실제 코드에 적용해봤어요
사실 GC를 바꾸는 게 간단한 JVM 옵션만 바꾸면 되는 줄 알았는데, 각 GC마다 성능 프로파일이 너무 다르다 보니 앱 내부 설정과 튜닝 지점도 바꿔야 해서 꽤 섬세한 작업이더라고요.
예를 들어 G1GC를 쓰다가 ZGC로 바꾸면 힙 사이즈 조정, CMS(Concurrent Mark Sweep) 관련 옵션 제거, 그리고 JVM의 스레드 수 조정법도 달라집니다. 아래 코드는 Java 애플리케이션을 실행할 때 대표적으로 사용하는 GC 옵션 예시예요.
// G1GC로 실행
java -Xms4g -Xmx4g -XX:+UseG1GC -jar myapp.jar
// ZGC로 실행 (2026년부터 Windows도 안정화)
java -Xms4g -Xmx4g -XX:+UseZGC -jar myapp.jar
// Shenandoah GC 사용 시 (주로 Red Hat 기반 OS)
java -Xms4g -Xmx4g -XX:+UseShenandoahGC -jar myapp.jar
여기서 저는 ZGC를 도입했는데, 메모리 압박이 큰 대규모 애플리케이션에서 GC 멈춤 시간이 100분의 1 수준으로 줄어드는 걸 보고 충격을 받았어요. 물론 힙 메모리는 기본적으로 많이 필요하니 메모리 여유가 꼭 있어야 합니다.
Java Garbage Collector 종류와 선택 기준 관련 정보
여기서 삽질했던 부분들
이 에러가 왜 나는지 한참 찾았는데, 2026년부터 기본 GC가 엄밀히 G1GC로 바뀌면서 JVM 옵션 충돌 문제가 많이 발생했어요. 저도 처음에 옵션을 과거와 동일하게 두었다가 JVM 시작이 안 되더라고요.
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option UseConcMarkSweepGC; support was removed in Java 21.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
작년에 쓰던 -XX:+UseConcMarkSweepGC 옵션이 완전히 사라졌더라고요. 그래서 옵션 제거하고 G1GC로 변경하니 정상 실행됐습니다.
또 ZGC를 도입할 때는 -Xlog:gc* 옵션으로 로그를 꼼꼼히 분석하지 않으면 내부 GC 상태를 추적하기 어려웠어요. 로그 레벨을 높여두면 리소스 사용량이 급증하는 것도 깨달았고요.
자주 물어보시는 것들
Q. 2026년에도 Parallel GC를 선택할 이유가 있을까요?
A. 사실 요즘 서버 환경에서는 거의 G1GC나 ZGC를 추천해요. Parallel GC는 구형 JVM에서 멀티코어 활용에 특화됐지만, 최신 G1GC가 더 안정적이고 정교한 튜닝을 지원해서 신경 쓰지 않는 게 좋습니다.
Q. G1GC와 ZGC 중 어떤 걸 기본으로 써야 할까요?
A. 서비스 성격에 따라 달라요. 낮은 GC 멈춤 시간이 필수인 초대형 메모리 애플리케이션은 ZGC가 낫고, 보통 규모에서 안정성과 튜닝 용이성을 원하면 G1GC가 무난합니다.
Q. Shenandoah GC는 언제 써야 할까요?
A. Red Hat Linux 기반 환경에서 ZGC가 지원되지 않거나 호환성 이슈가 있을 때 선택하는 경우 많아요. 짧은 멈춤 시간과 낮은 메모리 오버헤드의 균형이 필요할 때 적합합니다.
마지막으로 Java GC 선택의 핵심은 ‘서비스의 메모리 패턴과 CPU 리소스 상황, 그리고 지연시간 목표’에 맞춰 직접 여러 GC를 돌려보고 로그와 프로파일링 결과를 비교하는 거예요. 저도 이번에 학습하면서 만만치 않았는데, 2026년부터는 기본 GC 정책이나 지원하는 플랫폼 범위가 계속 진화하니 업데이트된 공식 문서도 수시로 확인하는 걸 추천합니다.
'언어 > Java' 카테고리의 다른 글
| Java 예외 처리, Checked와 Unchecked를 실제로 언제 써야 할까 (0) | 2026.09.03 |
|---|---|
| Java 17에서 실무에 바로 써먹는 새로운 기능들 체크리스트 (0) | 2026.08.27 |
| Java Optional 제대로 쓰는 법과 흔한 안티패턴 사례 비교 (0) | 2026.08.07 |
| Java 예외 처리에서 Checked와 Unchecked, 비용 차이로 이해하기 (0) | 2026.07.30 |
| Java 17 새로운 기능, 실무에 바로 적용하는 절차 중심 가이드 (0) | 2026.07.23 |
