Gradle이란?

Jake Seo·2021년 7월 19일
0

자바 잡지식

목록 보기
10/17

위키 정의

Gradle은 빌즈 자동화와 다언어 개발을 지원하는데 초점을 맞춘 빌드 도구이다. 어떤 플랫폼에서든 소프트웨어의 빌드, 테스팅, 퍼블리싱, 배포를 한다면, Gradle은 코드 컴파일링 및 패키징부터 웹사이트 퍼블리싱까지의 전체 개발 라이프사이클을 지원할 수 있는 유연한 모델이다. Gradle은 자바, 스칼라, 안드로이드, 코틀린, C/C++, 그루비를 포함한 다양한 언어와 다양한 플랫폼들에 걸쳐 빌드 자동화를 지원하기 위해 디자인되었고 Eclipse, Intellij, Jenkins와 같은 개발 도구들과 CI 서버들에 밀접하게 통합되어 있다.

Gradle Overview

Gradle은 오픈소스 빌드 자동화도구로 어떤 타입의 소프트웨어도 빌드하기 충분한 유연성을 가지도록 디자인되었다. 아래는 Gradle의 가장 중요한 몇몇 기능들의 고수준 개요이다.

High performance

Gradle은 입력 혹은 출력이 변경되었기 때문에, 실행할 필요가 있는 작업들만 실행함으로써 필요 없는 작업을 하지 않는다. 빌드 캐시를 사용하여 task의 결과를 재사용하게 만들 수 있다. 이전 task 결과는 물론이고, 다른 머신으로부터 가져올 수도 있다. (공유하는 빌드 캐시에서)

JVM foundation

Gradle은 JVM에서 돌아가고 사용자는 JDK가 설치되어 있어야 한다. 자바 플랫폼에 익숙한 유저들에게 커스텀 테스크 타입이나 플러그인 빌드로직 같은 곳에 표준 자바 API들을 사용할 수 있다는 것은 보너스이다. 그리고 JVM에서 동작한다는 것은 다른 플랫폼에서 Gradle을 동작하기 쉽게 만들어준다.

Conventions

Gradle은 Maven의 책을 본보기로 하여 프로젝트의 공통 타입을 만들었다. 이를테면, 자바 프로젝트와 같은 일반적인 프로젝트의 경우 컨벤션을 구현함으로써 빌드를 쉽게 만들었다. 적절한 플러그인을 적용하면, 많은 프로젝트에 대해서도 가벼운 빌드 스크립트로 쉽게 끝맺을 수 있다. 하지만 이러한 컨벤션이 제약을 주진 않는다. Gradle은 오버라이딩을 허가하고, 우리 고유의 태스크를 추가할 수 있게 하고, 컨벤션을 기반으로 한 빌드에 많은 커스터마이징을 할 수 있게 허가한다.

Extensibility

우리 고유의 태스크 타입 혹은 빌드 모델을 제공할 수 있도록 Gradle은 쉽게 확장이 가능하다. 이 예제를 알고싶다면 안드로이드 빌드 지원을 보면 좋다. flavors와 빌드 타입과 같은 새 빌드 개념들을 많이 추가시킨다.

Insight

Build Scan은 빌드 이슈를 확인하기 위해 사용할 수 있는 빌드 실행에 대한 폭넓은 정보를 제공한다. 특히 빌드의 퍼포먼스와 같은 문제를 확인하는데 도움을 준다. 빌드에 대한 이슈를 고치는데 도움을 받고 싶다면, Build Scan을 다른 사람들과 함께 공유할 수 있다.

Gradle에 대해 알아야 할 5가지

Gradle은 유연하고 강력한 빌드 도구이지만, 처음 사용할 때는 약간 겁먹게 만드는 도구이다. 하지만, 아래 핵심 원리를 이해하면 Gradle에 대해 다가가기 훨씬 쉬워지고 툴에 쉽게 적응할 수 있게 될 것이다.

1. Gradle은 범용 목적(general-purpose)의 빌드 도구이다.

Gradle은 어떤 소프트웨어든 빌드할 수 있게 해준다. 왜냐하면 Gradle이 우리가 하려는 것에 대해 몇가지 가정을 하기 때문이다. 가장 중요한 제약은 의존성 관리는 현재 오직 Maven, Ivy-compatible 리포지토리, 파일시스템만 지원한다.

이러한 사실은 우리가 빌드하는데 많은 일을 해야하지 않아도 되는 것을 의미한다. Gradle은 컨벤션 레이어와 plugins를 통해 미리 빌드된 기능을 추가함으로써 자바 라이브러리와 같은 일반 타입의 프로젝트를 쉽게 빌드할 수 있게 해준다. 우리 고유의 컨벤션과 빌드 기능을 캡슐화하기 위해서 커스텀 플러그인을 만들고 퍼블리싱할 수도 있다.

