Gradle과 CI/CD

양성준·2025년 3월 10일

스프링

목록 보기
9/49

Gradle

  • 자바 기반 애플리케이션 빌드를 자동화하기 위한 도구
  • Gradle의 기능으로 CI/CD가 가능해진다.
    (Gradle은 빌드 자동화 도구이므로, CI/CD 파이프라인에서 코드를 빌드, 테스트, 패키징, 배포하는 과정에 사용됨)
  • 의존성 관리를 위한 다양한 방법을 제공
  • 빌드 스크립트를 XML 언어가 아닌 JVM에서 동작하는 스크립트 언어 ‘그루비’ 기반의 DSL(Domain Specific Language)를 사용

Gradle의 주요 역할

  1. 프로젝트 빌드/컴파일
    : 소스 코드를 컴파일하고, 필요한 라이브러리를 종합해 JAR, WAR 등으로 패키징
  2. 의존성 관리
    : Maven Central이나 사내 저장소에서 라이브러리를 다운로드하고 캐시 / 라이브러리를 자동으로 관리해줌
  3. 테스트 및 품질검사
    : JUnit, TestNG 등 다양한 테스트 프레임워크를 실행하는 task를 제공
  4. 다양한 확장성과 플러그인
    : Spring Boot, Kotilin, Java 등 수많은 플러그인을 통해 기능을 손쉽게 확장 가능
  5. CI/CD 파이프라인 통합
    : Jenkins, GitHub Actions 등 어디에서든 gradlew 스크립트를 이용해 동일한 빌드 환경을 재현 가능

Gradle Wrapper

  • Gradle 버전을 자동으로 관리해주는 스크립트
  • CI/CD 환경에서도 gradlw(mac)/gradlew.bat(windows) 를 통해 동일한 Gradle 버전을 사용할 수 있음
    -> 지정된 Gradle 버전이 자동으로 다운로드 및 실행
  • 관리하는 버전 정보는 gradle/wrapper/gradle-wrapper.properties 파일에 명시됨
  • 빌드/테스트 실행:
    • 리눅스/맥: ./gradlew build
    • 윈도우: gradlew.bat build
  • Wrapper 재생성:
    • gradle wrapper --gradle-version <원하는_gradle_버전>
    • 예: gradle wrapper --gradle-version 7.6.1
      이렇게 하면, 팀원 모두가 동일한 Gradle 버전을 사용하여 빌드 환경이 달라서 생기는 문제를 예방할 수 있다.

settings.gradle

: 프로젝트 이름을 설정, 멀티 프로젝트 구성 시 프로젝트를 포함할 수 있다.

rootProject.name = 'spring-boot-gradle-example'

build.gradle

: Gradle 빌드 스크립트로, 플러그인 / 의존성 / 테스크 등을 지정 가능

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.5'
    id 'io.spring.dependency-management' version '1.0.13.RELEASE'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}
  • plugins: 프로젝트에 필요한 플러그인을 선언. (Java, Spring Boot, Dependency Management 등)
  • repositories: 의존성을 가져올 저장소 지정 (Maven Central 등).
  • dependencies: 필요한 라이브러리 의존성 선언.
  • tasks.named('test'): 테스트 시 JUnit Platform을 사용하도록 설정.

Gradle plugin

  • 라이브러리는 자바 코드를 실행시키기 위함 <-> 플러그인은 Gradle 빌드 로직을 확장하기 위해 사용
  • 각 플러그인은 고유의 task, 설정을 제공해 빌드 스클비트를 모듈화하고 유지보수를 용이하게 해줌
  1. Java Plugin
    • id 'java': 자바 프로젝트에 필수적인 태스크(compileJava, test, jar 등)를 제공한다.
    • 예: build.gradleplugins { id 'java' }
  2. Spring Boot Plugin
    • id 'org.springframework.boot': Spring Boot 애플리케이션을 실행하고 패키징하는 데 필요한 태스크(bootRun, bootJar 등)를 제공한다.
    • 실행 가능한 JAR(일명 “fat jar”)을 손쉽게 생성할 수 있다.
  3. Dependency Management Plugin
    • id 'io.spring.dependency-management': Spring Boot에서 사용하는 BOM(Bill of Materials) 기반의 의존성 버전을 일관되게 관리한다.
    • Gradle에서도 Maven의 <dependencyManagement>와 유사한 기능을 사용할 수 있게 해준다.
    • 해당 플러그인을 사용하면, dependency에 버전을 명시해주지 않아도, 알맞은 버전으로 들어감

