Gradle1️⃣ 기본용어2️⃣ Gradle ??3️⃣ Gradle의 구성요소🤔 Gradle Wrapper?4️⃣ build.gradle??build.gradleapiimplementation5️⃣ 적용범위api, compile의 라이브러리 적용 범위implementation의 적용 범위결론 - api는 쓰지 말고 implementation을 쓰자6️⃣ Gradle Dependency ConfigurationscompileClasspathruntimeClasspathcompileOnlyruntimeOnly7️⃣ REF
Gradle
1️⃣ 기본용어
- Project : 소스를 jar 형태로 모으거나, 자바 프로젝트를 compile, 테스트 실행, 애플리케이션 deploy 등의 업무로 구성
- Task : 작업의 최소 단위
- Compile : 소스 코드를 컴퓨터가 이해할 수 있는 기계어로 변환하는 과정
- Build : 소스코드를 실행 가능한 SW 결과물로 만드는 일련의 과정(Compile 과정을 포함한다.)
2️⃣ Gradle ??
- Groovy 기반의 오픈소스 자동화 툴이다.
- Groovy : JVM에서 실행되는 스크립트 언어로 문법이 자바와 매우 유사하고 호환이 되며 Java 클래스 파일을 그대로 Groovy 클래스로 사용할 수 있다.
- Ant → Maven → Gradle 순으로 발달되어 왔다.
- xml의 구조적 틀을 벗어나 코딩에 의한 간결한 정의가 가능하다.
- 프로젝트를 설정 주입 방식으로 정의 → Maven의 상속 구조보다 재사용에 용이하다.
- 간결함, 속도, 유연성, 확장성, 공식 홈페이지에 문서화가 많은 것이 장점
3️⃣ Gradle의 구성요소
- gradlew : Unix용 실행 스크립트
- gradlew.bat : Window용 실행 스크립트
- gradlew-wrapper.jar : Wrapper 파일
- gradle-wrapper.properties : Gradle Wrapper 설정 파일
- build.gradle : 의존성이나 플로그인 설정 등을 위한 스크립트 파일
- settings.gradle : 프로젝트 구성 정보 기록
🤔 Gradle Wrapper?
- 사용자가 Gradle을 설치하지 않았어도 Gradle tasks를 실행할 수 있도록 돕는다.
- 프로젝트 생성자와 사용자가 동일한 버전의 Gradle을 사용할 수 있다.
4️⃣ build.gradle??

build.gradle
- api, implementation 모두 라이브러리를 적용시키는 키워드다.
- 오래된 gradle 버전에서는 implementation이 없어서 compile을 사용했고, 새로운 버전(6.x 이후)에서 compile이 deprecated 되면서 compile 대신에 api 키워드가 사용되게 되었다.
- 이 때문에 오래된 프로젝트들의 build.gradle 파일들을 보면 api와 compile을 implementation대신 쓰는 모습을 확인할 수 있다.
- 즉 api와 compile 모두 같은 역할을 한다. 하지만 Gradle은 api나 compile을 사용하는 것을 권장하지는 않는다.
- api를 통해 라이브러리를 가져올 경우 라이브러리가 적용되는 범위 때문이다.
api
- 프로젝트에 의해 노출되는 API의 일부인 프로젝트 소스를 컴파일하는데 필요한 종속성
implementation
- 프로젝트에 의해 노출되는 API의 일부가 아닌 프로젝트 소스를 컴파일하는데 필요한 종속성
5️⃣ 적용범위
api, compile의 라이브러리 적용 범위
- 모듈에서 api 나 compile 을 사용해 라이브러리를 가져오게 되면, 해당 라이브러리는 해당 모듈을 의존하는 모듈에도 가져와진다.
- 예를 들어, 모듈A에서 api를 사용해 라이브러리를 가져온 다음 모듈B에서 api를 통해 모듈A를 가져올 경우 라이브러리도 같이 가져와진다.

- 이것은 프로그램 유지보수성 측면에서 매우 좋지 않다. 모듈을 사용할 때는 모듈의 인터페이스만이 외부에 노출되어야 하는데 라이브러리의 인터페이스까지 같이 노출되기 때문이다.
- 또한 Leak이 일어나는데, 모듈A를 빌드하면서 이미 들어간 라이브러리가 중복으로 모듈B에도 추가되기 때문이다. (라이브러리도 패키징된 모듈이다.)
- 특히 클린아키텍처적인 측면에서 Entity 모듈은 비즈니스 로직을 만드는 애플리케이션의 Usecase 모듈에서만 사용되고, Usecase 모듈은 Controller 모듈에서만 사용되는 구조로 이루어져 있어 각 레이어별로 분리가 확실하게 일어나는데, 만약 Controller에서 Entity 모듈을 알게 된다면 모듈 계층을 건너뛴 참조가 일어날 수 있게 되어 레이어를 나눈 의미가 없어지게 된다.
- 따라서 이를 해결하기 위해 한 모듈에서 사용하는 라이브러리는 그 모듈에서만 사용될 수 잇도록 implemetation을 써야한다.
implementation의 적용 범위
- 모듈에서 implementation을 사용해 가져오는 라이브러리는 해당 모듈을 의존하는 모듈에는 가져와지지 않는다.
- 모듈A에서 implementation을 이용해 라이브러리를 가져온 다음 모듈B에서 implementation을 사용해 모듈A를 가져오면 라이브러리는 가져와지지 않는다. (라이브러리는 모듈A에 캡슐화되어 모듈B에 노출되지 않는다.)

- 이 방식을 이용하면 모듈 수준에서 공개되는 코드를 모듈의 인터페이스로 제한할 수 있어 모듈간 의존성을 줄이게 된다.
- 위의 그림1에서는 모듈 B가 모든 라이브러리에 의존했지만 그림2에서는 모듈B가 모듈A만 의존하는 모습을 볼 수 있다.
- 프로그래밍 유지보수의 핵심은 모듈간 의존성을 줄이는 것이 1순위다. 수많은 라이브러리(모듈)들이 범람하고, 하나의 프로그램에 코드가 수십만줄이 넘어가는 현대에는 모듈간 의존성을 줄여야 프로그램을 유지보수하기 편해진다.

결론 - api는 쓰지 말고 implementation을 쓰자
6️⃣ Gradle Dependency Configurations
compileClasspath
- 컴파일 시에 필요한 class path를 뜻한다.
runtimeClasspath
- 런타임 시에 필요한 class path를 뜻한다.
- 보통, compile하면 compile path에도 있고 runtime path에도 있다.

compileOnly
- 컴파일 시에만 필요하고 런타임에는 불필요한 경우
- 컴파일 할때는 종속성을 사용하고 build 결과물에는 넣지 않는 경우
- Advantage? build 결과물의 크기가 작아진다는 장점이 있다.
- compileClassPath에만 dependency를 두는 것
- Lombok → 컴파일 시에 lombok annotation을 보고 getter/setter 등을 만들어주고 런타임에는 사용하지 않는다.

runtimeOnly
- 컴파일 시에는 불필요하고, 런타임 시에만 필요한 경우
- Advantage? 컴파일 시간이 빨라진다. → 컴파일 할때는 사용하지 않기 때문이다.
- runtimeClassPath에만 dependency를 두는 것
- JDBC 관련 → h2, mysql
- log 관련 → log4j
