젠킨스 파이프라인 설정 가이드 - 멀티브랜치 프로젝트와 Jenkinsfile
인증 정보를 설정했다면 이제 파이프라인을 구성할 차례다. 이 포스트에서는 멀티브랜치 프로젝트를 생성하고 Jenkinsfile로 빌드/배포 파이프라인을 구성하는 방법을 다룬다.
멀티브랜치 프로젝트 생성
멀티브랜치 파이프라인은 저장소의 여러 브랜치를 자동으로 인식하고, 각 브랜치에 있는 Jenkinsfile을 기반으로 빌드를 실행한다.
생성 방법
- 젠킨스 대시보드 → "새로운 Item" 클릭
- 이름 입력 후 Multibranch Pipeline 선택
- "OK" 클릭
Branch Sources 설정
- Branch Sources 섹션에서 "Add source" → GitHub 또는 Git 선택
- Repository URL 입력
- Credentials: 등록해둔 GitHub 크레덴셜 선택
특정 브랜치만 빌드하도록 필터링
모든 브랜치를 빌드하면 리소스 낭비가 될 수 있다. Behaviours 섹션에서 Discover branches 의 "Filter by name (with regular expression)"을 추가해서 특정 브랜치만 빌드하도록 설정할 수 있다.
예를 들어 master, qa, develop 브랜치만 빌드하려면:
master|qa|develop
정규표현식이므로 | 로 여러 브랜치를 나열하면 된다.
feature 브랜치 패턴을 포함하려면:
master|qa|develop|feature/.*
Build Configuration
Jenkinsfile의 위치를 지정한다. 기본값은 저장소 루트의 Jenkinsfile 이다.
다른 경로에 있다면 "Script Path"를 수정한다. (예: ci/Jenkinsfile)
Jenkinsfile 작성
Jenkinsfile은 파이프라인을 코드로 정의하는 파일이다. 저장소에 함께 버전 관리되므로 변경 이력을 추적할 수 있다.
기본 구조
pipeline {
agent any
environment {
NODE_ENV = 'production'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Install') {
steps {
sh 'npm ci'
}
}
stage('Build') {
steps {
sh 'npm run build'
}
}
stage('Test') {
steps {
sh 'npm test'
}
}
stage('Deploy') {
when {
branch 'master'
}
steps {
// 배포 로직
}
}
}
post {
success {
slackSend(color: 'good', message: "Build succeeded: ${env.JOB_NAME} #${env.BUILD_NUMBER}")
}
failure {
slackSend(color: 'danger', message: "Build failed: ${env.JOB_NAME} #${env.BUILD_NUMBER}")
}
}
}
Node.js 프로젝트 예시
Node.js 플러그인을 설정했다면 아래처럼 사용할 수 있다.
pipeline {
agent any
tools {
nodejs 'NodeJS 20'
}
stages {
stage('Install') {
steps {
sh 'npm ci'
}
}
stage('Lint') {
steps {
sh 'npm run lint'
}
}
stage('Test') {
steps {
sh 'npm test'
}
}
stage('Build') {
steps {
sh 'npm run build'
}
}
}
}
SSH를 통한 배포 설정
빌드된 결과물을 SSH로 배포 서버에 전송하려면 SSH Agent 플러그인을 사용한다.
SSH 크레덴셜 등록
- 젠킨스 관리 → Credentials → System → Global credentials
- "Add Credentials" 클릭
- Kind: SSH Username with private key 선택
- 입력 항목:
- ID:
deploy-server-ssh - Username: 서버 접속 유저 (예: ec2-user)
- Private Key: pem 파일 내용 입력
- ID:
Jenkinsfile에서 SSH 배포
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'npm run build'
}
}
stage('Deploy') {
when {
branch 'master'
}
steps {
sshagent(['deploy-server-ssh']) {
sh '''
scp -o StrictHostKeyChecking=no -r dist/* ec2-user@your-server:/var/www/html/
ssh -o StrictHostKeyChecking=no ec2-user@your-server 'pm2 restart all'
'''
}
}
}
}
}
서버 측 SSH 권한 설정
jenkins 유저가 pem 파일에 접근할 수 있어야 한다.
# pem 파일 권한 설정
sudo chown jenkins:jenkins /var/lib/jenkins/.ssh/deploy.pem
sudo chmod 600 /var/lib/jenkins/.ssh/deploy.pem
# jenkins 유저로 SSH 접속 테스트
sudo -u jenkins ssh -i /var/lib/jenkins/.ssh/deploy.pem ec2-user@your-server
브랜치별 배포 전략
Jenkinsfile의 when 조건을 사용해서 브랜치별로 다른 배포 전략을 적용할 수 있다.
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'npm run build'
}
}
stage('Deploy to QA') {
when {
branch 'qa'
}
steps {
// QA 서버 배포
}
}
stage('Deploy to Production') {
when {
branch 'master'
}
steps {
// 프로덕션 서버 배포
}
}
}
}
In-process Script Approval
Jenkinsfile에서 특정 Groovy 메서드나 Java 클래스를 사용하다 보면 이런 에러를 마주칠 수 있다:
Scripts not permitted to use method ...
이건 Jenkins의 보안 기능 이다. 악의적이거나 위험한 코드가 실행되는 걸 막기 위한 장치다.
왜 필요한가
Jenkins는 기본적으로 파이프라인 스크립트를 샌드박스 모드 로 실행한다. 샌드박스 밖의 메서드나 클래스에 접근하려 하면 자동으로 차단된다.
예를 들어:
// 파일 시스템 직접 접근 - 차단됨
new File('/tmp/test.txt').text
// Java 정규식 클래스 사용 - 차단됨
import java.util.regex.Pattern
Pattern.compile('.*')
이런 코드는 Jenkins 서버의 파일 시스템이나 환경 변수에 접근할 수 있어서 보안 위험이 있다.
승인 방법
- 젠킨스 관리 → In-process Script Approval 으로 이동
- 대기 중인 스크립트/메서드 확인
- Approve 버튼 클릭
보안 주의사항
⚠️ 함부로 승인하면 안 된다.
악의적인 코드가 승인되면 Jenkins 서버 전체를 장악할 수 있다. 신뢰할 수 있는 스크립트만 승인한다.
우회 방법 (권장 순서)
승인 없이 문제를 해결하는 게 더 안전하다.
- Declarative Pipeline 사용 - 샌드박스 안에서 대부분 해결 가능
- Jenkins Plugin 사용 - 검증된 플러그인 활용
- Shared Library - 관리자가 승인한 공용 라이브러리
- Script Approval - 정말 필요할 때만 승인
예를 들어 파일을 읽고 싶다면:
// ❌ 승인 필요
new File('test.txt').text
// ✅ 승인 불필요
readFile 'test.txt'
정규식이 필요하다면:
// ❌ 승인 필요
import java.util.regex.Pattern
Pattern.compile('.*')
// ✅ Groovy 내장 기능 사용
def pattern = ~/.*/
대부분의 작업은 Pipeline DSL의 기본 기능으로 해결할 수 있다.
트러블슈팅
agent any와 deadlock
agent any 를 사용하면 사용 가능한 아무 에이전트에 작업이 할당된다. executor 수가 부족하면 여러 빌드가 서로 대기하면서 deadlock이 발생할 수 있다.
해결 방법:
- executor 수를 충분히 확보
- 또는 agent를 명시적으로 지정 (예:
agent { label 'build-server' })
자세한 내용은 초기 설정 가이드의 동시 실행 설정 섹션을 참고한다.
Jenkinsfile을 찾지 못하는 경우
- Jenkinsfile이 저장소 루트에 있는지 확인
- 파일명이 정확히
Jenkinsfile인지 확인 (대소문자 구분) - 다른 경로에 있다면 Build Configuration의 Script Path 수정
참고
이 포스트는 젠킨스 완벽 가이드 시리즈의 일부다. CI/CD 파이프라인의 전반적인 개념은 Jenkins를 활용한 CI/CD 파이프라인 구축하기를 참고한다.