2. 코어 모델은 task에 기반한다.

Gradle은 Task(작업의 단위)의 DAG(Directed Acyclic Graph)로 빌드를 모델링한다. 이게 의미하는 바는 그 의존성들에 기반해서 그 DAG를 만들기 위해 빌드가 필수적으로 태스크의 집합을 설정하고, 태스크들을 연결해야 한다는 것이다. 일단 task 그래프가 만들어지면, Gradle은 어떤 작업들이 어떤 순서로 동작하는지 결정하고 실행시킨다.

이 다이어그램은 태스크 그래프의 두가지 예를 보여준다, 하나는 abstract이고, 하나는 concrete이다. 작업 사이의 의존성은 화살표로 표기되어 있다.

두 종류의 Gradle task 그래프이다.

거의 어떤 빌드 프로세스도 위와 같이 그래프로 모델링될 수 있다. 이게 Gradle이 유연한 이유이다. 그리고 task graph는 플러그인과 빌드 스크립트 모두에 의해 정의될 수 있다. task들은 task dependency mechanism을 통해 링크된다.

태스크는 자체적으로 아래의 것들을 포함한다.

  • Actions: 무언가를 하는 작업들 ex) 파일 복사, 소스 컴파일
  • Inputs: action이 사용하거나 작동하는 값, 파일 그리고 디렉토리들
  • Outputs: action이 수정하거나 만들어내는 파일과 디렉토리들

사실, 위의 모든 것은 옵션이며, 어떤 작업을 해야 하는지에 달렸다. 표준 라이프사이클 태스크와 같은 몇몇 태스크는 어떤 action도 가지지 않는다. 그냥 간단히 몇몇 작업들을 모아놓는다.

어떤 작업이 실행도리지 선택할 수 있다. 우리가 필요한 작업을 명시해놓음으로써, 시간을 절약할 수 있다. 단순히 유닛 테스트를 실행하길 원한다면, 유닛테스트를 하는 태스크를 선택하면 된다. 일반적으로는 test라는 태스크다. 애플리케이션을 패키징하고 싶다면, 일반적으로 assemble 태스크가 있다.

마지막으로: Gradle의 증분 빌드 지원은 견고하고 안정적이므로, 실제로 클린을 수행하고 싶지 않다면 클린 작업을 피해서 빌드를 빠르게 실행할 수 있다.

3. Gradle은 고정된 빌드 페이즈를 갖는다.

Gradle이 빌드 스크립트를 해석하고 실행할 때 세가지 페이즈를 거친다는 것을 이해하는 것은 중요하다.

1. 초기화
빌드를 위한 환경 설정을 세팅하고 어떤 프로젝트가 빌드에 참여할지 결정한다.

2. 설정
빌드에 대한 태스크 그래프를 생성하고 설정한 뒤 사용자가 실행하길 원하는 태스크를 기반으로 어떤 태스크가 어떤 순서로 실행되어야 하는지 결정한다.

3. 실행
설정 페이즈의 끝에 선택된 태스크들을 실행한다.

세 페이즈가 Gradle의 Build Lifecycle이다.

Apach Maven terminology와 비교하면, Gradle의 빌드 페이즈는 메이븐의 페이즈 같지 않다. 메이븐은 빌드 실행을 여러개의 스테이지로 나누기 위해 페이즈를 사용한다. 여러개의 스테이지는 Gradle의 태스크 그래프와 비슷한데, 덜 유연하다.

Maven의 빌드 라이프사이클의 개념은 Gradle의 lifecycle tasks와 느슨하게 닮아있다.

잘 디자인된 빌드 스크립트는 명령적인 것보다 선언적인 환경설정을 포함한다. 해당 환경설정은 설정 페이즈에서 이해할 수 있게 평가(evaluated)된다. 심지어 아주 많은 그러한 빌드들이 task actions를 갖는다. 이를테면 doLast {}doFirst {} 블록들을 통해서이다. 위 블록은 실행 페이즈에서 평가되는 것들이다. 이게 중요한 이유는 설정 페이즈 동안 평가되는 코드는 실행 페이즈 동안 일어나는 변화를 볼 수 없기 때문이다.

설정 페이즈의 또 다른 중요한 부분은 빌드가 동작할 때마다 관련된 모든 내용을 평가(evaluate)한다는 것이다. 설정 페이즈에서 무거운 작업을 피하는 것이 베스트 프랙티스인 이유가 바로 이것이다. Build Scans는 부하가 걸리는 곳이 어느 곳인지 확인하는데 도움을 준다.

