안드로이드 탐구 : What is Gradle?

Skele·2025년 2월 24일
0

1. What is Gradle?

Gradle Build Tool is a fast, dependable, and adaptable open-source build automation tool with an elegant and extensible declarative build language.

Gradle은 유연하고 강력한 오픈소스 빌드 시스템으로, 안드로이드에는 Google I/O 2013에서 소개되어 공식 빌드 시스템으로 선택되었다.


2. Gradle Core Concept

Project

Gradle Project란, 어플리케이션이나 라이브러리 등 빌드 가능한 소프트웨어를 지칭한다.
싱글 프로젝트 빌드는 단일 루트 프로젝트로 구성되며, 멀티 프로젝트 빌드는 하나의 루트 프로젝트와 여러 개의 서브 프로젝트로 이루어진다.
그리고 안드로이드에서의 멀티 모듈 구조는 Gradle의 멀티 프로젝트 빌드 개념을 그대로 사용한다.

Build Scripts

Build Script(build.gradle.kts)는 Gradle이 프로젝트의 빌드 과정 및 설정을 정의하는 파일로, 프로젝트는 각 모듈별로 하나 이상의 빌드 스크립트를 포함할 수 있다.

Dependency Management

Gradle Dependency Management는 프로젝트에서 선언된 외부 라이브러리를 자동으로 검색, 다운로드 및 적용하는 시스템이다.

Tasks

Gradle Task는 Gradle 빌드 과정에서 실행되는 기본 작업 단위로, 컴파일, 테스트, 패키징, 배포 등의 작업을 수행한다.

Plugins

Gradle Plugin은 Gradle의 기능을 확장하고, 프로젝트에 필요한 태스크를 추가할 수 있도록 한다.


3. Gradle Wrapper

Gradle Wrapper는 Gradle을 설치하지 않아도 프로젝트에서 자동으로 Gradle 버전을 다운로드하고 실행할 수 있도록 도와주는 스크립트이다.

3.1. Benefits of Wrapper

"Standardizes a project on a given Gradle version."

팀원 간 Gradle 버전 차이로 인한 빌드 문제를 방지하고, 프로젝트의 일관성을 유지한다.

"Provisions the same Gradle version for different users."

개발자가 동일한 빌드 환경을 갖추게 되어, 빌드 오류 및 환경 차이로 인한 문제를 최소화할 수 있다.

"Provisions the Gradle version for different execution environments (IDEs, CI servers…)."

로컬 개발 환경, IDE, CI/CD 환경 등 어디서든 동일한 Gradle 버전으로 빌드를 수행할 수 있어 호환성과 재현성이 향상된다.

3.2. Wrapper Files

.
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar  
│       └── gradle-wrapper.properties   
├── gradlew 
└── gradlew.bat 

gradle-wrapper.jar

  • Gradle Wrapper의 실행파일
  • Gradle 버전을 자동으로 다운로드 하고 실행하는 코드를 포함한다.
  • 실행 시 설정된 Gradle 버전이 로컬에 있는지 확인하고, 없으면 다운로드하여 사용한다.

gradle-wrapper.properties

  • Gradle Wrapper의 설정파일
  • Gradle의 버전 및 다운로드 경로를 정의한다.
  • distributionUrl 속성을 통해 Gradle이 어디에서 다운로드할지를 설정하고, distribution type으로 파일 타입(ZIP, TARBALL)을 지정한다.

gradlew

  • Unix 기반 시스템용 Gradle Wrapper 실행 파일 (Shell Script)
  • gradle-wrapper.jar의 Unix용 Wrapper로, Unix 환경에서 Gradle을 자동 다운로드하고 실행한다.

gradlew.bat

  • Window 기반 시스템 용 Gradle Wrapper 실행 파일
  • gradlew와 동일한 목적을 가지지만, Window 환경에서 사용된다.

3.3. Gradle Wrapper in Android

안드로이드 프로젝트는 Gradle 빌드를 기반으로 작동하며, Gradle Wrapper를 사용하여 프로젝트에 맞는 Gradle 버전을 자동으로 적용한다. 이로써 일관된 빌드 환경을 유지하고, 개발자가 별도의 Gradle 설치 없이 프로젝트를 실행할 수 있도록 한다.

Sync Project with Gradle Files

Gradle 관련 파일을 수정했을 때, 반드시 누르는 "Sync"버튼으로 실행되는 Gradle Sync는 build.gradle.kts 또는 settings.gradle.kts 파일의 변경 사항을 반영하고, 필요한 의존성을 다운로드 및 적용하는 과정이다.


4. Settings File


