Jenkins에서 GitLab CI/CD로 Maven 빌드 마이그레이션하기

Jenkins에서 GitLab CI/CD로 Maven 빌드 마이그레이션하기

Jenkins에 Maven 빌드가 있다면 Java Spring 프로젝트 템플릿을 사용해 GitLab으로 마이그레이션할 수 있어요. 이 템플릿은 기본 의존성 관리를 위해 Maven을 사용해요.

출처: 문서

본문

샘플 Jenkins 구성

다음 세 가지 Jenkins 예시는 각각 다른 방법으로 셸 에이전트에 Maven 프로젝트를 테스트·빌드·설치해요:

  • 셸 실행이 있는 Freestyle
  • Maven 태스크 플러그인이 있는 Freestyle
  • Jenkinsfile을 사용하는 선언적 파이프라인 (declarative pipeline)

세 예시 모두 같은 세 명령을 세 단계에서 순서대로 실행해요:

  • mvn test: 코드베이스에서 발견된 테스트 실행.
  • mvn package -DskipTests: POM에 정의된 실행 가능한 유형으로 코드를 컴파일하고, 첫 단계에서 이미 테스트했으므로 테스트 실행은 건너뜀.
  • mvn install -DskipTests: 컴파일된 실행 파일을 에이전트의 로컬 Maven .m2 저장소에 설치하고 다시 테스트 실행을 건너뜀.

이 예시들은 단일 영구 Jenkins 에이전트를 사용하며, 에이전트에 Maven이 사전 설치되어 있어야 해요. 이 실행 방식은 shell executor를 사용하는 GitLab Runner와 비슷해요.

셸 실행이 있는 Freestyle

Jenkins의 내장 셸 실행 옵션을 사용해 에이전트의 셸에서 mvn 명령을 직접 호출한다면 구성은 다음과 같을 수 있어요:

Jenkins UI that shows build steps with Maven commands defined as shell commands.

Maven 태스크 플러그인이 있는 Freestyle

Jenkins의 Maven 플러그인을 사용해 Maven 빌드 수명주기에서 특정 goal을 선언·실행한다면 구성은 다음과 같을 수 있어요:

Jenkins UI that shows build steps with Maven commands defined using the Maven plugin.

이 플러그인은 Jenkins 에이전트에 Maven이 설치되어 있어야 하고, Maven 명령을 호출하기 위한 스크립트 래퍼를 사용해요.

선언적 파이프라인 사용

선언적 파이프라인을 사용한다면 구성은 다음과 같을 수 있어요:

pipeline {
    agent any
    tools {
        maven 'maven-3.6.3'
        jdk 'jdk11'
    }
    stages {
        stage('Build') {
            steps {
                sh "mvn package -DskipTests"
            }
        }
        stage('Test') {
            steps {
                sh "mvn test"
            }
        }
        stage('Install') {
            steps {
                sh "mvn install -DskipTests"
            }
        }
    }
}

이 예시는 플러그인 대신 셸 실행 명령을 사용해요.

기본적으로 선언적 파이프라인 구성은 Jenkins 파이프라인 구성이나 Git 저장소의 Jenkinsfile에 저장돼요.

Jenkins 구성을 GitLab CI/CD로 변환하기

이전 예시들이 모두 조금씩 다르지만, 모두 같은 파이프라인 구성으로 GitLab CI/CD로 마이그레이션할 수 있어요.

전제 조건:

  • Shell executor가 있는 GitLab Runner
  • 셸 러너에 Maven 3.6.3과 Java 11 JDK 설치됨

이 예시는 Jenkins에서 빌드·테스트·설치하는 동작과 구문을 흉내 냅니다.

GitLab CI/CD 파이프라인에서는 명령이 "잡(job)"에서 실행되며, 잡은 스테이지로 묶여요. .gitlab-ci.yml 설정 파일의 마이그레이션된 구성은 두 개의 전역 키워드(stagesvariables) 뒤에 3개의 잡으로 이루어져요:

stages:
  - build
  - test
  - install

variables:
  MAVEN_OPTS: >-
    -Dhttps.protocols=TLSv1.2
    -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository
  MAVEN_CLI_OPTS: >-
    -DskipTests

build-JAR:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS package

test-code:
  stage: test
  script:
    - mvn test

install-JAR:
  stage: install
  script:
    - mvn $MAVEN_CLI_OPTS install

이 예시에서:

  • stages는 순서대로 실행되는 세 개의 스테이지를 정의해요. 이전 Jenkins 예시와 마찬가지로 test 잡이 먼저 실행되고, 그다음 build 잡, 마지막으로 install 잡이 실행돼요.
  • variables는 모든 잡이 사용할 수 있는 CI/CD 변수를 정의해요:MAVEN_OPTS는 Maven이 실행될 때마다 필요한 Maven 환경 변수예요:-Dhttps.protocols=TLSv1.2는 파이프라인의 모든 HTTP 요청에 대해 TLS 프로토콜을 1.2 버전으로 설정해요.-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository는 로컬 Maven 저장소 위치를 러너의 GitLab 프로젝트 디렉터리로 설정해서, 잡이 저장소에 접근하고 수정할 수 있게 해요.MAVEN_CLI_OPTSmvn 명령에 추가할 특정 인자예요:-DskipTests는 Maven 빌드 수명주기에서 test 스테이지를 건너뜀.
  • test-code, build-JAR, install-JAR은 파이프라인에서 실행할 잡의 사용자 정의 이름이에요:stage는 잡이 실행되는 스테이지를 정의해요. 파이프라인에는 하나 이상의 스테이지가 있고, 스테이지에는 하나 이상의 잡이 있어요. 이 예시에는 각각 잡이 하나씩 있는 세 스테이지가 있어요.script는 그 잡에서 실행할 명령을 정의해요. Jenkinsfilesteps와 비슷해요. 잡은 이미지 컨테이너에서 실행되는 여러 명령을 순차적으로 실행할 수 있지만, 이 예시의 잡들은 각각 명령 하나만 실행해요.