의존성 관리

: Gradle은 여러 스코프로 의존성을 관리함

  • implementation: 런타임・컴파일 시 필요한 의존성
  • compileOnly: 컴파일 시에만 필요(런타임에는 필요 없음)
  • runtimeOnly: 런타임에서만 필요한 의존성
  • testImplementation: 테스트용 라이브러리
  • testRuntimeOnly: 테스트 실행 시에만 필요한 라이브러리
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok:1.18.26'
    annotationProcessor 'org.projectlombok:lombok:1.18.26'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
}

ex) Lombok은 런타임 시에 필요하지 않으므로 compileOnly와 annotationProcessor를 통해 컴파일 시에만 적용하도록 설정한다.
=> 특정 annotation을 보고 해당 기능을 만들어줌 (예시 @Getter @Setter)

Gradle 태스크

: Gradle 빌드는 여러 태스크로 구성됨. 각 태스크는 특정 작업을 수행한다.

  • build: 컴파일, 테스트를 수행하고 최종 산출물을 생성한다.
  • bootRun: Spring Boot 애플리케이션을 실행한다. (Spring Boot Plugin 제공)
  • bootJar: 실행 가능한 JAR(fat jar) 생성. (Spring Boot Plugin 제공)
  • test: 테스트 코드를 실행한다.

Gradle 구성(Configurations)과 의존성 분류

  • Configuration은 의존성을 묶어서 관리하는 컨테이너 역할이다.
  • 기본적으로 implementation, testImplementation 등이 제공되지만, 필요하다면 사용자 정의 Configuration을 만들 수도 있다.
configurations {
    customConfig
}

dependencies {
    customConfig 'org.example:some-library:1.0'
}
  • customConfig라는 Configuration을 정의해 특정 라이브러리를 별도로 관리할 수 있다.
  • 이처럼 다양한 상황에 맞춰 의존성을 구분하면, 빌드 과정에서 충돌을 방지하고 관리가 용이해진다.

멀티 모듈(Multi-project) 빌드

  • 대규모 애플리케이션을 여러 모듈(서브프로젝트)로 나누어 구조를 관리하는 방식이다.
  • 루트 프로젝트(settings.gradle)에서 어떤 모듈을 포함할지 선언하고, 각 모듈마다 build.gradle을 별도로 작성한다.
root
 ┣ settings.gradle
 ┣ build.gradle
 ┣ moduleA
 ┃  ┗ build.gradle
 ┗ moduleB
    ┗ build.gradle

settings.gradle:

rootProject.name = 'multi-module-project'
include 'moduleA', 'moduleB'

루트 build.gradle:

plugins {
    id 'java'
}

subprojects {
    apply plugin: 'java'

    repositories {
        mavenCentral()
    }
}
  • 모듈별로 moduleA/build.gradle, moduleB/build.gradle 내에서 의존성을 선언한다.
  • 모듈 간 의존 관계를 명시해 계층 구조를 명확히 할 수 있다.

Gradle 빌드 프로필/환경별 분기

  • Spring Boot에서는 application-dev.yml, application-prod.yml 등 프로필별 설정을 이용하지만, Gradle에서도 빌드 시점에 프로젝트 속성(Project property)이나 시스템 프로퍼티 등을 활용해 환경을 분기할 수 있다.
  • Gradle 자체적으로는 커맨드라인에서 Pprofile=dev처럼 프로젝트 속성(Project property)을 넘겨주거나, 시스템 프로퍼티 등을 통해 분기할 수 있다.