4. Gradle은 많은 곳에서 확장 가능하다.

오직 Gradle만을 사용한 빌드 로직을 이용하여 프로젝트를 빌드할 수 있을 때, 매우 유용하다. 하지만 가능한 경우가 매우 적다. 대부분의 빌드는 커스텀 빌드 로직을 추가할 필요가 있는 특별한 요구사항들이 있다.

Gradle은 몇가지 매커니즘을 제공하여 확장하는 것을 도와준다.

커스텀 태스크 타입

현재 존재하는 태스크가 할 수 없는 일을 빌드가 해주길 원할 때, 자신만의 태스크 타입을 작성할 수 있다. 일반적으로 커스텀 태스크 타입에 대해서는 소스 파일을 buildSrc 디렉토리나 패키지된 플러그인에 넣는 것이 베스트 프랙티스이다. 그러면 그레이들이 제공하는 것들과 같이 커스텀 태스크 타입을 사용할 수 있다.

커스텀 태스크 액션

task 전 후로 작동할 커스텀 빌드 로직을 덧붙일 수 있다. Task.doFirst()Task.doLast() 메소드를 통해서 가능하다.

프로젝트와 태스크들에 대한 엑스트라 프로퍼티

커스텀 액션 혹은 다른 빌드 로직으로부터 사용할 수 있는 프로젝트 또는 태스크에 자신만의 프로퍼티를 추가할 수 있도록 도와준다. 엑스트라 프로퍼티는 명시적으로 사용자에 의해 생성되지 않은 태스크들에 대해서도 적용된다. 이를테면 Gradle의 코어 플러그인 같은 것들 말이다.

커스텀 컨벤션

컨벤션은 빌드를 간략화하기 위한 강력한 도구이다. 이로 인해 사용자들은 잘 이해하고 커스텀 컨벤션들을 더 쉽게 사용할 수 있다. 이러한 커스텀 컨벤션은 표준 프로젝트 구조와 네이밍 컨벤션을 사용하는 자바 빌드와 같은 곳에서 볼 수 있다.

커스텀 모델

Gradle을 사용하면 작업, 파일 및 의존성 구성 외에 새로운 개념을 빌드에 도입할 수 있다. 대부분의 언어 플러그인에서 이러한 것을 볼 수 있는데, source sets의 개념을 빌드에 추가하는 것이다. 빌드 프로세스의 적절한 모델링은 빌드의 사용 편의성과 효율성을 크게 개선할 수 있다.

5. 빌드 스크립트는 API를 기반으로 작동한다.

Gradle의 빌드 스크립트를 실행 가능한 코드로 보기 쉽다. 사실이니까. 하지만, 그건 구현 세부사항이다. 잘 디자인된 빌드 스크립트는 소프트웨어를 빌드하기 위해 어떤 과정을 밟아야 하는지에 대해 묘사하지, 어떻게 그 과정이 동작하는지 묘사하지 않는다. 어떻게 동작하는지에 대해서는 커스텀 태스크 타입과 플러그인이 할 일이다.

흔히 하는 오해로 Gradle의 파워와 유연성이 빌드 스크립트가 코드라는 사실에서 온다고 생각한다. 이것은 전혀 사실이 아니다. 기저에 깔린 모델과 API가 강력함을 제공한다. 베스트 프렉티스에서 우리가 권고하듯, 빌드 스크립트에 명령형 로직을 넣는 것을 피해야 한다.

빌드 스크립트를 실행 가능한 코드로 보는 것이 유용한 한 분야가 있다. 빌드 스크립트의 문법이 어떻게 Gradle의 API에 매핑되는지 이해하는 부분이다. API 문서는 Groovy DSL 레퍼런스Javadocs의 형태로 되어있다. 메소드와 프로퍼티를 리스트화한다 그리고 클로져와 액션을 참조한다. 빌드 스크립트의 컨텍스트 내부에서 이것들이 어떠한 의미를 가질까? 해당 질문에 대한 답을 배우기 위해서는 Groovy Build Script Primer를 확인해보아라. API 문서의 효율적인 사용을 할 수 있게될 것이다.

Gradle이 JVM을 통해 동작하기 때문에, 빌드 스크립트는 표준 자바 API 또한 사용할 수 있다. Groovy 빌드 스크립트는 추가적으로 Groovy API들을 사용할 수 있다. Kotlin 빌드 스크립트는 Kotlin API들을 사용할 수 있다.

profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글