본문 바로가기
개발&프로그래밍

[Gradle] 빌드 속도 개선 방법 - 느린 빌드, 설정 하나로 50~70% 단축하기

by 재아군 2026. 2. 19.
반응형

안녕하세요! 재아군의 관찰인생 입니다.

오늘은 Gradle 빌드 속도 개선에 대해 알아보려고 합니다.

프로젝트 규모가 커질수록 빌드 시간은 기하급수적으로 늘어나고, 개발자의 생산성을 심각하게 떨어뜨립니다.

2025년 기준 Gradle 9.x가 출시되면서 Configuration Cache가 기본 실행 모드로 격상되는 등 빌드 성능 최적화에 대한 관심이 그 어느 때보다 높아졌습니다.


Gradle 빌드 최적화란?

  • 📌 공식 문서: Improve the Performance of Gradle Builds
  • Gradle 빌드 최적화란, 캐싱·병렬 실행·증분 빌드 등의 기법을 활용하여 불필요한 작업을 제거하고 빌드 시간을 단축하는 일련의 과정입니다.
  • 핵심 원칙은 "이미 한 일은 다시 하지 않는다" 입니다. Gradle은 입력이 변하지 않은 태스크의 출력을 재사용하여 빌드를 가속합니다.
  • 📢 최신 업데이트: Gradle 9.3.1 (2026-01-29 릴리스)이 최신 안정 버전이며, Gradle 9.0부터 Configuration Cache가 기본 권장 실행 모드로 전환되었습니다. Kotlin 2.2 런타임 내장, Groovy 4 지원, SemVer 채택 등 대규모 변화가 있습니다.

 

 

 

다른 빌드 도구와의 비교

항목 Gradle Maven Bazel sbt
언어 Kotlin DSL / Groovy DSL XML (POM) Starlark Scala
증분 빌드 ✅ 네이티브 지원 ❌ 제한적 ✅ 지원 ✅ 지원
빌드 캐시 ✅ 로컬 + 리모트 ❌ (플러그인 필요) ✅ 리모트 캐시 ❌ 제한적
병렬 실행 ✅ 태스크 단위 ⚠️ 모듈 단위만 ✅ 태스크 단위 ✅ 지원
Configuration Cache ✅ (Gradle 9 기본) N/A
대규모 멀티 모듈 ⭐ 우수 ⚠️ 보통 ⭐ 우수 ⚠️ 보통
학습 곡선 중간 낮음 높음 높음
Android 공식 지원

 

 

 

사전 체크리스트 (최적화 전 확인사항)

최적화를 시작하기 전에 반드시 아래 항목을 확인하세요:

  • 현재 Gradle 버전 확인 — 최신 버전(9.3.1)을 사용하고 있는가?
  • JDK 버전 확인 — JDK 17 이상을 사용하고 있는가?
  • 기준선(Baseline) 측정 — Build Scan 또는 프로파일 리포트로 현재 빌드 시간을 기록했는가?
  • 불필요한 의존성 정리 — 사용하지 않는 라이브러리가 있는가?
  • 동적 버전(+) 사용 여부com.example:lib:1.0+ 같은 동적 의존성이 있는가?
# 현재 Gradle 버전 확인
./gradlew --version

# 빌드 프로파일 리포트 생성
./gradlew build --profile

# Build Scan 생성 (Develocity)
./gradlew build --scan

 

 

 

설치 및 업그레이드 방법

방법 1: Gradle Wrapper 업그레이드 (권장)

프로젝트에 이미 Gradle Wrapper가 있다면, 아래 명령으로 간단히 최신 버전으로 업그레이드할 수 있습니다.

# Gradle Wrapper를 최신 버전으로 업그레이드
./gradlew wrapper --gradle-version=9.3.1 && ./gradlew wrapper

# 업그레이드 확인
./gradlew --version

방법 2: SDKMAN으로 설치 (Linux/macOS)

# SDKMAN 설치
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"

# Gradle 설치
sdk install gradle 9.3.1

# 버전 확인
gradle --version

방법 3: Homebrew로 설치 (macOS)

brew install gradle

# 또는 특정 버전
brew install gradle@9

방법 4: 수동 설치 (Windows/Linux)

# 1. 바이너리 다운로드
wget https://services.gradle.org/distributions/gradle-9.3.1-bin.zip

# 2. 압축 해제
unzip gradle-9.3.1-bin.zip -d /opt/gradle

# 3. 환경변수 설정 (~/.bashrc 또는 ~/.zshrc)
export GRADLE_HOME=/opt/gradle/gradle-9.3.1
export PATH=$PATH:$GRADLE_HOME/bin

 

 

 

