웹 파이프라인/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 테스트
- 위 패키지 구성, 코드 배치(ADD 하거나 tar 옮겨 풀너ㅏ, git pull 하거나)
- 레지스트리에 게시
- 태그 붙이고 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이 정해지면, 그에 맞도록 파일을 다듬기
- 파일 다운로드
- 링크: https://github.com/naver/hackday-conventions-java/tree/master/rule-config
- 위 리포지토리에서 다음과 같은 두 개 파일 다운로드
- naver-checkstyle-rules.xml
- naver-checkstyle-suppressions.xml
- 가이드라인 적용
- 위 두 파일을 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
}
}
빌드 트리거 설정 - 빌드 자동 개시
- Schedule은 cron의 문법을 따름
- 링크 : https://crontab.guru
젠킨스 confiqure > Triggers
- Poll SCM
- Schedule : H/5 ****
- 매 5분마다 (H는 여러 작업이 동시에 몰리지 않도록 하기 위함)
Advanced > Quiet period
- 코드 변경이 푸시되었음을 감지한 경우에도 일정 시간 동안 빌드 개시않고 기다리도록 설정
(5초 기본)