파이프라인 매개변수(Parameters)를 통해 외부에서 동적인 값을 주입받는 방법을 익혔다면, 이제 그 값에 따라 파이프라인의 물줄기를 요리조리 바꾸는 방법을 알아야 합니다. 만약 매개변수 설정만 해두고 if-else 문 같은 로직 분기를 태우지 않는다면 매개변수는 그저 화면에 찍히는 의미 없는 문자에 불과합니다.
본 글에서는 Declarative Pipeline의 꽃이자, 하나의 파일로 수십 가지의 배포 시나리오를 감당하게 해주는 강력한 무기인 'when' 조건문의 완벽한 활용법과 다양한 실무 예제들을 다뤄보겠습니다. 이 글을 마스터하시면 더 이상 브랜치별로 수많은 잡(Job)을 복사/붙여넣기 하는 고통에서 영원히 해방될 수 있습니다.
1. 왜 if-else 문을 쓰지 않고 when을 쓰는가?
과거 Scripted Pipeline 시절에는 모든 로직을 if (env.BRANCH_NAME == 'main') { ... } else { ... } 형태로 작성했습니다. 언뜻 보면 익숙한 프로그래밍 방식이라 편해 보이지만, 이 방식은 파이프라인 코드가 길어질수록 가독성을 심각하게 훼손합니다. 스테이지 안에 로직이 파묻혀버려, 젠킨스 웹 대시보드의 시각적 UI(Stage View)에서 이 스테이지가 "실행 중 실패한 것인지" 아니면 "조건이 안 맞아서 건너뛴(Skipped) 것인지" 명확히 구분되지 않는 치명적인 단점이 존재했습니다.
Declarative Pipeline은 이러한 문제를 when { ... } 블록으로 우아하게 해결했습니다. stage 블록 내부, steps 블록이 시작되기 when을 선언하면 젠킨스는 해당 스테이지를 실행하기 전에 조건을 먼저 평가합니다. 조건이 true면 steps를 실행하고, false면 해당 스테이지를 완전히 건너뜁니다(Skip). 웹 대시보드에서도 해당 스테이지가 '건너뜀' 상태로 빗금 처리되어 아주 명확한 시각적 피드백을 제공합니다.
2. 실무에서 가장 많이 쓰이는 3대 핵심 조건
when 블록 안에는 다양한 조건식(Condition)을 넣을 수 있습니다. 그중 실무 파이프라인의 90% 이상을 차지하는 3가지 핵심 조건을 완벽하게 숙지해야 합니다.
1. branch 조건 (가장 많이 쓰임)
코드가 푸시된 브랜치 이름을 검사합니다. Multibranch Pipeline이나 Github Webhook과 연동할 때 완벽한 궁합을 자랑합니다. 정규표현식(Regex)이나 와일드카드 기호도 지원합니다.
stage('Production Deploy') {
when {
// 정확히 main 브랜치일 때만 통과
branch 'main'
// 정규표현식: feature- 로 시작하는 브랜치일 때 통과
// branch pattern: "feature-.*", comparator: "REGEXP
}
steps { sh 'echo "운영 배포 시작!"' }
}
2. expression 조건 (가장 강력함)
Groovy 언어 기반의 어떠한 논리식이라도 넣을 수 있는 만능 조건문입니다. 주로 에서 배운 파이프라인 매개변수(Parameters) 값이나 내장 환경변수를 비교할 때 사용합니다.
stage('E2E Test') {
when {
// RUN_E2E 파라미터가 true(체크됨)일 때만 통과. (Groovy 문법이므로 return 필수)
expression { return params.RUN_E2E == true }
}
steps { sh 'npm run test:e2e' }
}
3. changeset 조건 (모노레포의 구세주)
프론트엔드와 백엔드가 하나의 레포지토리에 모여있는 모노레포(Monorepo) 구조에서 구세주 같은 역할을 합니다. 이번 깃 커밋(GIT Commit)에서 특정 경로의 파일이 변경되었는지를 감지합니다. 즉, 프론트엔드 코드만 1줄 수정했는데 백엔드 서버까지 굳이 재빌드하는 낭비를 막아줍니다.
stage('Backend Build') {
when {
// server/ 폴더 안의 파일이 단 하나라도 수정된 커밋일 경우에만 통과
changeset "server/**/*"
}
steps { sh 'cd server && ./gradlew build' }
}
3. 복합 조건문: allOf, anyOf, not 연산자 활용하기
하나의 조건만으로는 부족한 경우가 많습니다. "main 브랜치이면서, 동시에 배포 환경(TARGET_ENV)이 PROD일 때만"이라는 복잡한 비즈니스 로직을 구현해야 할 때는 논리 연산자 블록을 중첩해서 사용합니다.
- allOf (AND 연산): 내부의 모든 조건이 참(true)이어야만 통과합니다.
- anyOf (OR 연산): 내부의 조건 중 하나라도 참(true)이면 통과합니다.
- not (NOT 연산): 내부의 조건이 거짓(false)일 때 통과합니다.
실무 적용 극강의 예제:
pipeline {
agent any
parameters { choice(name: 'ENV', choices: ['DEV', 'PROD']) }
stages {
stage('Deploy to Prod') {
when {
// main 브랜치 '이면서' ENV 파라미터가 PROD 일 때만 실행하라!
allOf {
branch 'main'
expression { return params.ENV == 'PROD' }
}
}
steps {
echo " 운영 환경 배포를 시작합니다!"
// sh './deploy.sh prod'
}
}
stage('Skip Sandbox') {
when {
// 현재 브랜치가 sandbox가 '아닐 때만' 실행하라!
not { branch 'sandbox' }
}
steps {
echo "샌드박스 브랜치가 아니므로 정상적인 테스트 프로세스를 진행합니다."
}
}
}
}
4. 마무리 및 주요 발전 방향
지금까지 파이프라인의 생명을 불어넣는 동적 흐름 제어의 마술사, `when` 조건문의 핵심 조건들과 복합 논리 연산자 구성 방법에 대해 다루어 보았습니다. 이제 여러분은 개발, 스테이징, 운영 환경 배포를 단 하나의 Jenkinsfile에 우아하게 통합할 수 있는 능력을 갖추게 되었습니다. 불필요한 스테이지를 과감히 건너뛰게 만들면 전체 빌드 시간은 획기적으로 줄어들고 리소스 낭비는 사라집니다.
파이프라인이 when을 통해 역동적으로 흐르다 보면, 어느 스테이지는 통과하고 어느 스테이지는 실패하며 결국 파이프라인의 '최종 상태'가 결정됩니다. 그렇다면 이 최종 결과(성공/실패)에 따라 임시 파일을 청소하거나 담당자에게 슬랙 알림을 쏴주는 작업은 어디에 적어야 할까요? steps 맨 마지막 줄에 적으면 에러가 났을 때 그 줄에 도달하기도 전에 파이프라인이 멈춰버리게 됩니다. 본 설명에서는 모든 결과에 완벽하게 대응하는 자동화의 화룡점정, 'post 섹션을 활용한 빌드 후처리(알림/청소) 기법'에 대해 아주 치밀하게 파헤쳐 보겠습니다!
빌드가 무사히 완료되어 배포가 끝났다고 해서 젠킨스의 임무가 완전히 종료된 것은 아닙니다. "성공적으로 배포되었습니다"라는 메시지를 개발팀 슬랙(Slack) 채널에 쏘아주고, 빌드 과정에서 생성된 수십 기가바이트의 찌꺼기 파일(임시 캐시 등)을 청소해주어야 비로소 진정한 파이프라인의 사이클이 완성됩니다. 만약 중간에 에러가 났다면? 원인을 즉시 분석할 수 있도록 실패 로그를 추출하여 담당자에게 경고 이메일이나 멘션을 날려야 합니다.
본 글에서는 파이프라인의 화룡점정이자 사고 발생 시 골든타임을 확보해주는 핵심 기술, Declarative Pipeline의 `post` 섹션을 활용한 완벽한 빌드 후처리 자동화 기법에 대해 다뤄보겠습니다.
1. 왜 steps의 마지막 줄에 후처리 코드를 넣지 않는가?
초보자들이 가장 흔히 하는 실수는 "빌드가 끝나면 슬랙 알림을 보내야지"라고 생각하고, 마지막 steps 블록의 제일 끝단에 알림 스크립트를 밀어 넣는 것입니다. sh 'npm run build' 바로 밑에 sh 'curl slack-webhook-url...'을 적어버리는 식이죠.
치명적 문제: 만약 npm run build 도중에 구문 에러로 인해 빌드가 실패(Failure)하게 되면, 젠킨스는 즉시 파이프라인 실행을 그 자리에서 중단(Abort)해 버립니다. 즉, 그 밑에 적어둔 슬랙 알림 스크립트는 아예 실행조차 되지 못하고 파이프라인이 뻗어버리는 대참사가 발생합니다. 결국 빌드가 터졌는데도 아무도 알림을 받지 못해 운영 장애로 직결됩니다. 따라서 어떠한 에러가 나더라도, 심지어 사용자가 중간에 X 버튼을 눌러 취소하더라도 최후에 무조건 실행을 보장받는 독립된 블록이 필요하며, 그것이 바로 post 섹션입니다.
2. Post 블록의 전략적 위치 (전역 vs 지역)
post 블록은 선언하는 위치에 따라 그 역할과 스코프가 완전히 달라집니다. 실무에서는 상황에 맞게 2가지 위치를 혼용해서 사용합니다.
1. 전역 후처리 (Pipeline-level Post)
파이프라인의 맨 마지막, 즉 전체 stages 블록이 완전히 끝난 직후 단 한 번만 실행됩니다. 주로 전체 파이프라인의 최종 성적표(최종 성공/실패 여부)를 슬랙으로 알리거나 젠킨스 워크스페이스 전체를 포맷하는 용도로 쓰입니다. 가장 흔하고 권장되는 위치입니다.
2. 지역 후처리 (Stage-level Post)
각 개별 stage 블록 내부에 들어갑니다. 예를 들어 'Test' 스테이지가 끝난 직후에만 테스트 커버리지 리포트를 수집하거나, 특정 스테이지만 실패했을 때 담당 파트에만 알림을 분리해서 보낼 때 아주 세밀한 컨트롤을 위해 사용합니다.
3. 상태(Condition) 지시어 완벽 해부
post 블록 안에는 어떤 상황일 때 동작할 것인지 조건을 지정해야 합니다. 다음 6가지 Condition을 명확히 이해해야 합니다.
always(항상): 앞의 파이프라인이 성공하든, 처참하게 실패하든, 사용자가 취소하든 무조건 100% 실행됩니다. 주로 데이터베이스 연결 해제, 도커 임시 이미지 삭제, Workspace 청소(cleanWs)에 쓰이는 핵심 구문입니다.success(성공): 파이프라인 전체(혹은 해당 스테이지)가 단 하나의 에러 없이 완벽하게 끝났을 때만 실행됩니다. " 배포 완료" 알림을 보낼 때 씁니다.failure(실패): 중간에 쉘 스크립트가 1 이상의 에러 코드(Exit code)를 뱉고 비정상 종료되었을 때 실행됩니다. 담당자를 호출(Mention)하고 에러 로그 링크를 쏘는 데 특화되어 있습니다.aborted(취소): 관리자가 젠킨스 화면에서 강제로 빨간색 X 버튼(Cancel)을 눌러 빌드를 중단시켰을 때 실행됩니다.unstable(불안정): 빌드는 끝까지 돌았으나, 단위 테스트(JUnit 등) 통과율이 기준치 미달이거나 SonarQube 품질 게이트를 간신히 통과하지 못해 경고(노란색 불)가 떴을 때 실행됩니다.changed(상태 변경): 이전 빌드의 결과와 이번 빌드의 결과가 다를 때만 실행됩니다. 예를 들어 "실패->성공" 으로 복구되었을 때 " 빌드가 다시 정상화되었습니다!"라는 알림을 한 번만 보내고 싶을 때 쓰이는 극강의 실무 팁입니다.
4. 실무 적용 극한의 예제 (Slack 알림 및 청소 자동화)
모든 이론을 종합하여, 유니콘 스타트업 데브옵스 팀에서 실제로 굴리고 있는 가장 이상적인 post 블록 코드를 .
pipeline {
agent any
stages {
stage('Build & Deploy') {
steps { sh 'echo "열심히 배포 중..."' }
}
}
// 파이프라인 최하단 전역 후처리
post {
always {
// 1. 빌드가 끝나면 서버 디스크가 터지지 않도록 무조건 쓰레기 파일 정리
echo " Workspace를 깨끗하게 청소합니다."
cleanWs(cleanWhenFailure: true, cleanWhenSuccess: true)
}
success {
// 2. 성공 알림. (환경변수를 적극 활용하여 메타데이터 구성)
echo " 배포 성공!"
// slackSend color: 'good', message: "[${env.JOB_NAME}] 빌드 성공 (#${env.BUILD_NUMBER})\n상세보기: ${env.BUILD_URL}"
}
failure {
// 3. 실패 알림. 담당자 멘션 포함
echo " 치명적 빌드 실패 발생!"
// slackSend color: 'danger', message: " <@channel> [${env.JOB_NAME}] 빌드 실패!! 즉시 확인 바람!\n상세 로그: ${env.BUILD_URL}/console"
}
changed {
// 4. 상태 변경 시에만 복구 알림. (계속 성공할 때는 시끄럽게 알림을 보내지 않음)
echo " 빌드 상태가 변경되었습니다. (예: 실패 상태에서 드디어 복구됨!)"
}
}
}
5. 마무리 및 주요 발전 방향
지금까지 파이프라인의 완성도를 200% 끌어올려 주는 `post` 섹션의 완벽한 배치 전략과 상태별 세밀한 동작 제어법에 대해 다루어 보았습니다. 이제 여러분의 파이프라인은 어떤 상황에서도 무너지지 않으며, 개발팀과 인프라팀 모두 슬랙 알림 하나만 보고 편안하게 커피를 마시며 장애에 대비할 수 있게 되었습니다.
위 예제 코드의 always 블록에서 cleanWs()라는 매우 중요한 함수를 살짝 스포일러 했습니다. 젠킨스를 1년 이상 운영해 본 실무자라면 누구나 한 번쯤 겪게 되는 최악의 악몽, 바로 서버 디스크 100% 꽉 참 (Disk Full) 사태입니다. 이 사태가 벌어지면 젠킨스가 그대로 기절해버리며 모든 서비스 배포가 마비됩니다.
다음 포스트에서는 서버 디스크 공간을 사수하기 위한 'Jenkins Workspace 깔끔하게 유지하기' 실무 최적화 기법에 대해 다루어보겠습니다.
'CI. CD > Jenkins' 카테고리의 다른 글
| [Jenkins] 멀티브랜치 파이프라인 무한 증식 브랜치 자동화 (0) | 2026.10.04 |
|---|---|
| [Jenkins] 젠킨스 워크스페이스 완벽 청소 가이드 (디스크풀 대응) (0) | 2026.10.04 |
| [Jenkins] Pipeline의 시작 Scripted vs Declarative 문법 완벽 가이드 (0) | 2026.10.03 |
| [Jenkins] Freestyle Project로 첫 자동화 빌드 만들기 초보자 완벽 가이드 (0) | 2026.10.03 |
| [Jenkins] Github Webhook과 Jenkins 연동 완전 자동화의 꽃 (0) | 2026.10.03 |