Computer Sience/10분 테코톡

[10분 테코톡] Gradle

제우제우 2024. 8. 26. 19:43

참고 자료 

[10분 테코톡] 루나의 Gradle

[10분 테코톡] 메리의 Gradle

Gradle 공식 문서

 

Gradle User Manual

Gradle Build Tool is a fast, dependable, and adaptable open-source build automation tool with an elegant and extensible declarative build language. In this User Manual, Gradle Build Tool is abbreviated Gradle.

docs.gradle.org

 


Gradle 이란?

2012년에 출시된 Groovy를 기반으로 한 오픈소스 빌드 도구로, 

거의 모든 타입의 소프트웨어를 빌드할 수 있는 빌드 자동화 시스템 

 

빌드

소스 코드를 컴파일, 테스트, 정적분석 등을 실행하여 실행 가능한 애플리케이션으로 만들어주는 과정 

 

다양한 라이브러리의 등장 

문제점

  • 라이브러리를 직접 다운로드 및 추가하는 번거로움 (반복적인 작업을 수작업으로 진행)
  • 개발자들 간의 버전관리 어려움 
  • 다운받은 jar 파일의 보안 위험 
  • 프로젝트의 의존성 파악이 어려움 

빌드 도구 

  • 빌드 도구는 코드를 실행 가능한 파일로 만들어 주는 과정(빌드) 및 라이브러리 관리, 테스팅 등을 자동화 하여 수행 
  • 계속해서 늘어나는 라이브러리를 자동 추가 및 관리 
  • 프로젝트를 진행하며 라이브러리의 버전을 쉽게 동기화 

Gradle 등장 전 빌드 도구의 역사 

APACHE ANT 

  • 기본적인 컴파일, 패키징, 배포 작업 수행 가능 
  • XML 기반의 스크립트 사용 
  • 작성에 정해진 규칙이 없어 유연성을 가짐 (정해진 규칙이 없어 유지보수가 어려움)
  • 라이브러리의 의존관계를 정의하는 구조의 부재 

Maven

  • 정해진 라이프 사이클에 따라 빌드 진행 
  • pom.xml 파일 사용 
  • 라이브러리 의존성 자동 관리 기능 추가 
  • xml 파일 기반으로 가독성이 좋지 않음 
  • 상속구조를 이용한 멀티 모듈 구현 
  • 의존관계가 복잡한 프로젝트에는 부적절 

Groovy

  • JVM 상에서 실행되는 스크립트 언어 
  • Java와 유사한 문법 구조를 가지며, 호환성이 아주 좋다.

스크립트 언어 

  • 동적으로 실행 가능 
  • 추가적인 로직을 작성하고 싶을 때 스크립트 로직을 직접 작성할 수 있다. 
  • Gradle이 지원하는 플러그인(Plugin)을 호출할 수 있다. 

Gradle은 Groovy 기반의 스크립트 언어이다. 

Groovy 기반의 DSL(특정 도메인을 대상으로 만들어진 특수 프로그래밍 언어) 


빌드 스크립트 

Plugins

Plugin: 특정 작업을 위해 모아놓은 task들의 묶음 

ex) Gradle의 'java' 플러그인 

자바 플러그인을 추가하면, 다음과 같은 task들이 추가되어 수행할 수 있다. 

 

의존성 관리 : Dependencies

프로젝트에서 사용하는 라이브러리나 패키지를 의존성이라고 한다.

프로젝트별로 어떤 의존성을 갖는지 명시해주어야 한다. 

 

Dependencies Configuration

  • 라이브러리를 추가하는 시점을 설정
  • 특정 시점에 불필요한 특정 라이브러리를 추가한다면 리소스 낭비이다. 

Dependencies Configuration 종류

  • Implementation: 런타임 + 컴파일 시점 모두에서 사용 
  • compileOnly: 컴파일할 때만 사용되고 런타임 때에는 미사용 
  • runtimeOnly: 런타임 때에만 사용 
  • testImplementation: 테스트할 때에만 사용 

Repositories

  • Repositories는 라이브러리(모듈)가 저장된 위치를 정의 
  • 대표적으로 Maven Central(), Jcenter(), Google Android()이 있다. 
  • 라이브러리의 저장소를 명시해주면 Gradle이 해당 저장소에서 필요한 라이브러리를 가져온다. 

Gradle 장점 

  • 프로젝트를 설정 주입(Configuration Injection) 방식으로 정의 
  • 멀티 프로젝트 빌드 
  • 빌드 속도가 빠름 

프로젝트를 설정 주입(Configuration Injection) 방식으로 정의 

Maven의 상속 구조보다 재사용에 용의 

프로젝트의 조건을 체크할 수 있어서 프로젝트별로 주입되는 설정을 다르게 할 수 있다. 

 

ex) 스프링 부트 버전에 따라 주입되는 라이브러리 버전이 달라진다. 

이런 방식을 통해 환경별, 프로젝트별로 필요한 설정을 유연하게 조정할 수 있게 해주어 매우 유용

 

멀티 프로젝트 빌드 

멀티프로젝트(멀티모듈)?

  • 공통되는 도메인을 사용하는 프로젝트를 하나의 프로젝트로 묶어서 관리하는 것 
  • Gradle은 각 프로젝트가 공통으로 사용되는 클래스를 모듈로 만들어 독립적인 각 프로젝트에서 사용할 수 있도록 한다.
  • 하나의 Repository내에 여러개의 하위 프로젝트를 구성할 수 있다.

