거북이-https://velog.io/@violet_evgadn 이전완료

Gradle이란 본문

웹 개발/Spring(이론)

Gradle이란

VioletEvgadn 2022. 11. 25. 14:29

Jenkins를 적용하다 보니 Gradle Command을 활용해 작업물을 WAR파일로 Build 할 필요가 있었다.

따라서 Gradle에 대해 먼저 알아보고 다음 Section에서 Gradle Build에 관한 명령어에 대해 뜯어보는 과정을 가져보자.


Gradle

◎ Gradle이란?

Gradle은 "Compile, Test, Packaing, Deploy & Run" Task들을 자동화시켜주는 Build Tool이다.

 

이전에 배웠듯 Compile은 Java 파일을 Byte Code(.class 파일)로 변환해주는 작업, Test는 JUnit 등을 활용한 테스트 작업, Packaging은 만들었던 Byte Code를 활용해 실행 파일(JAR나 WAR)로 만들어주는 작업, Deploy & Run은 패키징 한 실행 파일을 실행시키는 과정을 말한다.

 

Gradle로 프로젝트를 빌드할 때는 Gradle을 개발자 로컬 환경이나 CI 서버에 설치하지 않아도 되는데, 이는 바로 Gradle Wrapper라는 존재 때문이다.

 

Gradle Wrapper는 선언되어 있는(사용 할) 버전의 Gradle을 호출하고 빌드하기 위해 미리 다운로드된 스크립트로써 빌드할 프로젝트에 포함되어 CI 서버나 개발자 로컬 환경에 배포된다.

이렇게 배포된 Gradle Wrapper는 빌드 환경에 Gradle이 설치되어 있지 않더라도 프로젝트를 Gradle을 통해 빌드할 수 있게 도와준다.

 

Gradle Wrapper를 활용할 경우 Java나 Gradle을 설치할 필요 없이 새로운 환경에서도 Gradle Build가 가능해진다. 또한 Gradle Wrapper를 활용하여 빌드를 수행할 경우 선언되어 있는 Gradle 설정값을 가지고 와 빌드를 수행하므로 어떤 환경에서 Gradle Build를 수행하던지 동일한 버전의 Gradle로써 빌드할 수 있다는 장점도 가진다.

 

◎ Gradle 디렉터리 구조

  • .gradle : 작업(Task)을 통해 생성된 파일이 저장됨
  • .idea : Editor 관련 파일
    • 사실상 위 2개는 편집하는 일이 거의 없으므로 무시해도 됨
  • gradle : Build를 수행할 Gradle Wrapper에 대한 정보가 저장되어 있음 
    • gradle-wrapper.jar : Gradle Wrapper 파일
    • gradle-wrapper.properties : Gradle Wrapper의 설정 파일로써 Wrapper 버전을 변경하거나 Task 실행 시 새로운 Wrapper 파일을 로컬 캐시에 다운로드하는 등의 작업을 수행할 수 있다
  • gradlew : gradle 명령 파일 for Unix
  • gradlew.bat : gradle 명령 파일 for Windows
  • settings.gradle : Build할 Project에 대한 구성 설정
    • 멀티 프로젝트를 구성할 경우 프로젝트 간 의존성, Sub Project 및 교차 프로젝트에 대한 설정을 수행함
    • Single Project, 즉 src 밑에 1개의 Project만 존재할 경우에는 생략이 가능
  • build.gradle : Project Build에 대한 모든 기능 정의
    • 빌드 구성 스크립트(Build Configuration Script)
    • 의존성, Plugin 등 빌드에 필요한 여러 가지 설정을 하는 Script
  • src : (자바) 소스 파일. src 아래 있는 작업물을 빌드하여 배포한다

 

즉, gradle-wrapper.properties의 설정값을 통해 gradle-wrapper.jar라는 Gradle Wrapper(Build 실행 주체)가 생성되며 이렇게 만들어진 Gradle Wrapper가 Gradle Build를 수행하므로 gradlew(gradlew.bat)은 어떤 환경이든 동일한 버전의 Gradle을 활용하여 Build를 수행할 수 있는 것이다.


Gradle의 장점

◎ 직관적인 코드

Gradle은 이전에 존재하던 Build Tool인 Maven이나 Ant보다는 직관적이다.

