그래이들(Gradle)이란 무엇인가?

2020. 8. 12. 15:38Spring Boot

인텔리제이로 새 프로젝트를 생성할 때 프로젝트 유형을 그레이들로 선택한다. 이후 ArtifactId 와 GroupId를 등록한다. 이 설정이 끝나면 그레이들 기반의 자바 프로젝트가 생성된다.

 

그래이들 = 빌드 도구

그렇다면 그레이들 Gradle 이란 무엇일까? 위키백과에 대략적으로 서술된 내용에 따르면 그래이들은 Groovy를 이용한 빌드 자동화 시스템이다. 빌드 자동화의 목적은 소프트웨어 개발자가 반복적으로 해야 하는 코딩을 잘 짜여진 프로세스를 통해 자동으로 실행하며, 믿을 수 있는 결과물도 생산해 낼 수 있는 일련의 작업방식 및 방법을 말한다.

 

다시 말해,

1) 빠른 기간동안 계속해서 늘어나는 라이브러리의 추가와

2) 프로젝트를 진행하며 라이브러리의 버전을 쉽게 동기화 하기 위해 등장한 것이다.

 

초기 자바의 빌드 도구로 Ant라는 도구를 많이 사용했으나, 늘어나는 라이브러리를 관리하기 위해 Maven, Gradle 등의 기존 Ant를 보완한 빌드 도구들이 생겨나게 되었다.

 

그렇다면 그레이들은 Ant와 Maven과 무슨 차이가 있는 것이고 어떤 특징을 가지고 있을까?

 

Ant vs Maven vs Gradle

1. Apache ANT

Ant는 자바 기반의 빌드 도구로 다른 빌드 도구보다 역사가 오래되었다. Ant 는 개발자가 원하는 것을 개발할 수 있다는 유연성에 큰 장점이 있다.

 

[Ant의 특징]

  • 각 프로젝트에 대한 XML 기반 빌드 스크립트 개발
  • 결과물을 넣을 위치를 정확히 알려줘야 하며, 프로젝트에 특화된 Target과 Dependency를 이용해 모델링 한다.
  • 명확한 빌드 절차가 필요하다
  • 생명주기를 갖지 않기 때문에 각각의 target에 대한 의존관계와 일련의 작업을 정의해주어야 한다.

 

[Ant의 단점]

  • 유연성이 높으나 프로젝트가 복잡해질 경우, 각각의 Build 과정을 이해하기 어렵다
  • XML, Remote Repository를 가져올 수 없었음
  • 스크립트 재사용이 어려움

2. Apache Maven

프로젝트에 필요한 모든 Dependency를 리스트의 형태로 Maven에게 알려, 관리할 수 있도록 돕는 방식을 말한다.

 

[Maven의 특징]

  • Dependency를 관리하고, 표준화된 프로젝트를 제공한다.
  • XML, remote repository를 가져올 수 있다. jar이나 class path를 굳이 다운로드 할 필요 없이 선언만으로 사용이 가능하다
  • 하위 XML이 필요 없는 속성도 모두 표기한다

 

즉 POM.xml이라는 Maven파일에 필요한 Jar, class path를 선언해 주면 직접 다운로드 할 필요 없이 Maven 은 Repository에서 필요한 모든 파일들을 해당 프로젝틀로 불러와준다. 이렇나 강점에도 불구하고, Maven은 몇가지 단점이 있다.

 

[Maven 의 단점]

  • 라이브러리가 서로 종속할 경우 XML이 복잡해진다.
  • 계층적인 데이터를 표현하기 좋지만, 플로우나 조건부 상황을 표현하기엔 어렵다.
  • 편리하지만 맞춤화된 로직 실행이 어렵다.

 

3. Apache Gradle

최근 소프트웨어 개발 범위의 변화에 따라 빌드 자동화에 대한 요구도 증가하게 되었다. Gradle 은 JVM 기반의 빌드 도구로 기존의 Ant와 Maven을 보완하였다. 따라서 JAVA 혹은 Groovy를 이용해 로직을 개발자의 의도에 따라 설계할 수 있다.

 

