프로그래밍/Gradle

Gradle의 이해: Task

Lou Park 2023. 10. 20. 23:59

Tasks

gradle :project:tasks 를 입력하면 프로젝트에서 수행 가능한 Task들을 알 수 있다.

Gradle 작업의 중요한 측면은 증분성에 있다. 이는 Gradle이 이전 빌드의 결과를 재사용 할 수 있다는 것을 의미한다. 따라서 프로젝트를 빌드하고 소스 코드의 작은 부분만 변경했다면, 다시 빌드하더라도 다시 수행해야하는 Task들은 처음 빌드보다 적어진다.

> Task :app:processProductionDebugGoogleServices UP-TO-DATE
> Task :app:productionDebugOssDependencyTask UP-TO-DATE
> Task :app:productionDebugOssLicensesTask UP-TO-DATE
> Task :app:mergeProductionDebugResources UP-TO-DATE
> Task :app:packageProductionDebugResources UP-TO-DATE
> Task :app:parseProductionDebugLocalResources UP-TO-DATE

빌드를 돌리다보면 UP-TO-DATE라고 표시되는 부분이 바로 그것이다.

또한 캐시에서 Task 수행 결과를 가져올 수 있는데, build-cache를 활성화 할 경우 사용가능하다. 명령줄 인수로 --build-cache를 전달하거나,gradle.properties\에서 캐싱을 켜주면 된다.

gradle :app:build --build-cache
# gradle.properties
org.gradle.caching=true

캐시에서 결과를 가져온 Task들에는 FROM-CACHE로 표시된다.

> Task :app:test FROM-CACHE

흥미롭게도, 캐시는 원격 서버에 위치할 수도 있고 여러 시스템간에 공유될 수도 있다. 따라서 잘 설정해두면 CI 서버의 캐시를 여러 개발자들이 사용해서 빌드 속도를 향상시킬 수도 있다.

Task Result
(no label), EXCUTED Task가 실행됨
UP-TO-DATE Task의 결과가 바뀌지 않았음
FROM-CACHE 이전 실행에서 Task의 실행결과를 찾았음
SKIPPED Task가 실행되지 않았음
NO-SOURCE Task가 작업을 실행할 필요가 없음

Build Lifecycle

Task의 올바른 구성을 위해서는 Gradle의 Build Lifecycle을 알아두면 좋다.
Gradle은 Initialization, Configuation, Execution의 세 단계로 작업을 수행한다.

flowchart LR
    Initialization --> Configuration
    Configuration --> Execution
  1. Initialization
    • settings.gradle 파일을 읽는다.
    • 어떤 하위 프로젝트가 이 빌드에 포함되는지 확인한다.
    • 모든 프로젝트마다 Project 인스턴스를 생성한다.
  2. Configuration
    • 빌드에 포함되는 프로젝트의 모든 빌드 스크립트를 평가한다.
    • 요청된 Task들에 대한 Task Graph를 생성한다.
  3. Execution
    • 요청된 Task들을 의존성에 따라 순서대로 스케쥴링하고 실행한다.

Task 만들기

"안녕하세요!"라고 출력하는 Task를 만들어 보자.

tasks.register("hello") {
    doLast {
        println("안녕하세요!") // action
    }
}

등록한 이름 "hello" Task를 실행할 수 있다.

$ ./gradlew hello -q
안녕하세요!

doLast(action) 는 Task의 Action list 끝에 우리가 정의한 "안녕하세요" Closure를 더한다.
만약에 doLast(action)을 빼버리고 그냥 안녕하세요만 넣어버리면 어떻게 될까?

tasks.register("hello") {
    println("안녕하세요!")
}

단순히 hello Task를 실행하는데에는 큰 차이가 없어보인다.

$ ./gradlew tasks -q
안녕하세요!

하지만 이렇게 실행되지 않아야 할 상황에서도 Configuration 단계가 되면 이를 실행해버린다.
우리는 Task의 Execution 단계에서 실행되기를 원하므로 doLast(action) 에 작업을 정의했던 것이다.

관련 문서 https://docs.gradle.org/current/dsl/org.gradle.api.Task.html