Gradle이란?
- Gradle은 Groovy를 기반으로 한 오픈소스 빌드 도구입니다.
- 변수 선언, if, else, for 로직 구현이 가능합니다.
- Groovy를 이용한 빌드 자동화 시스템이며 Groovy와 유사한 도메인 언어를 채용했습니다.
- Java, C/C++, 파이썬 등 여러가지 언어를 지원합니다.
- 멀티 프로젝트 빌드를 지원합니다.
- 의존성 관리의 다양한 방법을 제공합니다.
- xml 형식이 아닌 간결한 정의가 가능합니다.
- 성능 향상을 위한 증분 빌드, 작업 결과 캐싱, 증분 하위 작업, 데몬 프로세스 재사용, 병렬 실행, 병렬 다운로드 등의 기능을 지원합니다.
- GradleWrapper를 제공합니다.
- GradleWrapper는 Gradle을 설치하지 않아도 Gradle버전, Java 버전을 신경 쓸 필요 없이 바로 사용할 수 있도록 해줍니다.
설정파일
setting.gradle
프로젝트 구성을 설정합니다. 멀티 프로젝트를 구성해 프로젝트간 의존성 및 서브프로젝트, 교차 프로젝트를 구성할 수 있습니다.
build.gradle
빌드에 대한 모든 기능을 정의합니다.
Task란?
Gradle의 Task는 작업의 최소 단위입니다. Task는 기본 내장 Task와 사용자 정의 Task 두 종류가 존재합니다.
init, build, run ,clean 등등 모두 내장 Task 입니다.

gradle tasks 또는 ./gradlew tasks로도 확인가능합니다.

Plugin이란?
Plugin이란 Gradle Task들의 집합입니다 플러그인은 특정 작업을 하기위해 Task의 묶음을 사용합니다.
개발 시 필요한 작업들을 일일이 작성을 하면 번거롭기 때문에 플러그인 단위로 Task의 묶음을 묶어 제공할 수 있습니다.
아래와 같이 flyway 플러그인을 추가하면 flyway의 Task 목록이 추가되는 것을 볼 수 있습니다.


Gradle Dependency Configurations

compileOnly
- 컴파일 시점에만 사용하고 런타임 시에는 불필요한 경우 사용합니다.
- ex) Lombok같은 경우에는 컴파일 시에 코드만 추가해주고 런타임 시에는 사용되지 않습니다.
- 컴파일 할 때만 사용하고 build 결과물에는 추가되지 않습니다. 컴파일 시에만 필요하다면 compileOnly를 사용해 build 결과물에 추가하지 않아 크기를 줄일 수 있습니다.
- compileClassPath에만 추가됩니다.
runtimeOnly
- 컴파일 시에는 불필요하고, 런타임 시에만 필요한 경우에 사용합니다.
- 컴파일 시에 사용하지 않기 때문에 빌드 시간이 빨라집니다.
- runtimeClassPath에만 추가 됩니다.
implementation
- A→B→C의 의존 관계가 있을 때, C가 변경되면 B만 다시 컴파일되면 됩니다.
- A의 compileClassPath C가 포함되지 않습니다.

api(compile)
- compile은 deprecated 됐습니다.
- 사용이 권장되지 않는 옵션입니다. (의존성이 불필요하게 늘어납니다)
- A→B→C의 의존관계가 있을 때 A가 B,C를 갖게 됩니다. A에서 C를 직접적으로 접근이 가능한 것 입니다.
따라서 A의 compileClassPath에 C가 포함되고 C가 변경되면 A도 다시 컴파일 됩니다.

이 외 testCompileOnly, testImplementation, testRuntimeOnly도 있습니다.
api와 implementation의 용도 차이에 대해 잘 설명해주는 다음 예시가 있습니다
// The following types can appear anywhere in the code // but say nothing about API or implementation usage import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; public class HttpClientWrapper { private final HttpClient client; // private member: implementation details // HttpClient is used as a parameter of a public method // so "leaks" into the public API of this component public HttpClientWrapper(HttpClient client) { this.client = client; } // public methods belongs to your API public byte[] doRawGet(String url) { HttpGet request = new HttpGet(url); try { HttpEntity entity = doGet(request); ByteArrayOutputStream baos = new ByteArrayOutputStream(); entity.writeTo(baos); return baos.toByteArray(); } catch (Exception e) { ExceptionUtils.rethrow(e); // *this dependency is internal only* } finally { request.releaseConnection(); } return null; } // HttpGet and HttpEntity are used in a private method, so they don't belong to the API private HttpEntity doGet(HttpGet get) throws Exception { HttpResponse response = client.execute(get); if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { System.err.println("Method failed: " + response.getStatusLine()); } return response.getEntity(); } }
HttpClientWrapper는 HttpClient를 의존하고 있습니다. 그리고 이것을 생성자를 통해서 노출시키고 있습니다.
그러므로 HttpClientWrapper는 HttpClient의 의존성을 가지고 와야하므로 api 옵션을 사용합니다.
반면에 ExceptionUtils는 메서드 본문에서만 사용되므로 HttpClientWrapper에게 전적으로 맡길 수 있어 implementation을 사용할 수 있습니다.
build.gradle dependencies { api 'org.apache.httpcomponents:httpclient:4.5.7' implementation 'org.apache.commons:commons-lang3:3.5' }