GitLab CI/CD vs Jenkins — 실무 비교
GitLab CI/CD와 Jenkins의 구조, 파이프라인 작성 방식, 운영 부담을 실제 예시로 비교하고 팀 상황에 맞는 선택 기준을 정리했다.
GitLab CI/CD vs Jenkins — 실무 비교
한 줄 요약
GitLab CI/CD
통합 플랫폼
Jenkins
전용 CI 서버
항목을 클릭하면 상세 비교를 확인할 수 있습니다
| GitLab CI/CD | Jenkins | |
|---|---|---|
| 형태 | SaaS / Self-hosted 통합 플랫폼 | 전용 CI 서버 (Self-hosted) |
| 설정 | .gitlab-ci.yml (YAML) | Jenkinsfile (Groovy DSL) |
| 운영 부담 | 낮음 (GitLab.com 사용 시 거의 없음) | 높음 (직접 설치·유지보수) |
| 플러그인 | 내장 기능 위주 | 2,000개+ 플러그인 |
GitLab CI/CD 구조
GitLab은 Git 저장소 + CI/CD + Container Registry + 이슈 트래커가 하나의 플랫폼에 통합되어 있다.
.gitlab-ci.yml → GitLab Runner(에이전트) 실행 → 결과를 GitLab UI에 표시.gitlab-ci.yml 기본 구조
# .gitlab-ci.yml
stages:
- install
- test
- build
- deploy
variables:
NODE_VERSION: "20"
IMAGE_NAME: $CI_REGISTRY_IMAGE # GitLab Container Registry 자동 변수
# 공통 설정 (앵커 재사용)
.node_template: &node_template
image: node:20-alpine
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- node_modules/
install:
<<: *node_template
stage: install
script:
- npm ci
test:
<<: *node_template
stage: test
script:
- npm test -- --coverage
coverage: '/Statements\s*:\s*([\d.]+)%/' # 커버리지 수치 파싱
artifacts:
reports:
junit: coverage/junit.xml
paths:
- coverage/
build:
<<: *node_template
stage: build
script:
- npm run build
artifacts:
paths:
- .next/
expire_in: 1 hour
docker-build:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_NAME:$CI_COMMIT_SHORT_SHA .
- docker push $IMAGE_NAME:$CI_COMMIT_SHORT_SHA
- docker tag $IMAGE_NAME:$CI_COMMIT_SHORT_SHA $IMAGE_NAME:latest
- docker push $IMAGE_NAME:latest
deploy-staging:
stage: deploy
environment:
name: staging
url: https://staging.example.com
script:
- ssh deploy@staging "docker pull $IMAGE_NAME:latest && docker compose up -d"
only:
- develop
deploy-production:
stage: deploy
environment:
name: production
url: https://example.com
script:
- ssh deploy@production "docker pull $IMAGE_NAME:latest && docker compose up -d"
only:
- main
when: manual # 수동 승인 후 배포GitLab 자동 환경변수
GitLab은 파이프라인 실행 시 유용한 변수를 자동으로 주입한다.
CI_COMMIT_SHA → 전체 커밋 해시
CI_COMMIT_SHORT_SHA → 앞 8자리
CI_COMMIT_BRANCH → 브랜치명
CI_REGISTRY → GitLab Container Registry 주소
CI_REGISTRY_IMAGE → 현재 프로젝트 이미지 경로
CI_ENVIRONMENT_NAME → 배포 환경 이름Jenkins 파이프라인 (동일 작업)
같은 파이프라인을 Jenkins로 작성하면:
// Jenkinsfile
pipeline {
agent any
environment {
IMAGE_NAME = 'registry.example.com/my-app'
REGISTRY = 'registry.example.com'
}
stages {
stage('Install') {
agent { docker { image 'node:20-alpine' } }
steps { sh 'npm ci' }
}
stage('Test') {
agent { docker { image 'node:20-alpine' } }
steps {
sh 'npm test -- --coverage'
}
post {
always { junit 'coverage/junit.xml' }
}
}
stage('Docker Build & Push') {
steps {
script {
docker.withRegistry("https://${REGISTRY}", 'registry-creds') {
def img = docker.build("${IMAGE_NAME}:${env.GIT_COMMIT[0..7]}")
img.push()
img.push('latest')
}
}
}
}
stage('Deploy Staging') {
when { branch 'develop' }
steps {
sshagent(['staging-ssh-key']) {
sh 'ssh deploy@staging "docker pull ${IMAGE_NAME}:latest && docker compose up -d"'
}
}
}
stage('Deploy Production') {
when { branch 'main' }
input { message '프로덕션에 배포하시겠습니까?' } // 수동 승인
steps {
sshagent(['prod-ssh-key']) {
sh 'ssh deploy@production "docker pull ${IMAGE_NAME}:latest && docker compose up -d"'
}
}
}
}
post {
success { slackSend message: "✅ 빌드 성공: ${env.JOB_NAME}" }
failure { slackSend message: "❌ 빌드 실패: ${env.JOB_NAME}" }
}
}핵심 차이점 비교
1. 설정 언어
# GitLab: 선언형 YAML → 읽기 쉬움, IDE 자동완성 지원
script:
- npm ci
- npm test// Jenkins: Groovy DSL → 복잡한 로직 구현 가능
steps {
script {
def version = sh(script: 'cat package.json | jq -r .version', returnStdout: true).trim()
currentBuild.displayName = "#${BUILD_NUMBER} - v${version}"
}
}2. 트리거 설정
# GitLab — 코드 안에서 선언
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_TAG # 태그 푸시 시
when: never # 제외// Jenkins — UI에서 설정하거나 코드로 선언
triggers {
pollSCM('H/5 * * * *') // 5분마다 변경 확인
cron('0 2 * * *') // 매일 새벽 2시
}
// 또는 Webhook 설정 (플러그인 필요)3. 캐시 / 아티팩트
# GitLab: 내장 캐시 + 아티팩트
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- node_modules/
- .npm/
artifacts:
paths:
- dist/
expire_in: 7 days// Jenkins: 플러그인 또는 수동 구현
steps {
// S3나 공유 볼륨에 수동으로 저장
sh 'tar czf node_modules.tar.gz node_modules'
s3Upload(bucket: 'my-cache', path: "cache/${env.BRANCH_NAME}/node_modules.tar.gz")
}4. 환경 및 배포 추적
GitLab은 Environments 기능이 내장되어 있어 어느 버전이 어느 환경에 배포됐는지 UI에서 바로 확인할 수 있다. Jenkins는 별도 플러그인이나 외부 도구 없이는 이 기능이 없다.
선택 가이드
GitLab CI/CD가 적합한 경우
- 이미 GitLab을 저장소로 사용 중
- 팀이 작거나 DevOps 전담 인력이 없음
- 빠른 CI/CD 구축이 우선
- Container Registry, CD 환경 추적 등 통합 기능이 필요
- GitLab.com 사용 시 서버 운영 부담 없음
Jenkins가 적합한 경우
- 온프레미스 환경 (인터넷 연결 제한)
- GitHub, Bitbucket 등 다양한 저장소 연동 필요
- 복잡한 빌드 로직, 레거시 시스템 연동
- 기존 Jenkins 파이프라인 자산이 있는 팀
- 세밀한 인프라 제어가 필요
마이그레이션 고려 시
Jenkins → GitLab CI/CD 마이그레이션 시 주요 매핑:
| Jenkins | GitLab CI/CD |
|---|---|
Jenkinsfile | .gitlab-ci.yml |
stage() | stages: + stage: |
agent { docker {} } | image: |
credentials() | GitLab CI/CD Variables (Settings → CI/CD) |
when { branch 'main' } | rules: - if: $CI_COMMIT_BRANCH == "main" |
input {} | when: manual |
parallel {} | 같은 stage에 여러 job |
정리
두 도구 모두 성숙한 CI/CD 솔루션이다. 핵심 차이는 플랫폼 통합 수준과 운영 부담이다.
GitLab CI/CD는 "이미 있는 환경에서 바로 쓰는" 도구, Jenkins는 "무엇이든 커스터마이징 가능한 파워툴"에 가깝다. 신규 프로젝트라면 GitLab CI/CD 또는 GitHub Actions 같은 플랫폼 통합 CI/CD로 시작하는 것이 빠르고, 레거시 환경이나 복잡한 온프레미스 요구사항이 있다면 Jenkins를 선택하는 것이 현실적이다.
Related Posts
같이 읽으면 좋은 글
Jenkins 기술 연구 — CI/CD 파이프라인 구축 가이드
Jenkins의 핵심 개념과 Declarative Pipeline 작성법, Docker 빌드·배포 자동화까지 실무에서 바로 쓸 수 있는 내용을 정리했다.
Docker 개념 정리 — 컨테이너부터 Dockerfile까지
VM과 컨테이너의 차이, 이미지·컨테이너·레지스트리 구조, Dockerfile 작성 방법까지 Docker 핵심 개념을 정리했다.
Kubernetes 개념 정리 — Pod부터 Service까지
컨테이너 오케스트레이션이 왜 필요한지, Kubernetes의 핵심 오브젝트(Pod, Deployment, Service, Ingress)를 실제 예시와 함께 정리했다.