Maven을 활용해본 경험이 있으면 느꼈겠지만 모든 설정파일들이 XML로 이루어져 있어 파악이 매우 어렵다.

 

Gradle은 Groovy라는 언어를 이용하기 때문에 코드를 통해 설정 정보를 구성한다.

즉, XML의 구조적인 틀을 벗어날 수 있어 설정 파일들에 대한 정의가 간단하며 코드를 통해 설정 파일을 관리하므로 더욱 직관적인 Script를 통해 설정 파일을 관리할 수 있게 된다.

 

◎ 뛰어난 Dependency 관리 기능

Maven은 상속 구조를 통해 의존성을 가지고 오지만 Gradle은 설정 주입 방식으로 의존성을 가지고 온다.

먼저 이 둘에 어떤 차이가 있는지 알아보자.

 

나는 3.3 버전의 A Dependency를 활용하고 싶다고 가정하자. 그리고 3.3 버전의 A는 2.0 버전의 B Dependency를 활용한다고 가정하자.

Maven 같은 경우 이러한 상황에서 A Dependency와 B Dependency를 모두 pom.xml 같은 설정 파일에 입력해줘야 한다.

문제는 버전이다. pom.xml에서는 Dependency에 대한 Version도 입력을 받으므로 A에는 3.3, B에는 2.0을 써줘야 할 것이다.

그런데 이런 상황에서 A를 4.5 버전으로 올려야 하는 상황이 왔다고 가정하자. 그런데 A 4.5 버전은 B 3.0 이상의 버전만 호환이 가능한 것이다. 이 경우 Maven에서는 A Dependency 버전을 4.5로 올리는 동시에 B 또한 2.0에서 3.0으로 버전을 올려야지만 정상적으로 A를 사용할 수 있다.

 

하지만 Gradle은 설정 주입 방식을 사용하므로 이런 문제가 존재하지 않는다.

Gradle에서는 A Dependency를 사용한다는 것만 명시해 놓는다면 Gradle 측에서 자동으로 그에 가장 최적인 B Dependency를 "버전까지 맞춰서" 다운로드한다.

즉 A Dependency의 버전이 변화하더라도 Gradle 측에서 알아서 B Dependency의 버전까지 맞춰 다운로드하여 주기 때문에 Maven과 비교했을 때 매우 유지보수성이 뛰어나다고 할 수 있다.

 

이런 점에서 Gradle은 버전을 관리하기 쉽고 상속 과정에서 부모 Dependency를 찾아 버전을 일일이 수정해줄 필요가 없기 때문에 재사용성이 뛰어나며 의존성들에 대한 관리가 쉽다는 특징을 가지게 된다. 

 

◎ 다양한 Repository 사용 가능

Build Tool은 설정 파일에 Dependency를 입력해 놓으면 그에 맞는 JAR 파일을 가지고 와 실행하려고 하는 프로젝트에 적용함으로써 손쉬운 Build를 가능하게 한다.

이때 Dependency와 연동되는 JAR 파일을 저장하는 공간을 Repository라고 한다.

 

우리에게 가장 유명한 Repository는 아마 Maven Repository(Google Maven Repository, Maven Central 등) 일 것이다.

하지만 Gradle은 Maven Repository 뿐만이 아닌 JCenter 같은 다양한 Repository를 추가로 활용할 수 있으며 회사 내에서만 활용하는 Repository 등도 손쉽게 선언하여 사용할 수 있다는 장점을 가진다.

 

◎ Library를  활용하는 시점을 제한시킬 수 있음

Gradle에서 dependency들을 선언할 때 testImplementation, implementation, runtimeOnly, compileOnly 등 다양한 방법으로 의존성 설정이 가능함을 알고 있을 것이다.

 

이처럼 Gradle은 라이브러리를 상시 활용하는 implementation 이외에도 테스트 시에만 활용하는 testImplementation, 런타임 시에만 활용하는 runtimeOnly 등 필요한 시점에만 Library를 가지고 오도록 설정할 수 있다는 장점을 가진다.

 

가장 대표적인 예시가 Lombok의 "compileOnly"일 것이다.

사실 Lombok은 Compile 할 때 Annotation에 맞도록 getter, setter 등을 생성해 줬다면 실제로 코드가 수행될 때는 굳이 Library에 있는 기능들을 활용할 필요가 없다.

