젠킨스를 도입하여 무중단 자동화 배포 파이프라인의 달콤함을 맛보고 있을 무렵, 보통 서비스 런칭 3개월에서 6개월 차 쯤에 모두가 똑같이 겪게 되는 거대한 재앙이 하나 찾아옵니다. 개발자가 코드를 푸시했는데 젠킨스가 아무런 응답을 하지 않고 뻗어버리는 현상입니다. 황급히 서버에 들어가 로그를 확인해 보면 어김없이 "No space left on device" (디스크 용량 100% 초과)라는 끔찍한 에러가 붉게 물들어 있습니다. 원인은 바로 젠킨스의 작업 공간인 Workspace(워크스페이스) 관리에 실패했기 때문입니다.
이 글에서는 인프라 관리자의 수명을 갉아먹는 이 고질적인 문제를 원천 봉쇄하고, Workspace Cleanup 플러그인을 활용하여 항상 쾌적하고 깔끔한 서버 환경을 유지하는 실무 최적화 기법에 대하여 다뤄보겠습니다.
1. 디스크 풀(Disk Full) 현상의 정체: 무한히 증식하는 쓰레기 더미
젠킨스가 코드를 빌드할 때는 가상의 공간이 아니라 서버의 실제 물리적 하드디스크 공간을 갉아먹습니다. 기본적으로 /var/jenkins_home/workspace/ 경로 아래에 각 잡(Job)의 이름으로 폴더가 생기며, 젠킨스는 이 곳에 Github에서 소스 코드를 클론(Clone)받고, 필요한 의존성 패키지들(Java의 .m2, Node.js의 node_modules)을 기가바이트 단위로 다운로드받습니다. 그리고 컴파일을 거쳐 무거운 .jar 빌드 산출물이나 임시 이미지 파일들을 생성해 냅니다.
치명적 문제: 젠킨스는 파이프라인 빌드가 끝나더라도 기본적으로 이 Workspace 폴더를 스스로 지우지 않습니다. 만약 프론트엔드 프로젝트 하나의 Workspace 용량이 1GB인데 하루에 개발자들이 10번씩 빌드를 돌린다면? 일주일이면 70GB, 한 달이면 수백 GB의 쓰레기 데이터가 고스란히 쌓이게 됩니다. 결국 서버 디스크 할당량을 100% 꽉 채우게 되고, OS는 새로운 로그 파일조차 쓸 공간이 없어져 젠킨스 데몬 자체가 크래시(Crash)나며 마비되어 버립니다. 이때 복구하려면 서버 터미널에 접속해 강제로 폴더들을 날려주어야 하는 엄청난 쌩고생을 동반합니다.
2. 구원투수: Workspace Cleanup 플러그인 도입
이러한 참사를 막기 위한 업계 표준 해결책이 바로 Workspace Cleanup Plugin을 사용하는 것입니다. 이 플러그인은 파이프라인의 생명주기가 끝날 때, 해당 빌드가 어질러 놓은 작업 공간을 말끔히 포맷(삭제)해주는 역할을 합니다.
플러그인 설치 방법:
[Jenkins 관리] -> [플러그인 관리] 메뉴로 들어가 Workspace Cleanup을 검색하여 설치합니다. (초기 설정 시 'Install suggested plugins'를 선택했다면 이미 설치되어 있을 확률이 높습니다.)
전략적 위치 선정 (Post 블록 100% 활용):
이 청소 코드를 steps 내부에 적으면 앞서 포스팅에서 설명했듯 빌드가 중간에 에러가 났을 때 실행되지 않고 넘어갈 수 있습니다. 따라서 반드시 파이프라인 맨 하단의 post { always { ... } } 블록 안에 선언해야 합니다. 그래야 성공하든 실패하든, 젠킨스는 퇴근하기 전에 무조건 자기 자리를 청소하고 나가게 됩니다.
3. 실무 적용 코드 파헤치기: `cleanWs()`
플러그인이 설치되었다면 cleanWs() 라는 내장 함수를 호출할 수 있습니다. 단순 호출뿐만 아니라, 다양한 옵션을 파라미터로 넘겨 세밀한 청소 정책을 설정할 수 있습니다.
pipeline {
agent any
stages
stage('Build Project') {
steps {
echo '수 기가바이트의 소스코드와 라이브러리를 받아와 빌드합니다...'
sh 'npm install && npm run build'
}
}
}
// 파이프라인의 제일 끝단, 어떤 결과에도 무조건 실행되는 영역
post {
always {
echo ' 빌드 작업 종료. Workspace를 깨끗하게 청소합니다.'
// 단순하게 cleanWs() 라고만 써도 작동하지만,
// 아래처럼 명시적 옵션을 주는 것이 실무 Best Practice 입니다.
cleanWs(
cleanWhenFailure: true, // 실패했을 때도 얄짤없이 삭제
cleanWhenSuccess: true, // 성공했을 때도 삭제
cleanWhenUnstable: true, // 불안정 상태일 때도 삭제
cleanWhenAborted: true, // 취소되었을 때도 삭제
deleteDirs: true, // 숨김 폴더나 빈 디렉토리 구조까지 싹 날림
disableDeferredWipeout: true // 백그라운드 삭제 대신 즉시 동기식으로 삭제
)
}
}
}
이 코드 한 뭉텅이만 여러분의 모든 파이프라인 하단에 붙여넣어 준다면, 젠킨스 서버의 디스크 사용량은 항상 쾌적한 10~20% 대를 유지하게 될 것이며 인프라 장애로 밤잠을 설칠 일은 영원히 사라집니다.
4. 중급 트러블슈팅: 지우지 말아야 할 '캐시(Cache)'의 딜레마
여기서 아주 예리한 개발자라면 딜레마에 봉착하게 됩니다. "잠깐, 빌드 끝날 때마다 Workspace를 싹 지워버리면, 다음번 빌드 때 수십 MB~GB에 달하는 npm 패키지나 maven 라이브러리를 처음부터 다시 다운로드받아야 하잖아요? 그럼 빌드 속도가 너무 느려지지 않나요?"
정확한 지적입니다. 청소를 너무 빡세게 하면 네트워크 I/O 병목이 발생하여 파이프라인 속도가 급격히 느려집니다. 그래서 진정한 상위 1% 실무자들은 캐시(Cache) 폴더 마운트 분리 기법을 사용합니다.
해결책 (Docker Agent 결합): 이전 포스팅에서 다루었던 Docker Agent 설정과 결합하는 것입니다. 도커 컨테이너를 띄울 때 패키지가 저장되는 디렉토리(예: /root/.npm 또는 /root/.m2)를 컨테이너 외부 호스트 서버의 디렉토리와 볼륨 마운트(Volume Mount)를 걸어버립니다. 이렇게 세팅하면, 파이프라인 마지막에 cleanWs()가 실행되어 소스코드 찌꺼기(Workspace)는 날려버리지만, 핵심 라이브러리 파일들은 안전한 외부 공간(호스트 서버 볼륨)에 캐시로 고스란히 남아 다음 빌드 때 즉시 재활용됩니다. 속도와 청결함, 두 마리 토끼를 모두 완벽히 잡아내는 인프라 아키텍처의 승리입니다.
5. 마무리 및 주요 발전 방향
지금까지 수많은 데브옵스 주니어들의 멘탈을 붕괴시키는 디스크 풀(Disk Full) 현상의 근본 원인을 파헤치고, Workspace Cleanup 플러그인을 활용해 서버를 항상 쾌적하게 유지하는 노하우와 캐시 딜레마 극복 방법에 대해 3,000자에 걸쳐 아주 치밀하게 알아보았습니다. 이 작은 습관 하나가 인프라의 안정성을 수백 배 끌어올린다는 사실을 절대 잊지 마십시오.
파이프라인이 안정적으로 돌아가기 시작하면, 팀장님이나 경영진은 슬슬 새로운 요구사항을 던지기 시작합니다.
"빌드 실패 알림이 매일 이메일로 오니까 보지도 않고 쌓이기만 하네요. 요즘 다들 쓰는 사내 메신저인 Slack(슬랙)으로 실패 로그가 팝업되게 해줄 수 없나요?"
인프라 담당자의 가치를 증명할 시간이 왔습니다. 본 설명에서는 모두가 열광하는 'Slack과 젠킨스의 연동을 통한 실시간 빌드 알림(Notification) 봇 구축의 모든 것'에 대해 아주 꼼꼼하게 셋업 가이드를 제공하겠습니다. 기대해 주십시오!
파이프라인 구축의 최종 목표는 '개발자가 배포에 신경 쓰지 않고 코드에만 집중하게 만드는 것'입니다. 배포 버튼을 누르고 빌드가 끝날 때까지 10분 동안 젠킨스 화면만 멍하니 쳐다보고 있다면 그것은 반쪽짜리 자동화입니다. 젠킨스가 빌드를 돌리는 동안 개발자는 커피를 마시거나 다른 코드를 짜고, 빌드가 끝나면 젠킨스가 알아서 사내 메신저인 Slack(슬랙)으로 성공/실패 여부를 보고하게 만들어야 합니다.
본 글에서는 인프라 관리자와 개발팀 모두에게 사랑받는 Jenkins-Slack 실시간 알림 연동 및 커스텀 봇(Bot) 구축 기법에 대하여 다뤄보겠습니다.
1. 왜 이메일 알림은 버림받았는가?
불과 몇 년 전만 해도 빌드가 터지면 젠킨스가 개발팀 전체 이메일로 [에러] 빌드 실패 알림 메일을 발송했습니다. 그러나 이메일은 실시간 확인이 어렵고, 스팸 메일함으로 빠지기 일쑤이며, 무엇보다 '팀원 간의 즉각적인 소통(장애 대응)'이 불가능합니다.
반면 Slack 특정 채널(예: #deploy-alerts, #backend-dev)에 알림을 쏘면 어떨까요? 모바일 앱으로 즉시 푸시 알림이 가며, 누군가 에러 메시지 아래에 댓글(Thread)을 달아 "제가 방금 푸시한 커밋 때문인 것 같습니다. 지금 바로 핫픽스(Hotfix) 올리겠습니다!"라고 즉각적인 장애 대응 커뮤니케이션을 시작할 수 있습니다. 이것이 바로 현대 데브옵스(DevOps)가 추구하는 ChatOps(채팅 기반 운영)의 핵심입니다.
2. Slack 앱 추가 및 Token 발급 (Slack 측 셋업)
젠킨스가 슬랙에 메시지를 쏘려면, 슬랙 채널 입장권(Token)이 필요합니다.
- Slack 좌측 하단의 [Apps (앱)] 메뉴를 클릭하거나 Slack App Directory 웹사이트로 이동합니다.
- 검색창에 Jenkins CI를 검색하고 앱을 워크스페이스에 추가(Install)합니다.
- 이 봇이 기본적으로 메시지를 쏘게 될 채널(Channel)을 하나 선택합니다. (예:
#deploy-alerts) - 추가를 완료하면 화면에 Integration Token (통합 토큰)이라는 긴 암호 문자열이 나타납니다. 이 값을 복사해 둡니다.
3. Jenkins 플러그인 설치 및 Credentials 등록 (Jenkins 측 셋업)
이제 슬랙에서 받아온 입장권을 젠킨스에 세팅할 차례입니다.
- 플러그인 설치: [Jenkins 관리] -> [플러그인 관리]에서
Slack Notification Plugin을 검색하여 설치합니다. - 자격 증명 등록: 이전에 배웠던 Credentials 관리를 떠올려봅시다. 토큰은 민감한 보안 정보이므로 [Manage Credentials] 메뉴에 들어가서,
Secret text타입으로 방금 복사한 슬랙 토큰을 붙여넣고 ID를slack-token이라고 저장합니다. - 시스템 글로벌 설정: [Jenkins 관리] -> [시스템 설정(Configure System)]으로 들어가 맨 밑의 Slack 섹션을 찾습니다.
- Workspace 입력칸에 슬랙 워크스페이스 이름(예:
my-company)을 적고, Credentials 드롭다운에서 아까 만든slack-token을 선택합니다. Default channel 입력칸에는#deploy-alerts를 적어줍니다. - 우측 하단의 Test Connection 버튼을 누릅니다.
Success가 뜨면서 슬랙 채널에 반가운 테스트 메시지가 날아왔다면 완벽하게 연결된 것입니다!
4. 실무 파이프라인 코드: slackSend() 함수 응용
연동이 끝났다면 이제 에서 배웠던 파이프라인의 post 섹션에 slackSend 함수를 결합할 차례입니다. 실무에서는 시각적인 구분을 위해 성공(초록색), 실패(빨간색), 취소(회색) 등 색상을 다르게 주고, 에러 발생 시 특정 개발자나 채널 전체를 호출(Mention)하는 기법을 씁니다.
pipeline {
agent any
stages {
stage('Build') {
steps { sh 'npm run build' }
}
}
// 전체 빌드가 끝난 후 상태별 슬랙 알림 발송
post {
success {
// 빌드 성공 시: 초록색(good) 바와 함께 조용히 보고
slackSend (
channel: '#deploy-alerts',
color: 'good',
message: " [SUCCESS] ${env.JOB_NAME} 배포 성공!\n버전: #${env.BUILD_NUMBER}\n상세 확인: ${env.BUILD_URL}"
)
}
failure {
// 빌드 실패 시: 빨간색(danger) 바와 함께 채널 멤버 전체(@channel) 호출!
slackSend (
channel: '#deploy-alerts',
color: 'danger',
message: " [FAILURE] <!channel> ${env.JOB_NAME} 배포가 터졌습니다!\n버전: #${env.BUILD_NUMBER}\n원인 분석 로그: ${env.BUILD_URL}console"
)
}
aborted {
// 사용자가 수동 취소했을 때: 경고(warning/회색) 색상으로 알림
slackSend (
channel: '#deploy-alerts',
color: 'warning',
message: " [ABORTED] 누군가에 의해 ${env.JOB_NAME} 배포가 취소되었습니다."
)
}
}
}
실무 꿀팁: 슬랙에서 멘션(Mention)을 날릴 때 @channel이나 특정 유저를 호출하려면 위 코드처럼 <!channel> 또는 유저 고유 ID인 <@U12345ABC> 형식으로 적어주어야 슬랙 봇이 멘션으로 제대로 인식하고 푸시 알림을 울립니다.
5. 마무리 및 주요 발전 방향
지금까지 단방향의 답답했던 젠킨스를 실시간 소통이 가능한 최첨단 알림 봇으로 진화시키는 Slack 연동을 다루어 보았습니다. 이제 여러분의 개발팀은 배포가 잘 되었는지 물어보러 데브옵스 팀의 자리에 찾아올 필요 없이, 슬랙 채팅방 하나만 켜두면 됩니다.
지금까지 우리는 하나의 Jenkinsfile을 만들고, 하나의 Job을 만들어 브랜치를 빌드했습니다.
하지만 개발자가 새로운 브랜치(feature/login)를 만들 때마다 젠킨스 웹에 접속해서 "새로운 브랜치용 잡(Job)을 하나 더 만들어주세요"라고 요청한다면 어떨까요? 인프라 팀은 하루 종일 젠킨스 화면만 누르다 퇴근하게 될 것입니다.
다음 포스트에서는 새로운 브랜치를 감지하면 젠킨스가 스스로 파이프라인을 복제하여 셋업해 주는 자동화의 끝판왕, 'Multibranch Pipeline (다중 브랜치 파이프라인) 구축 기법'에 대해 작성해보겠습니다.
'CI. CD > Jenkins' 카테고리의 다른 글
| [Jenkins] 병렬 빌드로 파이프라인 속도 혁신하기(Parallel Build) (0) | 2026.10.05 |
|---|---|
| [Jenkins] 멀티브랜치 파이프라인 무한 증식 브랜치 자동화 (0) | 2026.10.04 |
| [Jenkins] When 조건문으로 스테이지 완벽 제어하기 동적 파이프라인 구축 (0) | 2026.10.04 |
| [Jenkins] Pipeline의 시작 Scripted vs Declarative 문법 완벽 가이드 (0) | 2026.10.03 |
| [Jenkins] Freestyle Project로 첫 자동화 빌드 만들기 초보자 완벽 가이드 (0) | 2026.10.03 |