핵심 최적화 설정 — gradle.properties

프로젝트 루트의 gradle.properties 파일에 아래 설정을 추가하세요. 이것만으로도 빌드 시간을 50~70% 단축할 수 있습니다.

# ============================================
# Gradle 빌드 속도 최적화 설정
# ============================================

# 1. Gradle 데몬 활성화 (백그라운드 프로세스 유지)
org.gradle.daemon=true

# 2. 병렬 빌드 (멀티 모듈 프로젝트 필수)
org.gradle.parallel=true

# 3. 빌드 캐시 활성화 (동일 입력 → 캐시된 출력 재사용)
org.gradle.caching=true

# 4. Configuration Cache 활성화 (Gradle 9 기본 권장)
org.gradle.configuration-cache=true

# 5. JVM 메모리 설정 (프로젝트 규모에 따라 조정)
org.gradle.jvmargs=-Xmx4g -XX:+HeapDumpOnOutOfMemoryError \
  -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g

# 6. 워커 프로세스 수 (CPU 코어 수에 맞게 조정)
org.gradle.workers.max=4

각 설정의 효과

설정 역할 예상 효과
daemon=true 빌드 간 JVM 프로세스 재사용 콜드 스타트 제거
parallel=true 독립적인 모듈 동시 빌드 멀티 모듈에서 큰 효과
caching=true 태스크 출력 캐싱 클린 빌드도 빠르게
configuration-cache=true 설정 단계 결과 캐싱 2분 → 40초 사례 있음
jvmargs -Xmx4g 충분한 힙 메모리 할당 GC 오버헤드 감소
workers.max 병렬 워커 수 제한 리소스 최적 배분

 

 

 

고급 최적화 기법

1. api vs implementation 의존성 분리

// build.gradle.kts
dependencies {
    // ❌ 나쁜 예: 모든 의존성을 api로 선언
    // api("com.google.code.gson:gson:2.10.1")

    // ✅ 좋은 예: 내부에서만 쓰는 의존성은 implementation
    implementation("com.google.code.gson:gson:2.10.1")

    // 외부 모듈에 노출해야 할 때만 api 사용
    api("com.squareup.retrofit2:retrofit:2.9.0")
}

apiimplementation 전환 시 하위 프로젝트 재컴파일 범위가 줄어들어 증분 빌드가 크게 빨라집니다.

 

2. 동적 버전 제거

// ❌ 매 빌드마다 최신 버전을 확인하느라 느려짐
implementation("com.example:library:1.0+")

// ✅ 고정 버전 사용
implementation("com.example:library:1.0.3")

 

3. Java 컴파일 포크 (대규모 프로젝트)

// build.gradle.kts
tasks.withType<JavaCompile>().configureEach {
    options.isFork = true
    options.forkOptions.memoryMaximumSize = "512m"
}

1,000개 이상의 소스 파일을 컴파일하는 태스크에서 효과적입니다. 별도 JVM에서 컴파일하여 메인 Gradle 프로세스의 GC 부담을 줄여줍니다.

 

4. Non-Transitive R 클래스 (Android)

// gradle.properties
android.nonTransitiveRClass=true

Android Gradle Plugin 8.0 이상에서 기본 활성화됩니다. 각 모듈의 R 클래스가 자신의 리소스만 참조하여 리소스 중복을 방지합니다.

 

5. 디버그 빌드 최적화 (Android)

// build.gradle.kts (app 모듈)
android {
    buildTypes {
        debug {
            // PNG 크런칭 비활성화 (AGP 3.0+에서 기본 비활성화)
            isCrunchPngs = false
        }
    }
}

// Crashlytics 비활성화 (디버그 빌드)
android {
    buildTypes {
        debug {
            extra["enableCrashlytics"] = false
        }
    }
}

6. 이미지를 WebP로 변환

PNG/JPEG 대신 WebP 형식을 사용하면 빌드 시 이미지 압축 과정을 생략할 수 있습니다. Android Studio에서 마우스 우클릭 → Convert to WebP로 간단히 변환 가능합니다.


 

 

활용 시나리오 (실전 예시)

시나리오 1: 멀티 모듈 Android 프로젝트 (빌드 2분 30초 → 40초)

# 현재 상태 확인
$ ./gradlew build --profile
# BUILD SUCCESSFUL in 2m 30s

# gradle.properties 최적화 적용 후
$ ./gradlew build --profile
# BUILD SUCCESSFUL in 42s  ✅ 약 72% 단축!
# gradle.properties
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
org.gradle.jvmargs=-Xmx6g -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g

 

 