ex) 관리자 서버와 사용자 서버를 분리해서 진행해야 될 경우 

하나의 모듈로 하면 많은 코드를 복붙해서 구현해야 하지만, Gradle을 사용하면 중복을 피할 수 있다. 

즉 공통 설정이나 라이브러리를 쉽게 공유하면서도 각 프로젝트를 독립적으로 빌드할 수 있다. 

 

Maven 같은 경우 이를 위해서 여러 POM 파일을 작성해야 하지만, Gradle에서는 하나의 설정 파일에서 여러 

프로젝트를 간단하게 설정할 수 있다. 

 

root 프로젝트: 공통 모듈 멤버를 사용하는 관리자, 일반 회원 프로젝트를 묶는 프로젝트 

공통 모듈: 각 프로젝트에서 사용되는 클래스를 하나의 모듈로 저장 

Gradle은 독립적인 두 프로젝트에서 멤버 모듈을 사용할 수 있도록 해준다. 

 

설정 방법 

Root 프로젝트 설정 

root > settings.gradle 

 

root > build.gradle 

a-project <-> common-module

b-project <-> common-module

각 프로젝트가 common-module을 사용한다는 것을 명시 

빌드 속도가 빠름 

점진적 빌드 (Incremental Builds)

  • Gradle은 빌드 실행 중 마지막 빌드 호출 이후에 task의 입력, 출력 혹은 구현이 변경됐는지 확인 
  • 최신 상태로 간주하지 않는다면 빌드는 실행되지 않는다. 
  • 즉 변경되지 않은 작업은 이전에 실행된 결과를 그대로 재사용함으로써 빌드 시간을 절약한다. 

 

빌드 캐시 (Build Cache)

  • 두 개 이상의 빌드가 돌아가고, 하나의 빌드에서 사용되는 파일들이 다른 빌드들에 사용된다면 Gradle은 빌드 캐시를 이용해 이전 빌드의 결과물을 다른 빌드에서 사용할 수 있다. 
  • 다시 빌드하지 않아도 되므로 빌드 시간이 줄어들게 된다. 
  • 로컬 캐시, 서버 캐시 존재 

 

데몬 프로세스

  • 데몬 프로세스: 서비스의 요청에 응답하기 위해 오래 동안 살아있는 프로세스, 다음 빌드 작업을 위해 백그라운드에서 대기하는 프로세스 
  • 자원 보관: Gradle의 데몬 프로세스는 메모리 상에 빌드 결과물을 보관 이로 인해 빌드 작업이 반복될 때 이전 결과를 재사용할 수 있다. 빌드 결과를 메모리에서 직접 가져올 수 있으므로, 다음 빌드에서 전체 작업을 다시 실행할 필요 없이 빠르게 결과를 제공
  • 지속적인 실행: Gradle 데몬 프로세스는 빌드가 완료된 후에도 종료되지 않고 계속 실행, 이로 인해 다음 빌드 요청이 있을 때 빠르게 처리할 수 있다.
  • 자원 절략: 매번 새로운 프로세스를 시작하고 종료하는 것보다, 하나의 데몬 프로세스를 사용하는 것이 자원 소모가 적다. 

 

비교 대상인 Maven과의 비교 

  • 공식 문서에서 Maven과 속도 차이는 2배에서 최대 100배 차이가 난다고 한다. 

Gradle (build.gradle) 의존성 작성 

의존성, 내부 의존성?

의존성

B가 A를 사용한다 (의존한다.)

 

내부 의존성

C가 B를 의존할 때 B가 의존하는 A를 C가 인지하는 여부 

C는 B에 의존하기 때문에, B가 의존하는 A의 기능을 사용할 수 있다. 

Gradle은 이러한 의존성 전파를 자동으로 관리

 

Gradle 의존성 

  • api: 내부 의존성을 컴파일과 런타임 모두에 보이는 API 의존성 
  • implementation: 내부 의존성을 런타임에서만 보이는 구현 의존성 
  • compileOnly: 컴파일에서만 사용되는 의존성 정의 
  • runtimeOnly: 럼타임에만 사용되는 의존성 정의 
  • test + Implementation, CompileOnly, RuntimeOnly: 해당 의존성을 테스트 시에만 사용하도록 정의 

api vs implementation (의존성 전파)  

api

모듈 c가 모듈 b를 의존하고 모듈 b가 a라는 라이브러리를 api로 선언했을 때 모듈 c는 a 라이브러리를 사용 가능 

 

implementation

모듈 c가 모듈 b를 의존하고 모듈 b가 a라는 라이브러리를 implementation 로 선언했을 때 모듈 c는 a 라이브러리를 사용 불가능 

api vs implementation (빌드 속도)

api

api 의존성은 의존성이 전파되기 때문에, 의존성 체인 전체를 고려하여 빌드가 이루어진다. 이로 인해, 모듈 간의 변경이 발생할 경우, 의존성 전파로 인해 더 많은 모듈이 재빌드될 수 있다. 이로 인해 빌드 시간이 증가할 수 있다.

 

implementation

모듈 간의 변경이 발생하더라도, 해당 변경이 전파되지 않으므로 빌드가 더 빠르다. 변경된 모듈만 빌드되며, 의존성 체인의 다른 모듈은 재빌드되지 않는다.