Settings File(settings.gradle)은 Gradle 프로젝트의 진입점으로, 빌드의 초기화 단계에서 실행되며 프로젝트의 구조와 포함될 서브 프로젝트를 지정한다.

settings.gradle.kts

rootProject.name = "root-project"   // 프로젝트 이름

include("sub-project-a")            // 포함할 서브 프로젝트
include("sub-project-b")
include("sub-project-c")

루트 프로젝트는 오직 하나만 존재할 수 있지만, 서브 프로젝트는 다수가 포함될 수 있다.


5. Build File


Build File(build.gradle.kts)은 프로젝트의 빌드 과정, 의존성, 플러그인, 태스크 등을 설정한다.
모든 Gradle 빌드는 최소한 하나 이상의 Build Script(=Build File)을 포함한다.

build.gradle.kts

빌드 스크립트는 크게 플러그인플러그인의 속성(Convention Property) 설정으로 나눌 수 있다.

Plugin

plugins {
    id("com.android.application") 		// 안드로이드 애플리케이션 플러그인 적용
    id("org.jetbrains.kotlin.android")	// Kotlin-Android 플러그인 적용
}

Plugin은 Gradle에 새로운 태스크, 속성, 메서드를 추가해준다.
위에 각 플러그인은 안드로이드 앱과 Kotlin 코드에 대한 사용과 설정을 가능케한다.

Convention Property

android { // com.android.application 플러그인이 제공하는 속성
    namespace = "com.example.myapp" // 애플리케이션 패키지 네임스페이스
    compileSdk = 34 // 최신 Android SDK 버전 지정

	kotlinOptions { // org.jetbrains.kotlin.android 플러그인이 제공하는 속성
        jvmTarget = "17" // Kotlin 컴파일 시 JVM 17을 타겟으로 설정
        freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" // 실험적 기능 활성화
    }

    defaultConfig {
        applicationId = "com.example.myapp" // 앱의 고유 식별자
        minSdk = 23   // 최소 지원 Android 버전
        targetSdk = 34 // 타겟 Android 버전
        ...
    }

    buildTypes {
        ...
    }
}

플러그인에 의해 추가된 속성들로, 애플리케이션에 대한 정보와 버전 등 빌드에 필요한 속성을 설정할 수 있다.


6. Dependency Management


Dependency Management는 프로젝트에서 필요한 외부 라이브러리 및 플러그인을 선언하고, 이를 자동으로 다운로드 및 관리하는 시스템이다.
이러한 외부 의존성(Dependencies) 은 JAR 파일, 라이브러리, 소스 코드 또는 플러그인을 의미하며, Gradle은 이것들을 자동으로 다운로드하고 프로젝트에 포함시킨다.
하지만, 프로젝트 규모가 커질수록 버전 관리를 일일이 수동으로 하기가 어렵고, 서브 프로젝트 간 일관성을 유지하기가 어려워지는데, 이를 해결하기 위해 Version Catalog가 제공된다.

6.1. Version Catalog

Version Catalog는 모든 종속성을 한 곳에서 중앙 집중적으로 관리할 수 있도록 해준다.
Gradle 7.0부터 지원되며, libs.versions.toml 파일을 통해 라이브러리 및 플러그인의 버전을 선언하고, 빌드 스크립트에서 참조할 수 있도록 구성한다.

libs.versions.toml

섹션명역할
[versions]플러그인 및 라이브러리의 버전 정보 선언
[libraries]빌드 파일에서 사용할 라이브러리 정의
[bundles] 라이브러리의 묶음을 선언
[plugins]사용할 플러그인 정의
[versions]
androidGradlePlugin = "7.4.1"
mockito = "2.16.0"

[libraries]
googleMaterial = { group = "com.google.android.material", name = "material", version = "1.1.0-alpha05" }
mockitoCore = { module = "org.mockito:mockito-core", version.ref = "mockito" }

[plugins]
androidApplication = { id = "com.android.application", version.ref = "androidGradlePlugin" }

6.2. Using Version Catalog (Declaring Dependencies)

Version Catalog에 선언한 플러그인과 라이브러리는 빌드 파일에서 사용이 가능하다.

Plugin

alias()를 사용해 선언한 플러그인을 사용한다.

plugins {
    alias(libs.plugins.androidApplication) // Android Gradle Plugin 적용
}

여기서 libs.plugins.androidApplicationlibs.versions.toml[plugins] 섹션에서 정의한 androidApplication을 참조한다.

Library

implementation()을 사용해 실제 코드(Production Code)에 필요한 라이브러리를 사용하고, testImplementation()을 사용해 테스트 코드 실행에 필요한 라이브러리를 사용한다.