시나리오 2: CI/CD 파이프라인에서 리모트 캐시 활용

// settings.gradle.kts
buildCache {
    local {
        isEnabled = true
        directory = File(rootDir, ".gradle/build-cache")
    }
    remote<HttpBuildCache> {
        url = uri("https://your-cache-server.example.com/cache/")
        isPush = System.getenv("CI") != null  // CI에서만 캐시 업로드
        isEnabled = true
    }
}
# CI에서 빌드 (캐시 push)
$ ./gradlew clean build --build-cache
# BUILD SUCCESSFUL in 5s  (캐시 히트 시)

 

 

시나리오 3: Build Scan으로 병목 구간 분석

# Build Scan 생성
$ ./gradlew build --scan

# 출력 예시:
# Publishing build scan...
# https://gradle.com/s/abcdefgh  ← 이 링크로 상세 분석 가능

# 로컬 프로파일 리포트 (Build Scan 대안)
$ ./gradlew build --profile
# 리포트 위치: build/reports/profile/profile-2026-02-17-10-30-00.html

Build Scan의 Timeline 뷰에서 가장 오래 걸리는 태스크를 식별하고, Performance 탭에서 캐시 적중률을 확인하세요.


 

 

트러블슈팅

문제 1: Configuration Cache 호환성 오류

* What went wrong:
Configuration cache state could not be cached:
  - Plugin 'com.example.plugin': cannot serialize object of type ...

해결:

// 호환되지 않는 플러그인 확인 후, 임시로 비활성화
// gradle.properties
org.gradle.configuration-cache=false

// 또는 특정 태스크에서만 비활성화
// 터미널에서
./gradlew build --no-configuration-cache

문제 2: 메모리 부족 (OutOfMemoryError)

java.lang.OutOfMemoryError: Java heap space

해결:

# gradle.properties — 힙 메모리 증가
org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError \
  -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g

문제 3: 빌드 캐시가 동작하지 않음

# 캐시 상태 확인
$ ./gradlew build --build-cache --info | grep -i cache

# 캐시 디렉토리 정리 후 재시도
$ rm -rf ~/.gradle/caches/build-cache-*
$ ./gradlew build --build-cache

문제 4: Gradle 데몬이 느려짐

# 실행 중인 데몬 확인
$ ./gradlew --status

# 모든 데몬 중지 후 재시작
$ ./gradlew --stop
$ ./gradlew build

자주 묻는 질문 (FAQ)

Q1: gradle.properties 설정만 바꿔도 효과가 있나요?

네. daemon, parallel, caching, configuration-cache 4가지 설정만으로도 50% 이상의 빌드 시간 단축을 경험하는 사례가 많습니다. 실제로 2분 30초 → 35~45초로 줄었다는 보고도 있습니다.

 

 

Q2: Configuration Cache와 Build Cache는 다른 건가요?

다릅니다. Build Cache는 태스크의 입출력을 캐싱하여 동일 입력 시 재실행을 건너뜁니다. Configuration Cache는 빌드 설정 단계(configuration phase)의 결과를 캐싱하여 설정 단계 자체를 건너뜁니다. 둘 다 함께 사용하면 최대 효과를 볼 수 있습니다.

 

 

Q3: Gradle 8.x에서 9.x로 업그레이드하면 빌드가 깨질 수 있나요?

메이저 버전 업그레이드이므로 일부 호환성 문제가 발생할 수 있습니다. Gradle은 9.x 업그레이드 가이드를 제공하고 있으며, deprecated API 제거와 Kotlin 2.2 전환 등의 변경사항을 확인해야 합니다.

 

 

Q4: org.gradle.jvmargs-Xmx 값은 얼마로 설정해야 하나요?

프로젝트 규모에 따라 다릅니다. 소규모(4GB), 중규모(6GB), 대규모(8GB)로 시작해서 Build Analyzer에서 GC가 빌드 시간의 15% 이상을 차지하면 메모리를 늘리세요.

 

 

Q5: CI 환경에서도 동일한 최적화가 적용되나요?

대부분 적용됩니다. 다만 CI에서는 리모트 빌드 캐시(Develocity 또는 자체 HTTP 캐시 서버)를 설정하면 팀 전체가 캐시를 공유하여 훨씬 큰 효과를 볼 수 있습니다.

 


설정 몇 줄이 여러분의 개발 생산성을 극적으로 바꿀 수 있습니다.

오늘 소개한 방법들을 하나씩 적용하면서 Build Scan으로 효과를 측정해 보세요!

 

반응형

댓글