참고 자료
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
모듈 간의 변경이 발생하더라도, 해당 변경이 전파되지 않으므로 빌드가 더 빠르다. 변경된 모듈만 빌드되며, 의존성 체인의 다른 모듈은 재빌드되지 않는다.