이번엔 groovy와 gradle에 대해 간단히 알아보겠습니다.
gradle은 groovy를 기반으로 한 빌드 도구입니다.
Groovy
gradle은 기본적으로 groovy 기반이기 때문에 groovy 문법을 알아야 잘 다룰 수 있습니다.
groovy의 모든 타입은 java Class에 대응됩니다. 변수가 어떤 java class일지 생각하면서 읽으면 더 좋습니다.
문자열
- 작은 따옴표: 단순 문자열
- 큰 따옴표: 문자열 내부에
$변수
사용 가능 - 여러줄 사용:
''' '''
,""" """
사용 가능
메서드 호출
println ('Hello')
println 'Hello'
groovy의 경우 ( )
를 생략할 수 있습니다.
형 생략
String message = 'hi'
def message = 'hi'
둘 다 같은 결과입니다.
클로저
def closure1 = {
println 'hi'
}
closure1.call()
closure1()
클로저는 java의 lambda와 비슷한 문법입니다. 클로저에 ()
를 붙여서 실행시킬 수 있습니다.
gradle DSL 기본 개념
gradle script는 configuration scripts
라고 불리는데, 이는 스크립트가 실행될 때 특정 유형의 객체를 구성하는 것을 의미합니다.
예를 들어 build script가 실행되면 Project
유형의 객체를 구성하고, Init script가 실행되면 Gradle
유형의 객체를 구성하는 방식입니다.
이런 객체를 delegate 객체
라고 부르는데, delegate 객체
의 속성이나 메서드는 스크립트에서 사용할 수 있습니다.
그리고 각 gradle script는 Script
라는 인터페이스를 구현합니다.
Script 인터페이스?
내부적으로 buildscript, logging, resources 같은 property들을 가지고 있고, 흔히 보는 copy, exec, file, mkdir 같은 메서드들도 가지고 있습니다.
뿐만 아니라 Script 인터페이스는 위에서 언급한 delegate 객체를 포함하고 있어서 Script 인터페이스에 없는 메서드나 property는 그 build script에 맞는 delegate 객체에서 찾기도 합니다.
참고: https://docs.gradle.org/current/dsl/org.gradle.api.Script.html
build script structure
빌드 스크립트는 0개 이상의 statements와 스크립트 블록으로 구성됩니다.
스크립트 블록은 클로저를 매개변수로 받는 메서드 호출입니다.
최상위 스크립트 블록으론 dependencies
를 예로 들 수 있습니다.
dependencies {
...
}
core types
핵심 유형으로 Project, Task, Gradle 등이 여기에 포함됩니다.
contatiner types
컨테이너 유형은 요소들을 보관하고 handling하는 유형이고, TaskContainer, DependencyHandler 등이 있습니다.
task types
빌드 스크립트에서 사용할 수 있는 예약된 작업 유형들입니다.
Copy, Delete, Exec, Test, Jar 등이 있습니다.
task
task myFirstTask {
println 'Hello World'
}
위와 같이 build.gradle
파일을 간단하게 만들어서 실행시켜보겠습니다.
$ gradle myFirstTask
> Configure project :
Hello World
BUILD SUCCESSFUL in 307ms
doFirst, doLast
gradle Task에는 몇몇 예약어가 있습니다.
그 중 먼저 doFirst, doLast는 말 그대로 task 안에서 처음과 마지막에 수행하는 action입니다.
task안에서 수행하는 단위를 action이라고 부릅니다.
parameter
테스크를 실행할 때 -Pkey=value
를 이용해 파라미터를 전달할 수 있습니다.
task hello {
println 'Hello ' + myname
}
$ gradle hello -Pmyname=hyeonmo
> Configure project :
Hello hyeonmo
BUILD SUCCESSFUL in 450ms
참고로 task 안에서 그냥 name 변수는 task명을 가져옵니다.
task 간 의존성 설정
depnedsOn
을 사용하면 task간의 실행 순서를 지정할 수 있습니다.
task hello {
dependsOn('welcome') {
println 'Hello'
}
}
task welcome {
println 'Welcome'
}
$ gradle hello
> Configure project :
Welcome
Hello
BUILD SUCCESSFUL in 376ms
$ gradle welcome
> Configure project :
Welcome
BUILD SUCCESSFUL in 299ms
gradle은 사용자가 정의한 종속성 순서대로 실행되도록 보장해주는데, 이 때 gradle은 아래와 같은 종속성 그래프라는걸 만듭니다.
(사실 순환이 없어서 종속성 트리가 더 맞지 않나… 생각합니다)
자세한 내용은 build lifecycle 포스팅에서 다룰 예정입니다.