Docker 컨테이너에서 잡 실행하기

Jenkins 샘플처럼 영구 머신으로 이 빌드 과정을 처리하는 대신, 이 예시는 임시(ephemeral) Docker 컨테이너를 사용해 실행을 처리해요. 컨테이너를 사용하면 가상 머신과 그 위에 설치된 Maven 버전을 유지 관리할 필요가 없어져요. 또한 파이프라인 기능을 확장하는 유연성도 높아져요.

전제 조건:

  • 프로젝트가 사용할 수 있는 Docker executor가 있는 GitLab Runner. GitLab.com을 사용한다면 공용 인스턴스 러너를 사용할 수 있어요.

이 마이그레이션된 파이프라인 구성은 세 개의 전역 키워드(stages, default, variables) 뒤에 3개의 잡으로 이루어져요. 이 구성은 이전 예시보다 개선된 파이프라인을 위해 추가 GitLab CI/CD 기능을 활용해요:

stages:
  - build
  - test
  - install

default:
  image: maven:3.6.3-openjdk-11
  cache:
    key: $CI_COMMIT_REF_SLUG
    paths:
      - .m2/

variables:
  MAVEN_OPTS: >-
    -Dhttps.protocols=TLSv1.2
    -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository
  MAVEN_CLI_OPTS: >-
    -DskipTests

build-JAR:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS package

test-code:
  stage: test
  script:
    - mvn test

install-JAR:
  stage: install
  script:
    - mvn $MAVEN_CLI_OPTS install

이 예시에서:

  • stages는 순서대로 실행되는 세 개의 스테이지를 정의해요. 이전 Jenkins 예시와 마찬가지로 test 잡이 먼저 실행되고, 그다음 build 잡, 마지막으로 install 잡이 실행돼요.
  • default는 모든 잡에서 기본적으로 재사용할 표준 구성을 정의해요:image는 명령을 실행할 Docker 이미지 컨테이너를 정의해요. 이 예시에서는 필요한 모든 것이 설치된 공식 Maven Docker 이미지예요.cache는 의존성을 캐시하고 재사용하는 데 사용돼요:key는 특정 캐시 아카이브의 고유 식별자예요. 이 예시에서는 사전 정의 CI/CD 변수로 자동 생성된 Git 커밋 ref의 축약 버전이에요. 같은 커밋 ref로 실행되는 모든 잡은 같은 캐시를 재사용해요.paths는 캐시에 포함할 디렉터리나 파일이에요. 이 예시는 .m2/ 디렉터리를 캐시해서 잡 실행 사이에 의존성을 다시 설치하지 않게 해요.
  • variables는 모든 잡이 사용할 수 있는 CI/CD 변수를 정의해요:MAVEN_OPTS는 Maven이 실행될 때마다 필요한 Maven 환경 변수예요:-Dhttps.protocols=TLSv1.2는 파이프라인의 모든 HTTP 요청에 대해 TLS 프로토콜을 1.2 버전으로 설정해요.-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository는 로컬 Maven 저장소 위치를 러너의 GitLab 프로젝트 디렉터리로 설정해서, 잡이 저장소에 접근하고 수정할 수 있게 해요.MAVEN_CLI_OPTSmvn 명령에 추가할 특정 인자예요:-DskipTests는 Maven 빌드 수명주기에서 test 스테이지를 건너뜀.
  • test-code, build-JAR, install-JAR은 파이프라인에서 실행할 잡의 사용자 정의 이름이에요:stage는 잡이 실행되는 스테이지를 정의해요. 파이프라인에는 하나 이상의 스테이지가 있고, 스테이지에는 하나 이상의 잡이 있어요. 이 예시에는 각각 잡이 하나씩 있는 세 스테이지가 있어요.script는 그 잡에서 실행할 명령을 정의해요. Jenkinsfilesteps와 비슷해요. 잡은 이미지 컨테이너에서 실행되는 여러 명령을 순차적으로 실행할 수 있지만, 이 예시의 잡들은 각각 명령 하나만 실행해요.

더 알아보기

다음으로는 GitLab CI/CD 시작 가이드CI/CD YAML 문법 참조 문서를 읽으면, Maven 말고도 다양한 빌드 도구를 GitLab 파이프라인으로 옮기는 방법을 익힐 수 있어요. 캐시와 변수 구성도 함께 보면 빌드 속도를 개선할 수 있어요.