Jerry's Log

Gradle

contents

Maven이 정해진 규칙(XML)을 엄격히 따르는 "공장 관리자" 라면, Gradle은 코드를 작성해서 무엇이든 지을 수 있는 "스크립트형 건축가" 입니다.

다음은 Gradle의 내부 아키텍처, 생명주기, 그리고 성능의 비밀에 대한 상세 분석입니다.


1. 핵심 철학: "빌드 로직도 코드다"

Maven과 Gradle의 가장 큰 차이점은 사용하는 언어입니다.

예시 (build.gradle):

// 실제로 코드를 짤 수 있습니다!
if (project.hasProperty('production')) {
    apply plugin: 'com.newrelic.agent'
}

task copyDocs(type: Copy) {
    from 'src/main/doc'
    into 'build/target/doc'
}

2. 아키텍처: 빌드 생명주기 (Build Lifecycle)

이것이 가장 중요한 기술적 개념입니다. 위에서 아래로 단순히 실행되는 스크립트와 달리, Gradle은 3단계의 뚜렷한 과정을 거쳐 실행됩니다.

1단계: 초기화 (Initialization)

2단계: 구성 (Configuration) - ⚠️ 위험 구역

3단계: 실행 (Execution)


3. "DAG" (방향성 비순환 그래프)

Gradle은 단순히 태스크 목록을 실행하는 것이 아니라, 그래프를 구축합니다.

gradle build를 실행한다고 가정해 봅시다:

  1. buildcheckassemble에 의존합니다.
  2. checktest에 의존합니다.
  3. testcompileTestJava에 의존합니다.
  4. compileTestJavacompileJava에 의존합니다.

Gradle은 이 트리를 계산합니다. 만약 두 태스크가 서로 독립적이라면(예: 문서 생성과 테스트 컴파일), Gradle은 서로 다른 CPU 코어에서 병렬(Parallel) 로 실행하여 속도를 높입니다.


4. 성능: 왜 Gradle이 더 빠른가?

Gradle은 성능 최적화에 집착합니다. Maven을 이기기 위해 주로 3가지 기술을 사용합니다.

A. 증분 빌드 (Incremental Builds - "Up-to-date")

태스크를 실행하기 전에 Gradle은 두 가지를 확인합니다.

  1. 입력(Inputs): 소스 파일이 변경되었는가? (해시/체크섬 계산)
  2. 출력(Outputs): 목적지 폴더(예: build/classes)가 이미 존재하는가?

만약 입력이 변하지 않았다면, Gradle은 태스크를 UP-TO-DATE로 표시하고 실행을 건너뜁니다.

B. Gradle 데몬 (The Daemon)

JVM을 시작하고 라이브러리를 로딩하는 데는 시간이 걸립니다.

C. 빌드 캐시 (Build Cache)


5. 의존성 관리: api vs implementation

Maven에는 주로 compile 하나만 있지만, Gradle(특히 java-library 플러그인)에는 두 가지 방식이 있습니다. 이는 컴파일 속도에 결정적입니다.

implementation (기본값)

api


6. 래퍼 (The Wrapper - gradlew)

실무 CI/CD 파이프라인에서는 gradle 명령어를 거의 보지 못하고, ./gradlew를 보게 됩니다.


7. 비교표: Maven vs. Gradle

특징 Maven Gradle
언어 XML (선언적). Groovy 또는 Kotlin (명령형).
성능 느림 (보통 clean 빌드 필요). 빠름 (증분 빌드 + 캐시 + 데몬).
유연성 딱딱함 (생명주기 고정). 매우 유연함 (커스텀 로직/태스크).
러닝 커브 낮음 (읽기 쉬움). 높음 (API를 배워야 함).
의존성 범위 compile, provided, test implementation, api, compileOnly, runtimeOnly
주 사용처 전통적인 엔터프라이즈(SI). 안드로이드, 모던 스프링 부트, 빅테크 기업.

개발자를 위한 요약

  1. 전역 설치된 gradle 대신 ./gradlew를 사용하세요.
  2. 오픈소스 라이브러리를 만드는 게 아니라면 api 대신 implementation을 사용하세요.
  3. 생명주기를 이해하세요: 무거운 로직은 build.gradle 최상단이 아니라 doLast { ... } 블록 안에 넣으세요.
  4. Kotlin DSL (build.gradle.kts) 이 미래입니다. Groovy에는 없는 IntelliJ 자동 완성 기능을 제공합니다.

references