웹 파이프라인/Jenkins

CI 파이프라인 - 빌드 에이전트 개선, 단위테스트, 테스트커버리지, 코드 규약 준수 분석(정적 검사), 빌드 자동화

thinktank911 2025. 12. 16. 22:46

CI 파이프라인

파이프라인에 대한 추상적 정의

  • 새로 개발한 응용을 k8s에서 사용하는 과정을 그림으로 나타내기

상세 수준 정의

  • 젠킨스를 통해 자동화한 빌드 단계와 그 절차

간단한 파이프라인 구축 실습

  • 예제 응용
    • 두 수가 주어지면 이에 대한 덧셈 연산을 행하는 것을 웹 응용(스프링부트) 만들어서 이용
    • 입력은 query string으로, 출력은 그냥 날것의 텍스트로
  • 실습 단계
    • github에 code repository를 생성, 설정하고 초기 소스 코드를 등록
    • gradle 이용한 빌드 환경을 설정 (JDK 필요)
    • 응용에 알맞은 빌드 환경을 컨테이너 이미지로 제작하고 이것을 jenkins agent에 포함
  • 다음 단계
    • 파이프라인에 단위 테스트 단계 추가, 테스트 리포트 발행(Jenkins로 자동화)

Stage View 플러그인 설치

 

빌드 에이전트의 개선

  • 커스텀 에이전트 컨테이너 만들어 적용
    • 빌드에 필요한 환경 미리 구축
    • 어느 Jenkins CI 환경에 적용해도 동일한 환경 적용
    • 이후 복잡한 여러 단계를 거치는 빌드 과정에 대응하는 데에도 유리
  • 에이전트 컨테이너 준비 과정
    • Dockerfile 작성
    • docker build && push
    • 위에서 레지스트리에 등록한 이미지 적용


실습

  • 간단한 웹 응용 만들어 서버를 도커 이미지로 구성
    • 코딩
    • 서버 환경 구성
      • 필요한 패키지는 컨테이너 안에 apt-get 등으로 설치해보면 테스트
    • 이미지 만들기
      • 위 패키지 구성, 코드 배치(ADD 하거나 tar 옮겨 풀너ㅏ, git pull 하거나)
        설정 파일 구성 등을 Dockerfile에 작성하고 docker build 해서 만들어 docker run 테스트
    • 레지스트리에 게시
      • 태그 붙이고 docker push
  • 이 과정에서 코드 변경 일어나면 어떤 일들이 자동으로 실행되어야 할지 생각

 

[처음 파이프라인 스트립트]

pipeline {
    agent {
        kubernetes {
            yaml '''
            apiVersion: v1
            kind: Pod
            spec:
                containers:
                - name: jnlp
                  image: jenkins/inbound-agent
            '''
        }
    }
    tools {
        jdk 'default-jdk'
    }
    stages {
        stage("Checkout") {
            steps {
                git url: 'git@github.com:7saval/calculator.git',
                branch: 'main',
                credentialsId: 'github-credentials'
            }
        }
        stage("Compile"){
            steps{
                sh '''
                    chmod +x gradlew
                    ./gradlew compileJava
                '''
            }
        }
    }
}

 

[빌드 에이전트 개선 후 파이프라인 스크립트]

  • 커스텀 에이전트 구성
  • 빌드 에이전트 설정
    pipeline {
      agent {
          kubernetes {
              yaml '''
              apiVersion: v1
              kind: Pod
              spec:
                  containers:
                  - name: builder
                    image: geniusyoung/jenkins-agent-jdk-17
                    command:
                    - cat
                    tty: true
              '''
          }
      }
      tools {
          jdk 'default-jdk'
      }
      stages {
          stage("Checkout") {
              steps {
                  git url: 'git@github.com:7saval/calculator.git',
                  branch: 'main',
                  credentialsId: 'github-credentials'
              }
          }
          stage("Compile"){
              steps{
                  script {
                      container('builder'){
                          sh '''
                              chmod +x gradlew
                              ./gradlew compileJava
                          '''
                      }
                  }
              }
          }
      }
    }

 

CI 파이프라인 - 단위테스트

코드구현

  • 웹 서비스 컨트롤러 - 이 비즈니스 로직 이용해 웹 인터페이스 통하여 접근 가능하도록 코드 구성

테스트 케이스 구현

  • JUnit 테스트 프레임워크 라이브러리 이용
  • 로컬 환경에서 테스트 확인 - 테스트는 실패가 성공보다 더 필요

단위 테스트의 자동화 및 결과 보고서 생성

  • 파이프라인 스테이지 추가 - 테스트 포함한 CI 파이프라인
  • Jenkins 이용 test report 게시 - 플러그인 이용

비즈니스 로직 구현

  • 클래스 : Calulator
  • 소스 파일의 배치 (신규생성)
    • src/main/java/com/example/calculator/Calulator.java

서버 실행

  • ./gradlew bootrun --args="--server.port=8888"

단위 테스트 작성

JUnit 단위 테스트 라이브러리 이용한 단위 테스트 케이스 작성 및 설정

  • 테스트 케이스를 구현하는 클래스: CalculatorTest
  • 테스트 케이스 소스 파일의 위치: src/test/java/com/example/calculator/CalulatorTest.java

파이프라인 스크립트에 unitTest 추가