따라서 Compile 시에만 Lombok을 사용하고 컴파일이 완료되고 빌드된 작업물(WAR, JAR 파일 등)이 실제로 실행될 때는 Lombok을 활용하지 않도록 설정하기 위해 compileOnly를 사용함으로써 서버에 대한 부하를 줄일 수 있는 것이다.

 

◎ 빠른 빌드 속도

https://gradle.org/gradle-vs-maven-performance/

 

Gradle | Gradle vs Maven: Performance Comparison

Gradle is up to 100 times faster than Maven. Take a look at case studies and find out more about the performance advantages of Gradle over Maven.

gradle.org

Gradle은 속도 측면에서 매우 큰 자신감을 내보이는 것 같다.

실제로 Maven과는 달리 Gradle 사이트에는 Maven과의 성능 비교를 진행하고 결과를 게시해놓았다.

 

그렇다면 어떻게 Gradle은 빠른 Bulid가 가능한 것일까?

 

1. Daemon Process

Gradle은 데몬 프로세스를 지원한다.

데몬 프로세스란 서비스 요청에 응답하기 위해서 오랫동안 살아 있는 Process를 의미하는데 Gradle의 데몬 프로세스는 메모리 상에 이전 Build 결과물들을 보관한다.

 

이렇다 보니 Gradle은 첫 번째 빌드할 때만 빌드 시간이 오래 걸리고 이후부터는 Daemon Process가 저장한 Build 결과물을 활용해 바뀐 부분만 교체한 뒤 빌드를 수행하여 훨씬 적은 시간으로 Build를 수행할 수 있다.

이렇게 빌드할 파일들을 모두 빌드하는 것이 아닌 이전 Build 결과물에서 바뀐 파일들만 변경시켜 빌드하는 것을 "점진적 빌드(Incremental Build)라고 한다.

 

2. Build Cache

만약 2개 이상의 빌드가 동시에 돌아가고 하나의 빌드에서 사용되는 파일이 다른 빌드들에서도 사용된다면 Gradle은 빌드 캐시를 이용해 이전 빌드의 결과물을 다른 빌드에서 사용할 수 있다.

즉, 중복된 빌드는 다시 빌드할 필요가 없으므로 빌드 시간이 줄어든다.

 

3. 불필요한 Compile 방지

Gradle의 Smart classpath analyzzer는 Library의 Binary Interface가 변경되지 않았을 경우 불필요한 Compile을 방지한다.


빌드 관리 도구의 역사

◎ Ant

빌드 도구가 존재하기 이전 Java 프로젝트를 Tomcat에서 실행시킬 수 있는 실행 파일로 만들기 위해서는 Make 파일 같은 것을 사용해 Shell Command를 통해서 Build 과정을 수행해야 했다.

 

아마 Windows와 Linux의 Command 명령을 많이 입력해본 사람은 알겠지만, OS가 다를 경우 Shell Command 문법도 달라진다. 이 말인즉슨 Window에서 빌드하기 위한 Make 파일과 Linux에서 빌드하기 위한 Make 파일, 최소 2개를 만들어야 한다는 것이다.

이토록 OS에 의존적인 빌드 방법을 사용하기 귀찮았기에 빌드 관리 도구의 필요성이 커졌으며, 이런 이유로 나온 게 Ant 빌드 관리 도구이다.

 

Ant는 OS와 관계없이 XML 파일 기반으로 Build Script를 작성한다.

Build Script에 자유롭게 빌드에 관련된 설정값을 입력한다면 Ant 측은 알아서 Build Script에 기입된 내용을 바탕으로 프로젝트를 빌드해주는 것이다.

 

Ant를 통해 Build 설정을 XML 형태로 작성할 수 있어 계층적으로 보기가 쉬워졌으며 Task를 지정함으로써 확장성도 크게 증가시켰다.

또한 Shell Command로 직접 수행 방법을 명시하지 않아도 되므로 난해한 표기법이 없으며 OS 별로 따로 Make 파일을 만들 필요도 없어졌다.

 

하지만 Ant에는 큰 단점이 존재한다.

바로 Project가 커질수록 Script 관리와 빌드 과정이 복잡해진다는 것이다. 그리고 이는 Ant의 "생명주기를 갖지 않는다"의 이유가 크다.

 

