안녕하세요! 재아군의 관찰인생 입니다.
오늘은 Gradle 빌드에서의 JVM 가비지 컬렉터(GC) 설정 방법에 대해 알아보려고 합니다.
많은 개발자가 gradle.properties에서 -Xmx만 늘리고 끝내지만,
GC 알고리즘 선택 하나로 빌드 속도를 9~20% 추가 개선할 수 있습니다.
특히 Android 빌드처럼 컴파일 중심의 워크로드에서는 GC 선택이 체감 성능에 큰 영향을 미칩니다.

Gradle에서 GC 설정이란?
- 📌 공식 문서: Gradle JVM Memory Configuration
- Gradle은 JVM 위에서 동작하므로, Gradle 데몬의 GC 알고리즘과 메모리 설정이 빌드 성능에 직접적인 영향을 미칩니다.
gradle.properties의org.gradle.jvmargs에 GC 플래그를 지정하면, Gradle 데몬이 해당 GC를 사용하여 메모리를 관리합니다.- 📢 핵심 포인트: JDK 9 이후 G1GC가 기본 GC이지만, Gradle 빌드(컴파일 중심 워크로드)에는 Parallel GC가 더 적합한 경우가 많습니다. Google의 Android 공식 문서에서도 Parallel GC를 권장합니다.
GC 알고리즘 비교
| 항목 | Parallel GC | G1GC | ZGC | Serial GC |
|---|---|---|---|---|
| JVM 플래그 | -XX:+UseParallelGC |
-XX:+UseG1GC |
-XX:+UseZGC |
-XX:+UseSerialGC |
| 설계 목표 | 처리량(Throughput) 최대화 | 처리량 + 지연시간 균형 | 초저지연 (10ms 이하) | 최소 리소스 사용 |
| GC 스레드 | 멀티 스레드 | 멀티 스레드 (동시성) | 멀티 스레드 (동시성) | 단일 스레드 |
| STW 일시정지 | 중간~길음 | 짧음 (목표 200ms) | 극히 짧음 (<10ms) | 가장 길음 |
| 힙 크기 적합성 | 중 |
대 (4GB+) | 초대형 (8MB~16TB) | 소 (<100MB) |
| CPU 오버헤드 | 낮음 | 중간 | 높음 | 가장 낮음 |
| 메모리 오버헤드 | 낮음 | 중간 | 높음 | 가장 낮음 |
| Gradle 빌드 적합도 | ⭐⭐⭐ 최적 | ⭐⭐ 양호 (기본값) | ⭐ 과도함 | ❌ 부적합 |
| 최소 JDK 버전 | JDK 5+ | JDK 7+ (기본: JDK 9+) | JDK 15+ (프로덕션) | JDK 5+ |
왜 Parallel GC가 Gradle에 최적인가?
Gradle 빌드는 배치 처리(batch processing) 성격의 워크로드입니다. 짧은 지연시간보다 전체 처리량이 중요합니다. Parallel GC는 GC 자체의 CPU/메모리 오버헤드가 낮아 컴파일 작업에 더 많은 리소스를 할당할 수 있습니다. 실제 벤치마크에서 G1GC 대비 9~20%의 빌드 시간 단축이 보고되었습니다.
설정 방법
사전 체크리스트
- JDK 버전 확인 — JDK 17 이상 권장 (GC 성능이 JDK 버전마다 크게 개선됨)
- 현재 GC 확인 — 기본값은 G1GC (JDK 9 이후)
- Build Analyzer 확인 — GC가 빌드 시간의 15% 이상을 차지하는지 확인
- 가용 메모리 확인 — 시스템 RAM 대비 적절한 힙 크기 설정
# 현재 JDK 버전 및 기본 GC 확인
java -version
java -XX:+PrintCommandLineFlags -version 2>&1 | grep -i "Use.*GC"
# Gradle 데몬의 JVM 인자 확인
./gradlew --status
./gradlew properties | grep jvmargs
방법 1: gradle.properties에서 설정 (프로젝트별 — 권장)
프로젝트 루트의 gradle.properties 파일에 설정합니다. 팀 전체가 동일한 설정을 공유할 수 있어 가장 권장되는 방법입니다.
# ============================================
# gradle.properties — GC 최적화 설정
# ============================================
# ✅ 권장: Parallel GC (컴파일 중심 워크로드에 최적)
org.gradle.jvmargs=-Xmx4g \
-XX:+UseParallelGC \
-XX:MaxMetaspaceSize=1g \
-XX:+HeapDumpOnOutOfMemoryError \
-Dfile.encoding=UTF-8
# ⚠️ 대안: G1GC (기본값 유지, 대규모 힙에서 안정적)
# org.gradle.jvmargs=-Xmx6g \
# -XX:+UseG1GC \
# -XX:MaxGCPauseMillis=200 \
# -XX:MaxMetaspaceSize=1g \
# -XX:+HeapDumpOnOutOfMemoryError \
# -Dfile.encoding=UTF-8
# ❌ 비권장: ZGC (빌드에는 오버헤드가 과도함)
# org.gradle.jvmargs=-Xmx8g \
# -XX:+UseZGC \
# -XX:MaxMetaspaceSize=1g \
# -Dfile.encoding=UTF-8
방법 2: 글로벌 설정 (사용자별)
모든 Gradle 프로젝트에 공통으로 적용하려면 ~/.gradle/gradle.properties에 설정합니다.
# 글로벌 gradle.properties 생성/편집
mkdir -p ~/.gradle
cat >> ~/.gradle/gradle.properties << 'EOF'
org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
EOF
방법 3: 명령줄에서 일회성 지정
# 특정 빌드에서만 GC 변경하여 테스트
./gradlew build -Dorg.gradle.jvmargs="-Xmx4g -XX:+UseParallelGC"
# 또는 환경변수로 지정
export GRADLE_OPTS="-Xmx4g -XX:+UseParallelGC"
./gradlew build
방법 4: build.gradle.kts에서 포크된 컴파일러 GC 설정
Gradle 데몬의 GC와 별도로, 포크된 Java 컴파일러의 JVM 인자도 설정할 수 있습니다.
// build.gradle.kts
tasks.withType<JavaCompile>().configureEach {
options.isFork = true
options.forkOptions.jvmArgs = listOf(
"-Xmx512m",
"-XX:+UseParallelGC"
)
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions.jvmTarget = "17"
}
프로젝트 규모별 권장 설정
소규모 프로젝트 (단일 모듈, 소스 파일 <500개)
org.gradle.jvmargs=-Xmx2g -XX:+UseParallelGC -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8
org.gradle.daemon=true
org.gradle.caching=true
중규모 프로젝트 (5~15개 모듈)
org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
대규모 프로젝트 (15개+ 모듈, Android 멀티 모듈)
org.gradle.jvmargs=-Xmx6g -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
org.gradle.workers.max=4
초대규모 프로젝트 (50개+ 모듈, 모노레포)
# G1GC가 더 나을 수 있음 (힙이 8GB 이상이면 G1의 리전 기반 관리가 유리)
org.gradle.jvmargs=-Xmx8g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:MaxMetaspaceSize=2g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
org.gradle.workers.max=8
활용 시나리오 (실전 예시)
시나리오 1: G1GC → Parallel GC 전환으로 Android 빌드 개선
# 변경 전 (G1GC 기본값)
$ cat gradle.properties
org.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8
$ ./gradlew assembleDebug --profile
# BUILD SUCCESSFUL in 1m 48s
# 변경 후 (Parallel GC 적용)
$ cat gradle.properties
org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8
$ ./gradlew assembleDebug --profile
# BUILD SUCCESSFUL in 1m 29s ✅ 약 18% 단축!
시나리오 2: GC 스래싱(Thrashing) 해결
# 증상: 데몬이 갑자기 중지됨
# "Gradle build daemon has been stopped:
# JVM garbage collector thrashing and after running out of JVM memory"
# 원인: 힙 메모리 부족으로 GC가 계속 반복 실행
# 해결: 힙 크기 증가 + Parallel GC 전환
# 변경 전
org.gradle.jvmargs=-Xmx1g
# 변경 후
org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
시나리오 3: A/B 벤치마크로 최적 GC 찾기
#!/bin/bash
# gc-benchmark.sh — GC별 빌드 시간 비교 스크립트
echo "=== GC 벤치마크 시작 ==="
# 캐시 초기화
./gradlew clean
rm -rf ~/.gradle/caches/build-cache-*
# 1) G1GC (기본값) 테스트
echo "--- G1GC 테스트 ---"
./gradlew build -Dorg.gradle.jvmargs="-Xmx4g -XX:+UseG1GC" --profile
# 프로파일 리포트 확인: build/reports/profile/
./gradlew clean
# 2) Parallel GC 테스트
echo "--- Parallel GC 테스트 ---"
./gradlew build -Dorg.gradle.jvmargs="-Xmx4g -XX:+UseParallelGC" --profile
./gradlew clean
# 3) ZGC 테스트 (JDK 15+ 필요)
echo "--- ZGC 테스트 ---"
./gradlew build -Dorg.gradle.jvmargs="-Xmx4g -XX:+UseZGC" --profile
echo "=== 벤치마크 완료 ==="
echo "build/reports/profile/ 에서 결과를 비교하세요."
GC 관련 JVM 옵션 상세 레퍼런스
# ================================================
# 메모리 크기 설정
# ================================================
-Xmx4g # 최대 힙 크기 (필수)
-Xms2g # 초기 힙 크기 (선택, Xmx와 동일하게 설정 시 리사이징 오버헤드 제거)
-XX:MaxMetaspaceSize=1g # 메타스페이스 최대 크기 (클래스 메타데이터)
# ================================================
# GC 알고리즘 선택 (하나만 선택)
# ================================================
-XX:+UseParallelGC # Parallel GC — Gradle 빌드에 권장
-XX:+UseG1GC # G1GC — JDK 9+ 기본값
-XX:+UseZGC # ZGC — JDK 15+, 초저지연 필요 시
-XX:+UseSerialGC # Serial GC — 테스트/소규모 전용
# ================================================
# Parallel GC 튜닝 옵션
# ================================================
-XX:ParallelGCThreads=4 # GC 스레드 수 (기본: CPU 코어 수)
-XX:MaxGCPauseMillis=200 # 목표 GC 일시정지 시간 (ms)
# ================================================
# G1GC 튜닝 옵션
# ================================================
-XX:G1HeapRegionSize=4m # G1 리전 크기 (1~32MB, 자동 결정)
-XX:MaxGCPauseMillis=200 # 목표 일시정지 시간
-XX:InitiatingHeapOccupancyPercent=45 # 마킹 사이클 시작 힙 점유율
-XX:ConcGCThreads=2 # 동시 GC 스레드 수
# ================================================
# 진단 및 디버깅
# ================================================
-XX:+HeapDumpOnOutOfMemoryError # OOM 발생 시 힙 덤프 자동 생성
-XX:HeapDumpPath=/tmp/gradle-heapdump.hprof # 힙 덤프 저장 경로
-Xlog:gc*:file=gc.log:time # GC 로그 파일 출력 (JDK 9+)
-verbose:gc # GC 활동 콘솔 출력 (JDK 8)
트러블슈팅
문제 1: "JVM garbage collector thrashing" 오류로 데몬 중지
Gradle build daemon has been stopped:
JVM garbage collector thrashing and after running out of JVM memory
원인: 힙 메모리가 부족하여 GC가 대부분의 시간을 메모리 회수에 사용하는 상태입니다.
해결:
# 1단계: 힙 크기 증가
org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g
# 2단계: 여전히 발생하면 6g → 8g로 점진적 증가
org.gradle.jvmargs=-Xmx6g -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g
# 3단계: 데몬 재시작
./gradlew --stop
./gradlew build
문제 2: Build Analyzer에서 GC가 15% 이상 차지
해결:
# Parallel GC로 전환 + 힙 크기 증가
org.gradle.jvmargs=-Xmx6g -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
문제 3: ZGC 사용 시 "Unrecognized VM option" 오류
Unrecognized VM option 'UseZGC'
Error: Could not create the Java Virtual Machine.
원인: JDK 버전이 15 미만이거나, JDK 배포판이 ZGC를 지원하지 않습니다.
해결:
# JDK 버전 확인
java -version
# JDK 17 이상으로 업그레이드 후 재시도
문제 4: Parallel GC 설정 후 오히려 느려짐
원인: 힙이 매우 크거나 (8GB+) 모듈이 극히 많은 경우, G1GC의 리전 기반 관리가 더 효율적일 수 있습니다.
해결:
# 대규모 힙에서는 G1GC + 튜닝이 더 나을 수 있음
org.gradle.jvmargs=-Xmx8g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:MaxMetaspaceSize=2g -Dfile.encoding=UTF-8
자주 묻는 질문 (FAQ)
Q1: Gradle에서 기본 GC는 무엇인가요?
JDK 9 이후로는 G1GC가 기본입니다. Gradle 자체가 GC를 별도로 지정하지 않으므로, JDK의 기본 GC가 그대로 사용됩니다. JDK 8 이하에서는 Parallel GC가 기본이었습니다.
Q2: Parallel GC로 바꾸면 빌드 중 앱이 멈추지 않나요?
Gradle 빌드 중의 "멈춤(STW)"은 IDE가 잠시 멈추는 것이 아니라, Gradle 데몬 JVM 내부의 일시정지를 의미합니다. 빌드는 배치 처리 성격이므로 짧은 STW보다 전체 처리량이 중요합니다. Parallel GC가 GC 자체에 쓰는 CPU/메모리가 적어서 결과적으로 빌드 전체가 빨라집니다.
Q3: -Xmx와 GC 선택 중 무엇이 더 중요한가요?
-Xmx(힙 크기)가 먼저입니다. 힙이 부족하면 어떤 GC를 쓰든 스래싱이 발생합니다. 충분한 힙을 확보한 후에 GC 알고리즘을 선택하세요. 순서: ①힙 크기 → ②GC 선택 → ③세부 튜닝.
Q4: CI 서버에서도 Parallel GC를 써야 하나요?
네, CI에서도 효과적입니다. CI는 특히 처리량이 중요하므로 Parallel GC가 잘 맞습니다. 다만 CI 서버의 가용 메모리에 맞게
-Xmx를 조정하세요.
Q5: GC 로그는 어떻게 확인하나요?
JDK 9 이상에서는
-Xlog:gc*:file=gc.log:time플래그를 추가하면gc.log파일에 GC 활동이 기록됩니다. GCEasy 같은 온라인 도구에 업로드하면 시각적으로 분석할 수 있습니다.
Gradle 빌드 최적화에서 GC 설정은 "마지막 10%"를 끌어올리는 핵심 튜닝 포인트입니다.
먼저 힙 크기를 충분히 확보하고, Parallel GC를 적용한 뒤, 프로파일 리포트로 효과를 확인해 보세요!
'개발&프로그래밍' 카테고리의 다른 글
| JVM GC 로그 분석 방법 (G1GC 패턴 해석 + 실전 예시) - G1GC 로그 읽는 법 완전 정복 (0) | 2026.02.20 |
|---|---|
| [Gradle] 빌드 속도 개선 방법 - 느린 빌드, 설정 하나로 50~70% 단축하기 (0) | 2026.02.19 |
| [SpringBoot] 로그 잘림 해결 방법 - 콘솔 / 파일 로그 길이 제한 완전 정리 (0) | 2026.02.19 |
| [JVM] [OutOfMemoryError 해결] - 원인 분석부터 완벽 해결까지 실전 가이드 (0) | 2026.02.18 |
| [Codex] 프롬프트 작성법 - Codex를 200% 활용하는 비법 완전 가이드 (0) | 2026.02.18 |
댓글