if (project.hasProperty('devProfile')) {
    dependencies {
        implementation 'com.h2database:h2'
    }
} else {
    dependencies {
        runtimeOnly 'com.mysql:mysql-connector-j'
    }
}
  • ./gradlew build -PdevProfile로 실행하면 H2 의존성을 사용한다.
  • 배포 시에는 이 옵션을 생략해 실제 DB(MySQL 등)를 사용하는 식으로 구분할 수 있다.

Gradle 캐시(Cache) & 성능 최적화

  • Gradle 캐시를 이용하면 빌드 결과물을 재사용하여 빌드 시간을 단축할 수 있다.
  • CI/CD 환경에서 -build-cache, -scan 옵션을 자주 활용하며, Gradle Enterprise를 도입하면 빌드 스캔과 캐시 공유가 가능하다.

CI/CD

: 지속적인 통합 / 지속적인 배포
Gradle을 활용하면 CI/CD(Continuous Integration / Continuous Deployment) 파이프라인에서 다음과 같은 작업을 자동화할 수 있다.

GitHub Actions + Gradle

name: CI/CD with Gradle

on:
  push:
    branches:
      - main  # main 브랜치에 푸시될 때 실행
  pull_request:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Set up JDK
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'

      - name: Grant execute permission for Gradle
        run: chmod +x gradlew

      - name: Build with Gradle
        run: ./gradlew build  # ✅ Gradle 빌드 실행

      - name: Run tests
        run: ./gradlew test  # ✅ Gradle 테스트 실행

      - name: Publish artifact
        uses: actions/upload-artifact@v3
        with:
          name: application
          path: build/libs/*.jar  # ✅ 빌드된 JAR 파일 저장

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to server
        run: echo "Deploying application..."  # 실제 배포 스크립트 실행 가능

📌 CI/CD 흐름

  • 코드 변경 감지 → GitHub Actions가 main 브랜치의 푸시를 감지
  • Gradle 빌드 실행 (./gradlew build)
  • 테스트 자동화 실행 (./gradlew test)
  • 빌드된 JAR 파일 저장 (build/libs/*.jar)
  • 서버 배포 단계 (배포 스크립트 실행 가능)

Jenkins + Gradle

pipeline {
    agent any

    stages {
        stage('Checkout') {
            steps {
                git 'https://github.com/example/repository.git'
            }
        }

        stage('Build') {
            steps {
                sh './gradlew clean build'
            }
        }

        stage('Test') {
            steps {
                sh './gradlew test'
            }
        }

        stage('Deploy') {
            steps {
                sh './deploy.sh'  // ✅ 배포 스크립트 실행
            }
        }
    }
}

📌 Jenkins CI/CD 흐름

  • Git 리포지토리에서 코드 가져오기 (git clone)
  • Gradle 빌드 실행 (./gradlew clean build)
  • 테스트 실행 (./gradlew test)
  • 배포 실행 (deploy.sh)

Gradle을 활용한 배포 자동화 (Docker + Gradle)

  • Gradle을 사용하여 Docker 컨테이너를 자동으로 빌드 가능!
  • Gradle에서 Dockerfile을 빌드하여 컨테이너로 배포할 수 있다.
plugins {
    id 'com.palantir.docker' version '0.30.0'
}

docker {
    name 'my-app:latest'
    files 'build/libs/app.jar'
    buildArgs(['JAR_FILE': 'app.jar'])
}
gradle docker  # ✅ Docker 이미지 빌드 실행

깃에 올릴 때, .gradle 파일이나 이미 빌드된 파일인 .build만 ignore 해주면 되고,
├── gradlew
├── gradlew.bat
└── gradle
└── wrapper
└── gradle-wrapper.properties
해당 파일들은 다 올라가야 남들이 열어볼 수 있고, CI/CD도 가능!

참고 - https://madplay.github.io/post/what-is-gradle

profile
백엔드 개발자를 꿈꿉니다.

0개의 댓글