본문 바로가기

Build/Gradle

Gradle 도큐먼트: 빌드 스크립트 build.gradle.kts 기본기

이 문서의 내용

    더보기

    gradle 명령문을 사용하면 프로젝트의 build.gradle.kts 파일을 찾습니다.

    build.gradle.kts 파일은 통상적으로 빌드 스크립트(Build script)라고 부릅니다.

    빌드 스크립트는 프로젝트와 작업(Tasks)를 정의하며, 사실 환경 설정 파일에 가깝습니다.

    Hello world!

    예제를 위한 디렉토리를 생성하고 빌드 스크립트 파일 build.gradle.kts을 만듭니다.

    예제는 macOS 환경에서 실행을 가정하고 Kotlin으로 작성합니다.

    tasks.register("hello") {
        doLast {
            println("Hello world!")
        }
    }
    코드 비고
    Line 1 tasks.register() Gradle에서 실행되는 새로운 Task를 등록합니다.
    Line 2:4 { } { } 블록으로 감싸져 있는 코드는 Task의 Action입니다.
    doLast doLastTask에서 서술된 Action 중 가장 마지막에 실행되도록 합니다.

    빌드 스크립트 파일이 위치한 곳에서 명령줄 인터페이스를 열고 gradle -q hello를 실행합니다.

    $ gradle -q hello
    Hello world!
    더보기

    명령문에 사용 된 -q 옵션은 Gradle에서 출력하는 로그를 숨기고 Task에서 표시하는 출력한 보여줍니다.

    Gradle의 빌드 스크립트에서는 Kotlin 또는 Groovy의 모든 문법을 그대로 사용 할 수 있습니다.

    tasks.register("upper") {
        doLast {
            val someString = "mY_nAmE"
            println("Original: $someString")
            println("Upper case: ${someString.toUpperCase()}")
        }
    }
    코드 비고
    Line 3:4 val someString $someString 변수를 선언하고 값을 할당합니다.
    문자열 내에서 변수에 접근할 때는 $ 키워드를 사용합니다.
    Line 5 toUpperCase() Kotlin 문법에서의 문자열을 대문자로 치환하는 함수를 사용합니다.

    명령줄 인터페이스에서 gradle -q upper를 실행합니다.

    $ gradle -q upper
    Original: mY_nAmE
    Upper case: MY_NAME

    또는 Kotlin의 repeat()을 사용한 반복문 예시에서도 알 수 있습니다.

    tasks.register("count") {
        doLast {
            repeat(5) { print("$it") }
        }
    }
    코드 비고
    Line 3 repeat(5) 0부터 4까지 반복합니다. 반복되는 숫자는 it 키워드로 접근합니다.

    명령줄 인터페이스에서 gradle -q count를 실행합니다.

    $ gralde -q count
    01234

    Task Dependencies(의존성)

    일부 Task는 다른 Task의 실행에 의존 할 수 있습니다.

    tasks.register("hello") {
        doLast {
            println("Hello World!")
        }
    }
    
    tasks.register("intro") {
        dependsOn("hello")
        doLast {
            println("I'm Gradle")
        }
    }
    코드 비고
    Line 1:5 Line 7:12 tasks.register() 두 개의 Task를 등록합니다.
    Line 8 dependsOn() Task에 의존성을 지정합니다.
    예제에서는 into Task가 실행되기 위해서 hello Task가 선행됩니다.

    명령줄 인터페이스에서 gradle -q intro를 실행합니다.

    $ gradle -q intro
    Hello World!
    I'm Gradle
    더보기

    Task의 의존성 선언 dependsOn()은 Task 선언 순서와 관계 없이 사용 할 수 있습니다.

    다음 예시에서는 taskY가 등록되기 전에 taskX에서 taskY에 대한 의존성을 지정하지만, 실행에는 문제 없습니다.

    tasks.register("taskX") {
        dependsOn("taskY")
        doLast {
            println("taskX")
        }
    }
    tasks.register("taskY") {
        doLast {
            println("taskY")
        }
    }

    자세한 내용은 Adding dependencies to a task를 참고합니다.

    Task 등록 과정에서 Kotlin 문법 사용

    KotlinGroovy는 단순히 Task 내부 뿐만 아니라 Task를 등록하고 편집하는 과정 중에서도 사용 할 수 있습니다.

    repeat(4) { counter ->
        tasks.register("task$counter") {
            doLast {
                println("My task number is $counter")
            }
        }
    }

    명령줄 인터페이스에서 gradle -q task<0:3>을 실행합니다.

    $ gradle -q task0
    My task number is 0
    $ gradle -q task1
    My task number is 1
    $ gradle -q task3
    My task number is 3

    등록이 완료된 Task를 수정

    Gradle은 등록이 완료된 Task를 수정하기 위한 다양한 방법을 제공합니다.

    다음 예시에서는 런타임에 생성되는 Task의 의존성을 지정합니다. 이러한 동작은 Ant에서는 허용하지 않는 문법입니다.

    repeat(4) { counter ->
        tasks.register("task$counter") {
            doLast {
                println("My task number is $counter")
            }
        }
    }
    
    tasks.named("task0") {
        dependsOn("task2", "task3")
    }
    코드 비고
    Line 9 tasks.named() 이미 등록된 Task를 다시 정의합니다.
    Line 10 dependsOn() 지정된 의존성 task2task3는 런타임에 생성됩니다.
    Gradle에서는 런타임에 생성되는 Task에 의존성을 지정 할 수 있습니다.

    명령줄 인터페이스에서 gradle -q task0을 실행합니다.

    $ gradle -q task0
    My task number is 2
    My task number is 3
    My task number is 0

    기존 Task에서 Action을 추가하는 것도 가능합니다.

    tasks.register("hello") {
        doLast {
            println("Hello Earth")
        }
    }
    
    tasks.named("hello") {
        doFirst {
            println("Hello Venus")
        }
    }
    
    tasks.named("hello") {
        doLast {
            println("Hello Mars")
        }
    }
    
    tasks.named("hello") {
        doLast {
            println("Hello Jupiter")
        }
    }

    명령줄 인터페이스에서 gradle -q hello를 실행합니다.

    $ gradle -q hello
    Hello Venus
    Hello Earth
    Hello Mars
    Hello Jupiter

    함수 사용

    공통된 로직은 함수로 선언해서 재사용합니다. 기본적인 함수의 선언은 fun <함수 이름> <Argument>입니다.

    tasks.register("hello123") {
        doLast {
            printStringNumber("Hello", 123)
        }
    }
    
    tasks.register("hello456") {
        doLast {
            printStringNumber("Hello", 456)
        }
    }
    
    fun printStringNumber(str: String, value: Int) {
        println("$str $value")
    }

    명령줄 인터페이스에서 gradle -q hello123 gradle -q hello456을 실행합니다.

    $ gradle -q hello123
    Hello 123
    $ gradle -q hello456
    Hello 456
    더보기

    Top-Level에 선언된 함수 또는 변수에 엑세스는 아직 configuration cache와 호환되지 않습니다.

    빌드 로직이 복잡해짐에 따라서 빌드 스크립트를 정리하는 방법은 Organizing Gradle Project를 참고합니다.

    Default Tasks(기본 작업)

    Gradle은 Task가 지정되지 않은 경우 실행되는 기본 Task를 정의 할 수 있습니다.

    기본 Task는 여러 개로 구성 될 수 있습니다.

    defaultTasks("clean", "run")
    
    tasks.register("clean") {
        doLast {
            println("Default cleaning!")
        }
    }
    
    tasks.register("run") {
        doLast {
            println("Default running!")
        }
    }
    
    tasks.register("other") {
        doLast {
            println("I'm not a default task")
        }
    }

    명령줄 인터페이스에서 gradle -q를 실행합니다. 별도의 Task를 지정하지 않고 기본 Task가 실행됩니다.

    $ gradle -q
    Default cleaning!
    Default running!
    더보기

    다중 프로젝트 빌드(Multi-Project build) 환경에서 하위 작업은 고유의 기본 Task를 가질 수 있습니다.

    하위 프로젝트에서 기본 Task를 정의하지 않고 상위 프로젝트에서만 기본 Task를 정의할 때 상위 프로젝트의 것이 실행됩니다.

    외부 의존성 추가

    빌드 스크립트에서 외부 라이브러리에 대한 의존성은 빌드 스크립트 내의 classpath에 추가합니다.

    buildscript {
        repositories {
            mavenCentral()
        }
    
        dependencies {
            "classpath"(group="commons-codec", name="commons-codec", version="1.2")
        }
    }
    코드 비고
    Line 6:8 dependencies classpathdependencies에서 지정됩니다.
    "classpath"( ) Task에서 사용하는 외부 라이브러리 의존성입니다.
    프로젝트 종속성을 제외한 모든 dependency type을 사용 할 수 있습니다.

    외부 의존성이 추가되면 빌드 스크립트 내에서 외부 라이브러리의 클래스를 사용 할 수 있습니다.

    import org.apache.commons.codec.binary.Base64
    
    buildscript {
        repositories {
            mavenCentral()
        }
    
        dependencies {
            "classpath"(group="commons-codec", name="commons-codec", version="1.2")
        }
    }
    
    tasks.register("encode") {
        doLast {
            val encodedString = Base64().encode("hello world\n".toByteArray())
            println(String(encodedString))
        }
    }
    코드 비고
    Line 1 import org.apache...Base64 외부 라이브러리 commons-codecBase64 클래스를 Import합니다.
    Line 15 Base64().encode() 빌드 스크립트에서 Base64 클래스를 사용합니다.

    명령줄 인터페이스에서 gradle -q encode를 실행합니다. 외부 의존성이 추가되었기에 다른 예제의 Gradle 빌드보다 시간이 더 오래 걸립니다.

    $ gradle -q encode
    aGVsbG8gd29ybGQK
    더보기

    다중 프로젝트 빌드(Multi-Project build) 환경에서 프로젝트의 buildscript() 메소드로 선언된 의존성은 모든 하위 프로젝트의 빌드 스크립트에서 동일하게 사용 할 수 있습니다.

    모든 Gradle 프로젝트에서는 빌드 스크립트의 의존성을 리포팅하는 buildEnvironment Task가 포함됩니다. 자세한 내용은 BuildEnvironmentReportTask를 참고합니다.

    정리 및 복습

    • 빌드 스크립트(build.gradle.kts)에서는 Kotlin 또는 Groovy의 모든 문법을 그대로 사용 할 수 있습니다.
    • gradle -q 옵션은 Gradle에서 출력하는 로그를 숨기고 Task에서 표시하는 출력한 보여줍니다.
    • 새로운 Task를 등록하려면 tasks.register()를 사용하고, 기존 Task를 수정하려면 tasks.named()를 사용합니다.
    • Task에서 다른 Task에 대한 의존성을 추가하려면 dependsOn()을 사용합니다.
    • 빌드 스크립트에서 공통 로직을 함수로 분리 할 수 있습니다. 기본적인 함수의 선언은 fun <함수 이름> <Argument>입니다.
    • defaultTasks()는 Task가 지정되지 않은 경우 실행되는 기본 Task를 정의합니다.
    • 외부 의존성을 추가하면 빌드 스크립트 내에서 외부 라이브러리의 클래스를 사용 할 수 있습니다.