Gradle은 Android 애플리케이션의 컴파일, 테스트 및 패키징을 자동화하는 빌드 시스템입니다. Apache Ant 또는 Maven과 달리 증분 빌드와 결과 캐싱을 지원합니다. 자세한 내용은 Gradle 공식 문서를 참조하세요. 2013년부터 이 도구는 Android Studio에서 Android 프로젝트의 표준 빌드 시스템으로 사용되고 있습니다.
핵심 요점
Gradle은 Java로 작성되고 JVM에서 실행되는 오픈소스 빌드 자동화 도구입니다. 소스 코드, 종속성 및 리소스를 입력으로 받아 Android용 APK 또는 AAB와 같은 준비된 애플리케이션을 출력으로 생성합니다. 핵심적으로 Gradle은 태스크의 방향성 비순환 그래프(DAG) 개념을 사용합니다. 각 태스크는 작업의 원자 단위이며, 태스크 간의 연결이 실행 순서를 결정합니다. Make나 Ant와 달리 Gradle은 수동으로 단계 순서를 설명할 필요가 없습니다. 태스크 간의 종속성을 선언하기만 하면 시스템이 자체적으로 최적의 순서를 결정합니다. 이 접근 방식은 Gradle을 모든 규모의 프로젝트에 유연하고 확장 가능하게 만듭니다.
시스템은 세 가지 실행 단계를 사용합니다: 초기화(참여 프로젝트 식별), 설정(태스크 그래프 구축), 실행(필요한 순서로 태스크 실행). 설정 단계는 Gradle의 핵심 차별점입니다: 태스크가 시작되기 전에 전체 빌드 스크립트가 실행되어 조건에 따라 그래프를 동적으로 변경할 수 있습니다. 이를 통해 예를 들어 코드를 중복하지 않고 특정 빌드 변형에만 태스크를 추가할 수 있습니다. 빌더는 Groovy로 작성되었지만 설정 파일은 Groovy DSL과 Kotlin DSL 두 가지 언어를 지원합니다.
Gradle용 Android 플러그인은 com.android.application과 com.android.library로 구성되며, Android 도구 작업을 위한 태스크를 프로젝트에 추가합니다. 개발자가 빌드를 시작하면 Gradle은 수십 개의 태스크를 순차적으로 실행합니다: javac 또는 kotlinc를 통한 Kotlin과 Java 컴파일, AAPT2를 통한 리소스 처리, R.java 생성, D8 또는 R8을 통한 DEX로의 바이트코드 컴파일, APK 서명 및 압축. 각 태스크는 입력 데이터가 변경되었는지 확인하고, 변경되지 않은 경우 캐시된 결과를 사용합니다. 이 메커니즘을 증분 빌드라고 하며 전체 재빌드에 비해 재컴파일을 60~80% 가속화합니다.
Android 모듈 설정은 build.gradle.kts 파일의 android 블록에서 설정됩니다. 블록 내에서 compileSdk, minSdk, targetSdk, 앱 버전, 서명 및 기타 매개변수가 정의됩니다. Gradle은 각 모듈에 대해 여러 빌드 변형(유형(release, debug)과 flavor의 조합)을 자동으로 생성합니다. 예를 들어 두 개의 flavor와 두 개의 유형이 있는 모듈의 경우 Gradle은 assembleDemoDebug, assembleDemoRelease, assembleFullDebug, assembleFullRelease의 네 가지 태스크를 생성합니다. 이러한 모든 태스크는 개별적으로 실행하거나 모든 변형에 대해 한 번에 하나의 명령으로 실행할 수 있습니다.
각 Android 프로젝트에는 두 가지 수준의 설정이 있습니다: 루트 build.gradle.kts(모든 모듈에 대한 설정)와 모듈 수준 build.gradle.kts(특정 모듈에 대한 설정)입니다. 루트 파일에서는 플러그인을 적용하지 않고 선언하고, 리포지토리와 공통 변수를 정의합니다. 모듈 파일에서는 플러그인이 특정 모듈에 적용되고 빌드 매개변수가 설정됩니다. 이 접근 방식은 버전 카탈로그 또는 ext 블록을 통해 종속성 버전을 중앙에서 관리할 수 있게 합니다.
@Suppress("UnstableApiUsage")
plugins {
id("com.android.application") version "8.2.2"
id("org.jetbrains.kotlin.android") version "1.9.22"
}
android {
namespace = "com.example.myapp"
compileSdk = 34
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
}
}dependencies 블록은 build.gradle.kts의 또 다른 중요한 요소입니다. 애플리케이션에 필요한 라이브러리, 모듈 및 파일 종속성을 나열합니다. Gradle은 여러 종속성 설정을 지원합니다: implementation(현재 모듈에서만 사용 가능), api(종속 모듈에서도 사용 가능), testImplementation(테스트 전용), androidTestImplementation(계측 테스트용), compileOnly(컴파일 시에만). 각 설정은 종속성 그래프에서 클래스 가시성을 관리하여 빌드 시간과 최종 아티팩트 크기에 영향을 줍니다.
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
implementation("androidx.activity:activity-compose:1.8.2")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
}Build variant는 고유한 설정, 코드 및 리소스를 가진 앱 버전을 정의하는 빌드 유형과 제품 flavor의 조합입니다. 빌드 유형은 패키징 매개변수를 정의합니다: debug(디버깅 및 .debug 접미사 포함) 또는 release(난독화 및 서명 포함). 제품 flavor는 기능적 변형을 정의합니다: 예를 들어 demo(제한된 버전)와 full(추가 기능이 있는 전체 버전). Gradle은 각 조합에 대해 자동으로 태스크를 생성하여 모든 버전을 하나의 명령으로 빌드할 수 있게 합니다.
android {
buildTypes {
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
debug {
applicationIdSuffix = ".debug"
}
}
flavorDimensions += "version"
productFlavors {
create("demo") {
dimension = "version"
applicationIdSuffix = ".demo"
}
create("full") {
dimension = "version"
applicationIdSuffix = ".full"
}
}
}각 build variant에는 별도의 소스 세트가 있습니다. Gradle은 src/demo/release, src/full/debug 등의 디렉토리를 사용하여 특정 변형에 대한 고유한 리소스, 매니페스트 및 소스 파일을 저장합니다. 공통 코드는 src/main에 남습니다. 이 접근 방식은 주요 로직을 재사용하고 문자열, 아이콘, API 엔드포인트 또는 설정 파일 등 다른 부분만 교체할 수 있게 합니다. 소스 세트는 main의 모든 리소스(매니페스트, drawable, values 또는 Kotlin 클래스)를 재정의할 수 있습니다. 특정 변형을 빌드할 때 Gradle은 main과 해당 소스 세트의 파일을 병합하며 변형의 파일이 우선 순위를 가집니다.
Gradle 플러그인 생태계는 Android 애플리케이션 개발의 모든 단계를 포괄합니다. Google의 공식 플러그인에는 com.android.application(앱 모듈용), com.android.library(라이브러리 모듈용), com.android.test(테스트 모듈용) 및 JetBrains의 Kotlin 플러그인이 포함됩니다. 플러그인은 프로젝트에 새 태스크를 추가하고, 새로운 설정 블록으로 DSL을 확장하며, 추가 도구를 연결합니다. com.android.application 플러그인이 없으면 프로젝트가 APK를 빌드할 수 없습니다. 이 플러그인은 모든 Android 관련 태스크를 등록하고 빌드 그래프에 연결합니다.
타사 플러그인은 더 구체적인 작업을 해결합니다. Google Services(com.google.gms.google-services)는 Firebase와 Google Play Services를 통합하여 google-services.json을 자동으로 빌드에 삽입합니다. Hilt(dagger.hilt.android.plugin)는 컴파일 시 종속성 주입 코드를 생성합니다. Safe Args(androidx.navigation.safeargs.kotlin)는 프래그먼트 간 탐색을 위한 타입 안전 클래스를 만듭니다. 각 플러그인은 루트 build.gradle.kts의 plugins 블록을 통해 추가되며 일반적으로 최소한의 설정만 필요합니다. Gradle은 플러그인 간의 전이적 종속성을 자동으로 해결하고 Bom 파일과 버전 카탈로그를 통해 버전 호환성을 보장합니다.
태스크는 Gradle에서 작업의 원자 단위입니다. 각 태스크에는 입력 데이터, 출력 데이터 및 작업이 있습니다. Android의 내장 태스크에는 assemble(모든 변형 빌드), lint(코드 검사), test(단위 테스트 실행), clean(임시 파일 정리)이 있습니다. 개발자는 Groovy 또는 Kotlin DSL을 사용하여 자체 태스크를 추가할 수 있습니다. 사용자 정의 태스크는 보고서 생성, 아티팩트 복사, 테스트 장치에 배포 또는 CI 시스템과의 통합과 같은 일상적인 작업을 자동화하는 데 유용합니다.
tasks.register("printBuildInfo") {
description = "빌드 정보를 표시합니다"
group = "custom"
doLast {
println("Build variant: ${project.name}")
println("Version: ${android.defaultConfig.versionName}")
}
}각 태스크는 dependsOn 메커니즘을 통해 다른 태스크에 종속될 수 있습니다. 태스크 A가 태스크 B에 종속된 경우 Gradle은 B가 A보다 먼저 실행됨을 보장합니다. 시스템은 각 쌍에 대해 수동으로 순서를 지정할 필요가 없습니다. 종속성을 선언하기만 하면 Gradle이 독립적인 태스크의 병렬 실행에 최적화된 방향성 그래프를 구축합니다. Android 플러그인의 내장 태스크는 이미 연결되어 있습니다: lint는 컴파일에 종속, test는 assemble에 종속, assembleDebug는 compileDebugKotlin에 종속됩니다. 개발자는 dependsOn, mustRunAfter 또는 shouldRunAfter를 사용하여 그래프의 모든 노드에 자체 태스크를 삽입할 수 있습니다.
자주 발생하는 문제 중 하나는 종속성 버전 충돌로, 두 라이브러리가 동일한 전이적 종속성의 다른 버전을 필요로 하는 경우입니다. Gradle은 충돌 오류를 보고하지만 항상 자동 해결책을 제공하지는 않습니다. 진단을 위해 ./gradlew :app:dependencies 명령을 사용하여 전체 종속성 트리를 출력합니다. resolutionStrategy 블록을 통해 충돌하는 라이브러리의 버전을 강제로 지정하는 것이 좋습니다. 또 다른 일반적인 시나리오는 증분 처리 부족으로 인한 느린 빌드입니다. 모든 플러그인이 업데이트되었는지, Gradle Daemon이 활성화되었는지(org.gradle.daemon=true), gradle.properties에 충분한 메모리가 설정되었는지(org.gradle.jvmargs=-Xmx4096m) 확인하세요.
캐싱 문제는 종속성 업데이트 후 발생합니다: Gradle이 오래된 캐시를 사용하여 빌드가 실패할 수 있습니다. 해결책은 --refresh-dependencies 플래그로 빌드를 실행하거나 ./gradlew cleanBuildCache로 수동으로 캐시를 지우는 것입니다. 세 번째로 흔한 오류는 Android Gradle Plugin(AGP)과 Gradle 간의 버전 비호환성입니다. 각 AGP 버전에는 특정 최소 Gradle 버전이 필요합니다. 호환성 테이블은 developer.android.com에 게시됩니다. 버전이 호환되지 않으면 Gradle이 설정 단계에서 최소 필요 버전에 대한 메시지와 함께 실패합니다. Gradle 래퍼 버전이 AGP 요구 사항과 일치하는지 항상 확인하세요.
자주 묻는 질문
Gradle은 프로젝트를 빌드하기 위한 프로그램 자동화 도구입니다. Kotlin 또는 Java로 작성된 소스 코드를 가져와 인터넷에서 라이브러리를 연결하고 모든 것을 바이트코드로 컴파일하여 APK로 패키징합니다. JVM에서 실행되며 수동 명령 대신 선언적 스크립트를 사용합니다. 개발자는 규칙만 설명하면 나머지는 Gradle이 처리합니다.
Build.gradle은 Groovy(유연한 구문과 덜 엄격한 동적 언어)로 작성됩니다. Build.gradle.kts는 Kotlin DSL을 사용합니다: 강력한 타입 지정, Android Studio에서 자동 완성, 컴파일 시 오류 검사. Google은 모든 새 프로젝트에 Kotlin DSL을 권장합니다. Groovy 파일은 마이그레이션이 더 쉽지만 Kotlin 파일은 유지 관리가 더 안정적입니다.
Gradle Daemon(org.gradle.daemon=true)과 병렬 빌드(org.gradle.parallel=true)를 활성화하세요. org.gradle.jvmargs를 통해 JVM 메모리를 4~8GB로 늘리세요. 온디맨드 프로젝트 설정(org.gradle.configureondemand=true)을 사용하세요. Android 프로젝트의 경우 태스크 캐싱을 설정하고 필요한 ABI에 대해서만 빌드하세요. Android Studio에서 Build Analyzer를 실행하여 병목 현상을 찾으세요.
Build variant는 빌드 유형(예: debug 또는 release)과 제품 flavor(예: demo 또는 full)의 조합입니다. 각 변형은 고유한 패키지 이름, 버전, 리소스 및 소스 파일을 가질 수 있습니다. Gradle은 각 변형에 대해 별도의 빌드 태스크를 자동으로 생성합니다. 이를 통해 단일 프로젝트에서 애플리케이션의 여러 버전을 빌드할 수 있습니다.
종속성은 build.gradle.kts 파일의 dependencies 블록에 추가됩니다. 형식은 다음과 같습니다: configuration("group:artifact:version"). 예: implementation("androidx.core:core-ktx:1.12.0"). 테스트에는 testImplementation, 계측 테스트에는 androidTestImplementation을 사용합니다. 버전은 libs.versions.toml 파일을 통해 별도의 버전 카탈로그로 구성하는 것이 편리합니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.