stage("Unit Test"){
    steps {
        script {
            container('builder'){
                sh '''
                    chmod +x gradlew
                    ./gradlew test
                '''
            }
        }
    }
}

젠킨스에 test report 발행

  • HTML Publisher plugin 설치
  • 파이프라인 스크립트 추가
  • 젠킨스 좌측 사이드바 test report 확인 가능
container('builder'){
    sh '''
        chmod +x gradlew
        ./gradlew test
    '''
    publishHTML(taget: [
        reportDir: 'build/reports/tests/test',
        reportFiles: 'index.html',
        reportName: 'JUnit Report'
    ])
}

CI 파이프라인 - 코드 품질 확보

코드의 품질이란?

  • 기능성 - 의도한(요구된) 기능을 모두 올바르게 수행하는가?
  • 올바른 코드 말고, 좋은 코드란 어떤 것인가?
    • 읽기 좋은 코드, 재사용성이 높은 코드

실행 시점 아닌, 이전에 정의할 수 있는 코드의 품질은 어떤 것이 있을까?

  • 단위 테스트가 잘 마련되어 있는 코드 - 테스트 커버리지로 측정
  • 규칙에 따라 잘 쓰여진 코드 - 컨벤션(스타일, 가이드라인) 준수 정도로 측정

 

실습 흐름

  • 테스트 커버리지 분석
    • JaCoCo를 이용 : 로컬 환경에서 Gradle 설정하고 테스트 -> Jenkins 파이프라인 스테이지로 추가
  • 코딩 규약 준수 정도 분석
    • Checkstyle을 이용 : 로컬 환경에서 Gradle 설정하고 테스트 -> Jenkins 파이프라인 스테이지로 추가
  • CI Pipeline 완성
    • Pipeline 구성을 SCM Repository에 함께 두고 관리하도록 설정을 변경
    • 코드 리포지토리에 변경사항(push)이 생기는 경우 자동으로 빌드가 개시되도록 설정

 

테스트 커버리지 분석

  • build.gradle에 jacoco 플러그인 추가 및 설정
plugins {
    id 'java'
    id 'org.springframework.boot' version '4.0.0'
    id 'io.spring.dependency-management' version '1.1.7'
    id 'jacoco'
}

jacocoTestCoverageVerification {
    violationRules {
        rule {
            limit {
                minimum = 0.2
            }
        }
    }
}
  • 명령어
./gradlew test jacocoTestCoverageVerification 

./gradlew test jacocoTestReport // jacoco 테스트리포트 생성 

ls -l build/reports/jacoco/test/html // 테스트리포트 경로
  • 젠킨스 파이프라인 스테이지 추가
stage("Code Coverage"){
    steps {
        script {
            container('builder'){
                sh '''
                    chmod +x gradlew
                    ./gradlew jacocoTestReport
                '''
                publishHTML(target: [
                    reportDir: 'build/reports/jacoco/test/html',
                    reportFiles: 'index.html',
                    reportName: 'JaCoCo Report'
                ])
                sh '''
                    chmod +x gradlew
                    ./gradlew jacocoTestCoverageVerification
                '''
            }
        }
    }
}

정적 검사 - Checkstyle 이용

  • Checkstyle 구성 추가
    • https://checkstyle.sourceforge.io
    • 이미 다른 사람들이 만들어서 이용하고 있는 파일을 참고하도록 하고
    • 이후에 우리 팀의 coding style guideline이 정해지면, 그에 맞도록 파일을 다듬기
  • 파일 다운로드
  • 가이드라인 적용
    • 위 두 파일을 config/checkstyle (디렉토리 만들어서) 안에 배치
  • build.gradle 추가
checkstyle {
    toolVersion = '10.12.0'
    configFile = file("config/checkstyle/naver-checkstyle-rules.xml")

    // suppressionFile 변수 지정
    configProperties = [
        'suppressionFile': file("config/checkstyle/naver-checkstyle-suppressions.xml")
    ]
}

tasks.withType(Checkstyle) {
    // 보고서 옵션
    reports {
        html.required.set(true)
        xml.required.set(true)
    }
}

 

Jenkins 파이프라인 스테이지 추가

stage("Static Analysis"){
    steps {
        script {
            container('builder'){
                sh '''
                    chmod +x gradlew
                    ./gradlew checkstyleMain
                '''
                publishHTML(target: [
                    reportDir: 'build/reports/checkstyle',
                    reportFiles: 'main.html',
                    reportName: 'Checkstyle Report'
                ])
            }
        }
    }
}

빌드 명세를 코드 리포지토리와 함께 관리

지금까지 만든 Pipeline script 의 내용 Jenkinsfile로 작성

  • 다만, chckout 스테이지 내용을 다음과 같이 수정 (SCM 설정은 pipeline 속성으로 지정)
stage("Checkout") {
    steps {
        // git url: 'git@github.com:7saval/calculator.git',
        // branch: 'main',
        // credentialsId: 'github-credentials'
        checkout scm
    }
}

빌드 트리거 설정 - 빌드 자동 개시

젠킨스 confiqure > Triggers

  • Poll SCM
    • Schedule : H/5 ****
    • 매 5분마다 (H는 여러 작업이 동시에 몰리지 않도록 하기 위함)

Advanced > Quiet period

  • 코드 변경이 푸시되었음을 감지한 경우에도 일정 시간 동안 빌드 개시않고 기다리도록 설정
    (5초 기본)