[Build] 빌드 의미와 빌드 도구

2021. 8. 17. 23:40[ 백엔드 개발 ]/[ Spring ]

'빌드'한다는 것의 의미

- 빌드한다는 것은 컴파일보다 훨씬 더 큰 의미를 갖는다.

- 빌드툴의 설정파일에 라이브러리의 버전을 명시해주면 자동으로 다운받고 classpath에 추가해준다. (스프링'부트'의 starter를 사용하면 버전을 명시하지 않아도 관련된 의존성을 모두 다운로드 해줌)

- 소스코드를 '컴파일'한다.

- '테스트 코드'를 실행한다.

- 컴파일된 코드를 packaging한다. (jar, war, zip, ddl, exe 등의 파일로 만든다.)

- packaging된 파일을 주로 artifact(산출물)라 부르며 서버나 레퍼지토리에 배포한다.

 

즉, 소프트웨어를 '실행 가능한 하나의 단위'로 구성하는 과정이다.

 

 

 

빌드툴을 사용하는 이유

자바 애플리케이션 빌드 과정

 

즉, 빌드도구는 위 일련의 복잡한 작업들을 자동화하고 기술할 수 있도록 해준다. 빌드툴이 없다면 개발자가 직접 의존성을 다운받고 classpath에 추가한뒤, 컴파일하고 패키징하는 등의 작업을 해줘야 한다. 빌드툴은 이러한 일련의 빌드 과정을 명령어 한줄로 단순화한다. (반복적인 작업을 자동화해 개발자 생산성 증가)

 

cf. 빌드툴 종류 : Ant, Maven, Gradle, Cmake(C언어 진영)

 

 


 

Maven

- 주로 자바 기반 프로젝트에서 많이 사용된다.

- XML기반으로 설정 모델을 제공하고 pom(Project Object Model)파일로 수행할 작업들을 작성할 수 있다.

 

Maven을 사용하는 이유

- maven은 archetype이라는 프로젝트 템플릿 구조를 제공해서 매번 같은 설정을 반복하지 않게 해준다.

- 프로젝트에서 사용하는 외부 라이브러리(dependency)르 관리한다. 여기서 관리한다는 것은 다운로드, 라이브러리들 간 버전 호환성 관리 등이 포함된다.

- 플로그인과 외부 라이브러리를 분리해서 관리해준다. 즉, 플러그인에서 사용하는 라이브러리와 프로젝트에서 사용하는 라이브러리가 섞이지 않게 관리한다.

- 각각의 별도의 레포지토리를 통해서 jar파일 다운한다.(dependency를 갖게 한다.) 여기서 라이브러리를 다운받을 레포지토리는 로컬이 될 수도 있고(비공개) maven central과 같은 공개된 레포지토리일 수도 있다.

 

* maven coordinate

- maven 프로젝트의 메타데이터를 의미한다.

- groupId, artifactId, version으로 구성되고 maven프로젝트를 구분하기 위한 좌표와 같은 역할을 한다.

 

* SNAPSHOT의 의미

- version에 SNAPSHOT을 붙이는 경우가 있는데, SNAPSHOT은 계속 '개발이 되는 과정 진행중'임을 의미한다. 배포한 버전은 RELEASE가 붙는다. (예. 2.0.0-RELEASE)

 

* maven 멀티모듈

- maven 기반 프로젝트를 만들면 상위 폴더 아래 src라는 단일 모듈 구조가 기본적이지만 멀티모듈도 지원한다. pom.xml파일에서 <modules> 테그를 만들고 안에 <module> 테그를 통해 멀티모듈을 만들 수 있으며 개별 모듈 단위로 컴파일 가능하다. 이러한 구조는 프로젝트안에 서브 프로젝트를 갖는 구조와 유사하며 프로젝트 모듈 간 관계가 생긴다. 자식 모듈로 설정할 모듈의 pom.xml에 들어가서 <parent> 테그를 통해 부모 모듈을 지정한다.

 

 

 

