콘텐츠로 건너뛰기

빌드 자동화 도구란? 개요 및 Maven과 Gradle 분석

  • 테크

비즈스프링은 다양한 개발 언어를 활용하여 프로그램을 구축하고 있는데요, 그 중에서도 보편적으로 가장 많이 사용하는 Java Spring Boot 프레임워크(이하 스프링 부트)를 사용하여 프로그램 개발 및 구축을  진행하고 있습니다.

이번 시간에는 스프링 부트 프로젝트를 구축하는 데 있어 가장 많이 사용하는 빌드 자동화 도구에 대해 살펴보겠습니다.

Springboot Logo

빌드 자동화 도구

하나의 프로그램을 만들기 위해선 소스코드를 컴파일하고, 정적 및 동적 링크로 연결하는 과정이 필요합니다.
이 과정에서, 외부 프로그램(라이브러리)을 사용할 경우 해당 라이브러리를 연결해 주는 작업도 수행되어, 최종적으로 실행 가능한 프로그램으로 만들게 됩니다. 이러한 전체 과정을
빌드(Build)라고 합니다.

Build Process
빌드 과정 (출처: https://st-lab.tistory.com/176)

이러한 빌드 과정들은 작은 프로젝트에서는 큰 문제가 되지 않지만, 개발 및 프로그램 규모가 커질수록 관리해야 할 요소가 늘어납니다. 특히 라이브러리 규모가 커지고, 그로 인하여 프로그램 빌드 과정에서 오류를 제거하기 위한 테스트 과정이 복잡해지는 등 빌드의 관리 포인트가 증가하게 되어 불필요한 리소스를 낭비가 발생할 수 있습니다

이를 해결하기 위해, 개발자가 반복적으로 수행해야 하는 작업들을 체계적인 프로세스를 통해 자동으로 실행하고 믿을 수 있는 결과물을 생산하는 도구가 필요합니다.
가장 대표적인 예로 라이브러리를 간편하게 추가하고 관리할 수 있으며, 버전을 효율적으로 동기화하여 개발자가 비즈니스 로직에 집중할 수 있도록 도와줍니다.

이러한 작업을 자동화하는 도구를 빌드 자동화 도구(Build Automation Tool)라고 합니다. 이 도구를 통해 프로그램 소스들을 실제로 실행 가능한 형태로 변환하고, 이를 배포 및 실행할 수 있게 됩니다.

Build Automation tools
빌드 자동화 도구(출처: https://www.delftstack.com/howto/java/build-tools-in-java/)

Java의 가장 대중화된 자동화 빌드 도구, Maven과 Gradle

Maven

Apache Maven

Maven(이하 메이븐)은 자바 애플리케이션 전용 자동화 빌드 도구입니다.

기존 자바 애플리케이션 자동화 빌드 도구는 Ant(이하 앤트)라는 도구를 이용했었습니다.
앤트는 XML 기반의 자동화 빌드 도구로 xml 파일 내에 빌드 스크립트를 작성하여 빌드 자동화를 이룰 수 있는 도구입니다.

앤트의 가장 큰 특징은 빌드 스크립트라는 말처럼 빌드 자동화를 설정하기 위한 별도의 규약 없이 원하는 대로 스크립트를 작성할 수 있는 점인데, 자율성이 높다는 것은 장점이나 프로젝트 규모가 커질수록 빌드 스크립트가 복잡하고 정형화 되어있지 않기 때문에 유지보수가 어려운 단점이 있습니다.
또, 빌드에 대해서는 관리가 가능하지만, 외부 라이브러리를 관리할 수 없는 큰 단점이 있습니다.

이를 보완하기 위해 아파치 재단에서 앤트를 보완한 메이븐을 배포하였습니다.

메이븐의 특징은 다음과 같습니다.

  • 아파치 라이센스로 배포되는 오픈 소스 소프트웨어입니다.
  • 프로젝트의 빌드 프로세스를 XML 기반의 설정 파일(POM, Project Object Model)을 통해 정의합니다.
    해당 파일은 프로젝트별로 pom.xml 파일에 정의하게 됩니다.
  • 앤트와 다르게 XML 작성 형식이 정해져 있습니다.
    이러한 일관된 구조로 인해 사용하기 쉽고, 유지보수가 용이합니다.
  • 프로젝트의 종속성을 정의 및 관리가 가능합니다. 이를 통해 프로그램에 필요한 라이브러리들을 자동으로 다운로드하여 빌드에 포함시킬 수 있습니다.
  • 중앙 저장소를 통한 자동 의존성 관리를 합니다.
    중앙 저장소는 라이브러리를 공유하는 파일서버입니다. 저장소는 아파치 재단에서 운영관리 하는 저장소를 사용할 수도 있고 별도의 사설 저장소를 사용도 가능합니다.

POM (Project Object Model)

POM은 종속성, 플러그인, 목표 및 기타 설정과 같은 프로젝트 및 구성 세부 정보에 대한 정보를 포함하는 XML 파일입니다.
프로젝트의 중앙 구성 파일 역할을 합니다.

  • 표준 프로젝트 구조를 적용하여 개발자가 다양한 프로젝트를 더 쉽게 이해하고 탐색할 수 있도록 해줍니다.
  • 종속성을 POM 파일에 선언할 수 있으므로 관리가 쉬워집니다.
  • 루트 POM은 일반적으로 프로젝트의 루트 디렉토리에 위치하며 구성 세부 정보를 정의하는 역할을 합니다.
  • 프로젝트에는 여러 개의 하위 모듈이 있을 수 있으며, 각 하위 모듈(루트 POM에서 구성 세부 정보를 상속)은 고유한 POM 파일을 갖지만, 전체 프로젝트를 감독하는 공통 또는 루트 POM도 있습니다.

POM에는 다음과 같은 정보들을 기재하여 관리합니다.

  • 프로젝트 정보 : 프로젝트의 이름, 개발자 목록, 라이센스 등
  • 빌드 설정 : 소스, 리소스, 라이프 사이클별 실행한 플러그인(goal) 등 빌드와 관련된 설정
  • 빌드 환경 : 사용자 환경 별로 달라질 수 있는 프로파일 정보
  • POM 연관 정보 : 의존 프로젝트(모듈), 상위 프로젝트, 포함하고 있는 하위 모듈 등

Gradle

Develocity Gradle
Develocity Gradle

Gradle(이하 그래들)은 Groovy(이하 그루비)를 기반으로 한 빌드 도구입니다.

앤트와 메이븐과 같은 이전 세대 빌드 도구의 단점을 보완하고 장점을 취합하여 만든 오픈소스로 공개된 빌드 도구로, 대규모 다중 프로젝트 빌드부터 다양한 언어에 걸친 빠른 개발 작업에 이르기까지 모든 것을 처리하도록 설계된 확장성이 뛰어난 빌드 자동화 도구입니다.
앤트의 장점인 자유로운 스크립트 작성과 메이븐의 장점인 라이브러리 관리 기능을 수용하면서도 동시에 XML 형식으로 인하여 다소 복잡해 보일 수 있는 메이븐의 단점을 보완한 빌드 도구입니다.

그래들의 특징은 다음과 같습니다.

  • Java, Kotlin, Scala, Android, Groovy, C++, Swift 등 대부분의 언어 애플리케이션을 지원이 가능합니다.
  • 별도의 프로그램 설치 없이 Gradle Wrapper를 프로젝트에 포함시켜 사용이 가능합니다.
  • 그루비 스크립트를 기반으로 구축되어 메이븐의 XML 방식보다 간결하게 작성됩니다.
    그루비 언어를 기반으로 작동하므로 변수 선언, if, else, for 등의 로직 구현이 가능합니다.
    이를 이용하여 동적 Build를 간편하게 설정할 수 있습니다.
  • 빌드 과정에서 병렬 처리와 캐싱을 활용하여 메이븐보다 약 10배~100배까지 향상된 성능을 구현할 수 있습니다.
    (참조 https://gradle.org/gradle-and-maven-performance/)
  • build.gradle 이라는 파일에 스크립트를 작성하여 관리합니다.

GradleMaven의 장단점 비교

Gradle

Maven

구축 및 빌드 시간이 짧습니다.

그래들 보다 성능이 느립니다.

스크립트의 양이 훨씬 더 짧고 깔끔합니다.

스크립트의 양이 그래들의 스크립트보다 약간 더 깁니다.

DSL(도메인 특정 언어)을 사용합니다.

XML 형식을 사용합니다.

태스크 기반으로 작업이 실행됩니다.

프로젝트와 관련된 목표 기반으로 작업이 실행됩니다.

Java 클래스 증분 컴파일을 지원합니다.

증분 컴파일을 지원하지 않습니다.

CI (지속적인 통합 도구)를 지원합니다.

대부분의 CI (지속적인 통합 도구)를 지원합니다.

Maven과 Gradle의 설정 파일 내용 간단비교

다음과 같은 조건의 프로젝트를 생성하여 비교해보겠습니다.

  • Java 17
  • Spring Boot Web + MySQL Connector 라이브러리
  • war 파일 패키징
  • 그룹명 org.example
  • 프로젝트명 test
				
					Maven

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>3.4.1</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>org.example</groupId>
   <artifactId>test</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>war</packaging>
   <name>test</name>
   <description>test</description>
   <url/>
   <licenses>
      <license/>
   </licenses>
   <developers>
      <developer/>
   </developers>
   <scm>
      <connection/>
      <developerConnection/>
      <tag/>
      <url/>
   </scm>
   <properties>
      <java.version>17</java.version>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>


      <dependency>
         <groupId>com.mysql</groupId>
         <artifactId>mysql-connector-j</artifactId>
         <scope>runtime</scope>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-tomcat</artifactId>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>


   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>


</project>

				
			
				
					Gradle

plugins {
   id 'java'
   id 'war'
   id 'org.springframework.boot' version '3.4.1'
   id 'io.spring.dependency-management' version '1.1.7'
}


group = 'org.example'
version = '0.0.1-SNAPSHOT'


java {
   toolchain {
      languageVersion = JavaLanguageVersion.of(17)
   }
}


repositories {
   mavenCentral()
}


dependencies {
   implementation 'org.springframework.boot:spring-boot-starter-web'
   runtimeOnly 'com.mysql:mysql-connector-j'
   providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
   testImplementation 'org.springframework.boot:spring-boot-starter-test'
   testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}


tasks.named('test') {
   useJUnitPlatform()
}

				
			

보시는 바와 같이 스크립트 길이와 가독성 면에서 그래들이 앞서는 것을 확인 할 수 있습니다.
라이브러리나 모듈 간의 의존성이 늘어날수록 메이븐과 그래들의 스크립트 길이의 차이가 더욱더 벌어져 유지보수 난이도에서 그래들이 더욱더 유리해질 수 있습니다.

또, 동일한 프로젝트를 빌드 시, 그래들이 메이븐보다 빌드 시간이 더 짧습니다.
증분 변경 시에 이 빌드 시간의 차이는 더욱더 벌어지게 되는데 이는 그래들은 빌드 과정에서 캐시를 사용하여 기존과 동일한 부분은 빠르게 처리합니다.
이러한 특성으로 인하여 빌드가 반복될 시 시간 차이는 더욱더 벌어집니다.

이상으로, 빌드 자동화 도구의 기본 개념과 자바 애플리케이션 빌드 자동화 도구인 메이븐, 그래들에 대해 정리해보았습니다.

위 글의 내용 중 궁금한 점이 있다면 언제든지 문의 해주시길 바랍니다.
감사합니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다