젠킨스와 스프링 부트를 활용한 지속적 통합 및 배포 구현

젠킨스와 스프링 부트를 이용한 지속적 통합 구현

지속적 통합(Continuous Integration, CI)은 소프트웨어 개발의 프로세스 중 하나로, 개발자들이 작성한 코드를 빌드하고 테스트하는 과정을 자동화하여 개발 생산성을 높이는 방법입니다. 이를 통해 코드 품질을 높이고 오류를 예방할 수 있습니다. 젠킨스(Jenkins)는 대표적인 CI 도구 중 하나입니다. 스프링 부트(Spring Boot)는 스프링(Spring) 프레임워크를 기반으로 한 자바 웹 어플리케이션 개발을 위한 도구로, 빠른 개발과 간편한 배포를 가능하게 합니다. 이번에는 젠킨스와 스프링 부트를 활용하여 지속적 통합을 구현하는 방법에 대해 알아보겠습니다.

젠킨스 설치 및 설정

젠킨스를 사용하기 위해서는 먼저 설치가 필요합니다. 다음과 같은 명령어를 통해 젠킨스를 설치할 수 있습니다.

$ wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
$ sudo sh -c 'echo deb https://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
$ sudo apt-get update
$ sudo apt-get install jenkins

설치가 끝나면 웹 브라우저를 열어 http://localhost:8080으로 접속합니다. 초기 비밀번호를 입력한 후 초기 설정을 마치면 젠킨스 대시보드가 표시됩니다.

스프링 부트 프로젝트 생성

스프링 부트 프로젝트를 생성하기 위해서는 스프링 부트 CLI(Command Line Interface)를 사용할 수 있습니다. 다음과 같은 명령어를 통해 스프링 부트 CLI를 설치합니다.

$ curl https://start.spring.io/starter.zip -d dependencies=web -d baseDir=myproject -o myproject.zip
$ unzip myproject.zip
$ cd myproject

이제 스프링 부트 프로젝트를 생성할 준비가 끝났습니다.

젠킨스와 스프링 부트 연동

젠킨스와 스프링 부트를 연동하려면 먼저 젠킨스 서버에 스프링 부트를 설치해야 합니다. 다음과 같은 명령어를 통해 스프링 부트를 설치합니다.

$ sudo wget https://repo.spring.io/release/org/springframework/boot/spring-boot-cli/2.0.2.RELEASE/spring-boot-cli-2.0.2.RELEASE-bin.tar.gz
$ sudo tar -xvf spring-boot-cli-2.0.2.RELEASE-bin.tar.gz

다음으로 젠킨스에서 스프링 부트를 실행할 수 있도록 설정해야 합니다. 젠킨스 대시보드에서 새로운 Item을 선택하고 프리스타일 프로젝트를 선택합니다. 소스 코드 관리에서는 Git 등의 버전 관리 시스템을 선택하고, 빌드 유발에서는 코드 변경이 발생할 때 자동으로 빌드하도록 설정합니다.

테스트 자동화

젠킨스와 스프링 부트를 연동하면 테스트도 자동으로 실행할 수 있습니다. 스프링 부트에서는 JUnit 등 다양한 테스트 프레임워크를 지원합니다. 다음과 같은 코드를 통해 JUnit을 사용하는 테스트를 작성할 수 있습니다.

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTest {

    @Autowired
    private MyService myService;

    @Test
    public void testMyService() {
        String result = myService.doSomething();
        assertEquals("expected result", result);
    }
}

이제 이 테스트를 실행하려면 build.gradle 파일에 다음과 같은 코드를 추가합니다.

test {
    useJUnitPlatform()
}

빌드 자동화

젠킨스를 사용하면 코드 변경이 발생할 때 자동으로 빌드하도록 설정할 수 있습니다. 빌드를 자동화하기 위해서는 빌드 유발에서 GitHub hook trigger for GITScm polling을 선택합니다. 이제 코드가 변경될 때마다 자동으로 빌드가 실행됩니다.

코드 분석 자동화

젠킨스를 사용하면 코드 분석도 자동으로 실행할 수 있습니다. 다양한 코드 분석 도구 중에서는 SonarQube 등이 있습니다. 다음과 같은 명령어를 통해 SonarQube를 설치합니다.

$ sudo apt-get install openjdk-8-jdk
$ sudo wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.6.zip
$ sudo unzip sonarqube-7.6.zip

SonarQube를 설치한 후 젠킨스와 연동하려면 다음과 같은 플러그인을 설치해야 합니다.

  • SonarQube Scanner for Jenkins
  • SonarQube Scanner

이후 빌드 유발에서 Invoke Standalone SonarQube analysis를 선택합니다.

배포 자동화

젠킨스를 사용하면 코드를 자동으로 배포할 수 있습니다. 다양한 배포 방식 중에서는 Docker 이미지를 사용하는 방법이 있습니다. 다음과 같은 명령어를 통해 Docker를 설치합니다.

$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

이제 Dockerfile을 작성하여 Docker 이미지를 빌드할 수 있습니다.

FROM openjdk:8-jdk-alpine
COPY target/myproject-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

이제 Dockerfile을 빌드하여 Docker 이미지를 생성하고, 이를 배포할 서버에 배포하면 됩니다.

Jenkinsfile 작성

Jenkinsfile은 젠킨스에서 파이프라인을 정의하는 파일입니다. Jenkinsfile을 작성하여 CI/CD를 자동화할 수 있습니다. 다음과 같은 Jenkinsfile을 작성할 수 있습니다.

pipeline {
    environment {
        DOCKER_REGISTRY = "docker.io"
        IMAGE_NAME = "${DOCKER_REGISTRY}/${env.JOB_NAME}:${env.BUILD_NUMBER}"
    }

    agent {
        docker {
            image "maven:3.6.0-jdk-8"
            args "-v /root/.m2:/root/.m2"
        }
    }

    stages {
        stage("Build") {
            steps {
                sh "mvn clean package -DskipTests"
            }
        }

        stage("Test") {
            steps {
                sh "mvn test"
            }
        }

        stage("SonarQube analysis") {
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh "mvn sonar:sonar"
                }
            }
        }

        stage("Docker build") {
            steps {
                script {
                    def dockerImage = docker.build(IMAGE_NAME)
                    dockerImage.push()
                }
            }
        }

        stage("Deploy") {
            when {
                branch "master"
            }

            steps {
                withCredentials([usernamePassword(credentialsId: 'DOCKER_HUB', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
                    sh "docker login -u ${USERNAME} -p ${PASSWORD}"
                    sh "docker push ${IMAGE_NAME}"
                }
            }
        }
    }
}

Jenkins 파이프라인 실행

이제 젠킨스 파이프라인을 실행할 차례입니다. Jenkinsfile을 작성한 후, 새로운 Item에서 파이프라인을 선택합니다. Pipeline script from SCM에서 코드 관리 방식을 선택하고, Repository URL에는 소스 코드가 저장된 Git 저장소의 URL을 입력합니다. 이후 빌드 유발에서 GitHub hook trigger for GITScm polling을 선택하여 코드 변경이 발생할 때마다 자동으로 파이프라인이 실행되도록 설정합니다.

결론

이번에는 젠킨스와 스프링 부트를 활용하여 지속적 통합 및 배포를 구현하는 방법에 대해 알아보았습니다. 젠킨스와 스프링 부트를 함께 사용하면 빠른 개발과 안정적인 배포를 가능하게 할 수 있습니다. 이를 통해 소프트웨어 개발 생산성을 높일 수 있으며, 코드 품질을 높이고 오류를 예방할 수 있습니다.

CI/CD