Maven의 빌드 라이프사이클

maven에는 미리 정의된 빌드 라이프사이클(일련의 절차)가 있다. 즉, 프로젝트를 빌드할 때의 단계(순서)가 있다.

위 사진은 meven프로젝트를 IntelliJ에 로드하고 확인한 라이프사이클이다.

https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

 

* Transitive Dependency 관리

- 프로젝트에서 사용중인 라이브러리가 사용하는 또 다른 라이브러리를 Transitive Dependency라고 한다.

- 프로젝트의 외부 라이브러리들 간 의존성을 트리모양으로 관리해서 의존성들이 충돌나지 않도록 관리한다.

 

* 의존성 구조 확인

- mvn dependency:tree 명령어를 통해 의존성 트리구조를 확인할 수 있다.

- 의존성 구조를 확인해 보면 scope을 확인할 수 있다.

 

* 의존 범위(Dependency Scope)

- 종류: compile, provided, runtime, system, test 등

- provided: maven 프로젝트가 실행되는 도중에 어디선가에서 제공되는 라이브러리임을 의미함

- runtime: 컴파일시에 사용되지 않고 실행과 테스트할 때 사용되는 라이브러리임을 의미함

- system: provided와 비슷한데, 특정 jar파일의 위치를 지정할 때 사용함. 예를들어, 로컬의 어느 위치에 있는 jar파일을 읽어들일 때 사용함.

(https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html)

 

 


 

Gradle

Groovy(build.gradle) 또는 Kotlin (build.gradle.kts)과 같은 스크립트 언어를 DSL(Domain Specific Language)로써 제공해서 빌드하는데 발생할 수 있는 여러 일들을 기술한다. 스크립트 언어를 사용하기 때문에 마크업 언어인 XML을 사용하는 Maven보다 간단해 가독성이 좋지만 DSL언어의 문법을 알아야 한다는 단점이 있다.

 

cf. 그루비 언어는 스크립트 언어로써 JVM에서 실행되는데, 컴파일될 필요 없이 소스코드가 그대로 실행된다.

 

Gradle을 사용하는 이유

- 빌드를 하기 전에, 자바 컴파일 정보를 Caching해서 자바 코드가 재컴파일 되는 것을 방지한다. 원시코드와 클래스 간의 종속성을 분석하고 변경 사항의 영향을 받는 항목만 다시 컴파일하는 방식으로 성능상 이점이 있다. 이는 Maven과 가장 큰 차이점이다.

- 문법이 자바와 유사해서 XML보다 간결하게 표현가능하다. 

- 스크립트 파일을 groovy 또는 kotiln으로 작성해 XML을 사용하는 Maven보다 가독성이 좋다.

 

Q) JIT 컴파일러가 캐싱하는 것과 gradle의 캐싱은 어떤 차이가 있는건가?

 

 

* gradle task

- maven의 빌드 라이프사이클처럼 gradle에도 task라는 개념이 있다. 

- 플러그인이 추가되면서 관련된 task들이 추가된다. 예를들어 java 플러그인은 java 컴파일 task, java 컨벤션 task등이 추가된다.

 

* gradle wrapper

- gradle wrapper를 사용하면 Gradle이 설치되지 않은 컴퓨터에서도 Gradle 빌드를 실행할 수 있다. 서버에 CI가 있을 때 유용하다. 

 

* 멀티 프로젝트 빌드

maven처럼 다중 프로젝트는 루트 프로젝트와 여러 하위 프로젝트로 구성될 수 있다. (maven은 상속구조임)

 

 

cf. Maven과 Gradle의 공통점

- 멀티 모듈을 만들고 이들을 병렬로 실행시킬 수 있다.

 

 

 

 

 

Reference

- https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

- https://docs.gradle.org/current/userguide/plugins.html

- https://mindmajix.com/gradle-tutorial#what-are-build-tools

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

- https://www.jrebel.com/blog/java-build-tools-comparison