dependencies {
    implementation(libs.googleMaterial) // Material UI 라이브러리 추가
    testImplementation(libs.mockitoCore) // Mockito 테스트 라이브러리 추가
}

Version Catalog를 사용하면 직접 버전을 입력할 필요 없이 libs.<이름>만 추가하면 된다.


7. Task


Task 는 빌드 수행 중 실행되는 독립적인 작업 단위이다.
코드를 컴파일하고, JAR 파일을 생성하며, 테스트를 실행하거나, 결과물을 배포하는 등의 작업이 태스크로 정의된다.

7.1. Available Tasks

명령어를 사용해 플러그인과 빌드 스크립트에 포함된 모든 사용가능한 태스크를 확인할 수 있다.

./gradlew tasks

7.2. Running Task

Gradle Wrapper 명령어를 사용해 build 태스크를 실행시킬 수 있다.

./gradlew build

결과

> Task :app:compileJava
> Task :app:processResources NO-SOURCE
> Task :app:classes
> Task :app:jar
> Task :app:startScripts
> Task :app:distTar
> Task :app:distZip
> Task :app:assemble
> Task :app:compileTestJava
> Task :app:processTestResources NO-SOURCE
> Task :app:testClasses
> Task :app:test
> Task :app:check
> Task :app:build

7.3. Task Dependency

위 결과를 보면 build 태스크를 수행하기 앞서 다른 많은 태스크들이 실행되는 것을 볼 수 있다. Gradle의 태스크는 서로 의존성을 가질 수 있으며, 특정 태스크가 실행되기 전에 필요한 태스크가 먼저 실행될 수 있도록 설정할 수 있다.

7.3.1 Define Task Dependency

기본적으로 Gradle이 자동으로 태스크 실행 순서를 결정하지만, 빌드 스크립트에 직접 태스크 실행 순서를 명시할 수 있다.

tasks.register("customTask") {
    dependsOn("help") // help 태스크가 먼저 실행됨
    doLast {
        println("Custom Task 실행 완료!")
    }
}
./gradlew customTask

결과

> Task :app:help

Welcome to Gradle 8.9.

To run a build, run gradlew <task> ...

To see a list of available tasks, run gradlew tasks

To see more detail about a task, run gradlew help --task <task>

To see a list of command-line options, run gradlew --help

For more detail on using Gradle, see https://docs.gradle.org/8.9/userguide/command_line_interface.html

For troubleshooting, visit https://help.gradle.org

> Task :app:customTask
Custom Task 실행 완료!

help 태스크 이후에 customTask가 실행된걸 볼 수 있다.


8. Plugins


Plugin은 Gradle 빌드 시스템에 추가적인 기능을 제공하는 소프트웨어이다.
Gradle 자체는 의존성 관리 및 태스크 실행을 위한 핵심 인프라를 제공하는 엔진이기에, 대부분의 다른 기능들은 플러그인을 통해 추가된다.
플러그인이 Gradle 빌드에 추가하는 것들로는 태스크(Task)와 속성(Property)이 있다.

8.1. Plugin Distribution

Gradle 플러그인은 배포 방식에 따라 세 가지 종류로 나뉜다.

8.1.1. Core Plugin

Core Plugin은 Gradle이 기본적으로 포함하고 있어 별도의 버전 지정 없이 적용 가능한 플러그인이다.

build.gradle.kts

plugins {
    id("java")
}

위와 같이 짧은 이름을 가지며 버전을 지정할 필요가 없다.
Core Plugins 에서 Gradle의 Core Plugin들을 확인할 수 있다.

8.1.2. Community Plugin

Community Plugin은 커뮤니티에 의해 개발되어 Gradle Plugin Portal에 등록된 플러그인으로, 필요한 특정 기능을 추가할 때 사용된다.#### build.gradle.kts

build.gradle.kts

plugins {
	alias(libs.plugins.androidApplication) 				// Version Catalog 사용
    //id("com.android.application") version "8.7.1"		// Version Catalog 없이 플러그인 추가
}

Gradle Plugin Portal에서 다양한 커뮤니티 플러그인을 확인할 수 있다.

8.1.3 Local Plugin

Local Plugin은 특정 프로젝트나 조직에서 직접 개발하여 공유되지 않고 내부적으로 사용하는 플러그인이다.
로컬 플러그인은 API를 사용해 직접 개발하여 프로젝트에 적용할 수 있다.
자세한 방법은 추후에 정리할 예정.

profile
Tireless And Restless Debugging In Source : TARDIS

0개의 댓글