[Gradle의 특징]

  • 오픈소스 기반의 빌드 자동화 시스템으로 Groovy 기반 DSL(Domain-Specific Language)로 작성
  • Build-by-convention을 바탕으로 한다. 따라서 스크립트 규모가 작고 읽기 쉬움
  • Multi 프로젝트 빌드를 지원하기 위해 설계됐다.
  • 설정 주입 방식(Configuration Injection)

 

따라서 초기 프로젝트 설정에 드는 시간을 절약할 수 있으며, 기존의 Ant나 Maven 등과 같은 빌드 도구들과도 호환이 가능하다.

이렇게 해서 그레이들의 간단한 특징과 장점들을 알아보았다. 이후에는 책의 내용을 따라가면서 개념을 정리해보겠다.

 

p.32 그레이들 프로젝트를 스프링 부트 프로젝트로 변경하기

생성된 프로젝트에서 build.gradle 파일을 열어보면 다음과 같은 코드들이 있다.

plugins { 
	id 'java'
} 

group 'com.jojoldu.book' 
version '1.0-SNAPSHOT' 

sourceCompatibility = 1.8 

repository { 
	mavenCenteral()
} 

dependencies { 
	testCompile group: 'junit', name: 'junit', version: '4.12'
}

 

이 빌드 파일을 바탕으로 스프링 부트에 필요한 설정들을 추가하면 스프링 부트 프로젝트에 필요한 빌드 파일 설정이 되는 것이다.

 

https://start.spring.io/ 에서 GUI를 통해서 빌드에 필요한 파일들을 생성해서 다운로드 받을 수 있지만 공부하는 입장에서는 역시 직접 만들어보는 것이 옳겠다.

 

위의 코드를 아래와 같이 update 한다.