생명 주기를 가지고 있다는 것은 이미 개발자들이 "우리가 직접 만들고 수행시켜야 할 과정들"을 자동화시켜줬다는 것을 의미한다.

반대로 Ant같이 생명 주기를 가지고 있지 않다면 다른 빌드 관리 도구(Maven, Gradle 등)에서 생명 주기에 의해 자동으로 처리되는 일을 개발자가 직접 수행해줘야 한다는 것이다.

Ant 같은 경우 생명주기가 없기 때문에 Target에 대한 의존 관계를 일일이 명시해줘야 하고, 당연히 이런 수작업은 작업 효율을 떨어뜨리고 Human Error의 가능성을 높일 것이다.

 

◎ Maven

Ant의 단점을 해결하기 위해 새롭게 도입된 빌드 관리 도구이다.

Maven은 Ant와 마찬가지로 XML 기반으로 Build에 관련된 내용을 작성하는데, Ant의 Build Script보다는 더욱 간단하게 작성할 수 있도록 업그레이드시켰다.

 

개발자는 "pom.xml"이라는 Script를 통해 필요한 라이브러리를 선언하고, Maven은 선언된 라이브러리에 맞는 JAR파일을 프로젝트로 불러오는 역할을 수행한다.

 

특히 Maven은 생명 주기(Lifecycle)와 프로젝트 객체 모델(POM; Project Object Model)이란 개념을 도입함으로써 Ant가 가지고 있던 많은 불편함과 높은 사용 난이도를 낮췄다.

 

물론 Maven도 Ant와 비교했을 때 쉬웠을 뿐 난이도는 여전히 높았으며 Library가 의존하는 경우 상속 관계 및 호환 가능 버전을 일일이 확인하고 상속 관계에 있는 라이브러리 버전을 모두 확인해줘야 했다는 점에서 큰 불편함을 가지고 있었다.

 

이런 단점을 보완하기 위해 Groovy 문법을 통해 코드로써 Script를 작성할 수 있으며 설정 주입 방식으로 상속 관계 버전 호환성을 크게 신경 쓰지 않아도 되는 Gradle이라는 문법이 새로 나오게 된 것이다.

 

※ POM

  • 프로젝트의 중요한 정보를 정의하고 정리하기 위한 장소.
  • pom.xml을 통해 프로젝트 관리 및 빌드에 필요한 환경 설정, 저장소 서버 위치 지정, 의존성 관리 등의 정보를 저장하는데 이러한 설정 정보들이 POM에 저장되어 원하는 설정대로 Build가 수행되는 것이다.

 

 Maven LifeCycle

출처 : https://tomgregory.com/maven-phases-vs-goals/

  • Clean : 이전 빌드에서 생성된 파일들을 삭제하는 단계
  • Validate : Project가 올바른지 확인하고 모든 정보를 활용할 수 있는지 확인하는 단계
  • Compile : Project Code를 컴파일
  • Test : JUnit 등을 통해 작성된 Test Code 실행
  • Package : 실제 컴파일된 소스 코드 및 리소스를 JAR나 WAR 파일로 합쳐 실행 파일로 만드는 단계
  • Verify : 품질 기준 충족 여부 확인
  • Install : 패키지를 로컬 저장소에 설치하는 단계
  • Site : 프로젝트 문서를 생성하는 단계
  • Deploy : 만들어진 실행 파일을 원격 저장소에 Release 하는 단계

 

Gradle LifeCycle

출처 : https://proandroiddev.com/understanding-gradle-the-build-lifecycle-5118c1da613f

  • Initialization(초기화) : 빌드 대상 프로젝트를 결정하고 각각에 대한 Project 객체를 생성
  • Configuration(구성) : 빌드 대상이 되는 모든 프로젝트의 Build Script 실행
  • Execution(실행) : 구성 단계에서 생성된 Project Task 중 실제로 실행시킬 것을 결정

'웹 개발 > Spring(이론)' 카테고리의 다른 글

URL과 Spring MVC 연동 과정  (0) 2023.02.27
WAR와 JAR  (0) 2022.10.17
Spring Web 계층  (0) 2022.09.19
DTO 클래스  (0) 2022.09.19
Spring의 데이터 처리 방법  (0) 2022.09.19
Comments