buildscript {
    ext {
        springBootVersion = '2.1.7.RELEASE'
    }
    repositories {
        mavenCentral()
        jcenter()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group 'com.jojoldu.book'
version '1.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

이제 내용들을 하나하나 뜯어보겠다.

 

buildscript 메소드

빌드 스크립트 자체를 빌드하는 과정에서 필요한 외부 라이브러리를 클래스패스에 추가하는 기능을 한다. 중괄호로 묶은 내용(closure)을 ScriptHandler로 전달한다. ScriptHandler는 클로저를 인자로 받는 두 개의 메소드(repositories와 dependencies)를 갖고 있다. 빌드 스크립트에서 클래스패스를 추가할 경우에는 구성(configuration) 이름으로 classpath 문자열이 필요하다.

 

A ScriptHandler allows you to manage the compilation and execution of a build script. You can declare the classpath used to compile and execute a build script. This classpath is also used to load the plugins which the build script uses.

 

의역: ScriptHandler는 빌드 스크립트에서의 통합과 실행을 관리할 수 있게 해줍니다. classpath를 선언함으로써 빌드 스크립트들을 컴파일하고 실행할 수 있었습니다. 이 classpath는 빌드 스크립트가 사용할 플러그인들을 불러오는데에도 사용됩니다.

 

repositories 메소드

저장소 설정을 담당한다. 클로저 내용은 RepositoryHandler를 통해 실행된다. RepositoryHandler는 메이븐 중앙 저장소 추가를 위한mavenCentral 메소드와 Bintray의 jCenter 저장소 추가를 위한 jcenter 메소드를 제공한다.

 

A RepositoryHandler manages a set of repositories, allowing repositories to be defined and queried.

 

의역: RepositoryHandler는 저장소들의 세팅을 관리하고,이 저장소들을 정의되고 검색될 수 있게 합니다.

 

JCenter is the place to find and share popular Apache Maven packages for use by Maven, Gradle, Ivy, SBT, etc. …

 

의역: JCenter은 Maven, Gradle, SBT 에 아파치 Maven의 유명한 패키지들을 사용하기 위해 검색하는 공간입니다. (후략)

 

ext 메소드

ext 메소드는 그 인자를 buildScript 에서 전역변수로 사용하기 위해 사용되는 메소드이다.

ext {
    springBootVersion = '2.1.7.RELEASE'
}

 

 

dependencies 메소드

  • Gradle은 Maven과 Ivy를 지원한다.
  • 이행적 의존성이 아닌 일반 파일로 저장된 외부 라이브러리도 지원한다.
  • 빌드 스크립트에서 직접 의존성을 지정한다.

 

의존성 설정 기본

group, name, version 순서로 써줄 수 있다.

dependencies {
    compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
}
// 짧게 쓰면 "group:name:version"
dependencies {
    compile 'org.hibernate:hibernate-core:3.6.7.Final'
}

따라서 다음 코드는

dependencies {
    classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}

compile group: ‘org.springframework.boot’, name: ‘spring-boot-gradle-plugin’, version: ‘${springBootVersion}’ 가 축약된 형태다.

${springBootVersion}는 ext로 선언된 ‘2.1.7.RELEASE’ 를 말한다.

 

플러그인 추가 ‘apply plugin: … ‘

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

 

apply plugin: 은 Gradle 플러그인을 사용하기 위한 것이다.

 

apply plugin: java 는 Java 프로그램을 위한 기능을 제공하는 프로그램이다.

 

apply plugin: ‘eclipse’ 는 이클립스 IDE 설정파일을 생성하여, 이클립스로 프로젝트를 Import할 수 있도록 한다. 웹 프로젝트는 eclipse-wtp 플러그인으로 분리되었다. 따라서 WTP 프로젝트를 생성하려면 eclipse 플러그인을 적용해야 한다.

 

apply plugin: ‘eclipse’ 혹은 apply plugin: ‘eclipse-wtp’ 로 적용하자.

 

apply plugin: ‘org.springframework.boot’ 는 스프링 부트 프로젝트를 run 할 수 있게 만들어주는 스프링 부트 관련 플러그인이다. 간소화된 Spring configuration 을 적용시켜준다.

 

apply plugin: ‘io.spring.dependency-management’ 는 메이븐 의존성 관리 기능을 제공하는 플러그인이다.

 

sourceCompatibility 란?

group 'com.jojoldu.book'
version '1.0.1-SNAPSHOT'
sourceCompatibility = 1.8

sourceCompatibility를 설명하기 전에…

 

group 은 프로젝트 생성시의 groupId를 말하며, version 은 애플리케이션의 버전이다. 접미사로 SNAPSHOT이 붙으면 아직 개발단계라는 의미이다.

 

sourceCompatibility라는 단어에서 알 수 있듯이, 이것은 자바소스를 컴파일시키는 역할을 한다. 따라서 뒤에 붙은 숫자 1.8은 자바버전을 의미한다. 그런데 찾아보니 sourceCompatibility가 있고 targetCompatibility가 있다.

 

간단하게 말해서 sourceCompatibility는 자바버전 1.6 이상에서 사용하는 컴파일 메소드고 targetCompatibility는 1.5 이하에서 사용하는 컴파일메소드다.

 

그런데 여기서 주의해야 할 점이 있는데, sourceCompatibility로 1.5 이하에서만 사용하는 메소드를 컴파일 한다고 해서 VM에서 이것을 실행시키지 못하는 것은 아니다. (다만 MethodNotFoundException이나 ClassNotFoundException 에러가 찍힌다)

Gradle, “sourceCompatibility” vs “targetCompatibility”?

 

dependencies 메소드의 compile과 testcompile

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

compile 은 dependencies의 메소드 중 하나로 말그대로 애플리케이션을 빌드하기 위해 사용하는 메소드이다. testcompile 은 오로지 테스트를 위한 메소드이다. 따라서 spring-boot-starter-test 는 런타임 과정을 필요치 않기에, 릴리즈된 패키지를 포함하지 않는다. (오직 테스트 도구로만 사용된다는 것)