CI/CD 완벽 가이드: 현대적인 소프트웨어 개발 파이프라인 구축하기
들어가며
지속적 통합(Continuous Integration, CI)과 지속적 배포(Continuous Delivery/Deployment, CD)는 현대 소프트웨어 개발의 핵심 프랙티스입니다. 이 가이드에서는 CI/CD의 개념부터 실제 구현까지 상세히 다루겠습니다.
1. CI/CD 기본 개념
1.1 지속적 통합(CI)
- 코드 변경사항의 정기적 통합
- 자동화된 빌드 및 테스트
- 품질 관리 자동화
1.2 지속적 배포(CD)
- Continuous Delivery: 수동 승인 후 배포
- Continuous Deployment: 완전 자동화된 배포
- 안정적이고 빠른 제품 출시
2. CI/CD 파이프라인 구성요소
2.1 버전 관리
# Git 기본 워크플로우
git checkout -b feature/new-feature
git add .
git commit -m "feat: add new feature"
git push origin feature/new-feature
2.2 자동화된 빌드
# GitHub Actions 빌드 설정 예시
name: Build Application
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK
uses: actions/setup-java@v2
with:
java-version: '11'
- name: Build with Maven
run: mvn clean install
2.3 자동화된 테스트
// Jest 테스트 예시
describe('User Authentication', () => {
test('should login with valid credentials', async () => {
const response = await auth.login({
username: 'testuser',
password: 'testpass'
});
expect(response.status).toBe(200);
expect(response.data.token).toBeDefined();
});
});
2.4 코드 품질 검사
# SonarQube 설정 예시
sonar.projectKey=my-project
sonar.sources=src
sonar.tests=test
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.coverage.exclusions=**/*.test.js
3. 주요 CI/CD 도구
3.1 Jenkins 파이프라인
// Jenkinsfile 예시
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'npm install'
sh 'npm run build'
}
}
stage('Test') {
steps {
sh 'npm run test'
}
}
stage('Deploy') {
when {
branch 'main'
}
steps {
sh './deploy.sh'
}
}
}
post {
always {
junit '**/test-results.xml'
cleanWs()
}
}
}
3.2 GitHub Actions
# GitHub Actions 워크플로우 예시
name: CI/CD Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: |
echo "${{ secrets.DEPLOY_KEY }}" > deploy_key
chmod 600 deploy_key
ssh -i deploy_key user@server './deploy.sh'
3.3 GitLab CI/CD
# .gitlab-ci.yml 예시
image: node:14
stages:
- build
- test
- deploy
build:
stage: build
script:
- npm install
- npm run build
artifacts:
paths:
- dist/
test:
stage: test
script:
- npm run test
coverage: '/Coverage: \d+.\d+%/'
deploy:
stage: deploy
script:
- apt-get update -qy
- apt-get install -y ruby-dev
- gem install dpl
- dpl --provider=heroku --app=my-app --api-key=$HEROKU_API_KEY
only:
- main
4. 배포 전략
4.1 블루-그린 배포
# Kubernetes Blue-Green 배포 예시
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-blue
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: blue
template:
metadata:
labels:
app: myapp
version: blue
spec:
containers:
- name: myapp
image: myapp:1.0
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-green
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: green
template:
metadata:
labels:
app: myapp
version: green
spec:
containers:
- name: myapp
image: myapp:2.0
4.2 카나리 배포
# Istio 카나리 배포 예시
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp.com
http:
- route:
- destination:
host: myapp-v1
weight: 90
- destination:
host: myapp-v2
weight: 10
5. 모니터링과 로깅
5.1 로그 수집
# ELK Stack 설정 예시
input {
beats {
port => 5044
}
}
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "app-logs-%{+YYYY.MM.dd}"
}
}
5.2 메트릭 모니터링
# Prometheus 설정 예시
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'spring-actuator'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8080']
6. CI/CD 보안
6.1 보안 스캔
# Docker 이미지 보안 스캔 예시
name: Security Scan
on:
push:
branches: [ main ]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: 'my-docker-image:latest'
format: 'table'
exit-code: '1'
ignore-unfixed: true
severity: 'CRITICAL,HIGH'
6.2 시크릿 관리
# Vault 설정 예시
path "secret/data/myapp/*" {
capabilities = ["read", "list"]
}
path "auth/token/create" {
capabilities = ["create", "update"]
}
7. CI/CD 모범 사례
7.1 파이프라인 최적화
- 병렬 실행 활용
- 캐싱 전략 수립
- 테스트 최적화
7.2 구성 관리
- Infrastructure as Code
- 환경 설정 분리
- 버전 관리
결론
CI/CD는 현대 소프트웨어 개발의 핵심 요소입니다. 효과적인 CI/CD 파이프라인을 구축하고 유지하기 위해서는 도구의 선택부터 보안, 모니터링까지 다양한 측면을 고려해야 합니다. 각 조직의 상황과 요구사항에 맞는 CI/CD 전략을 수립하고, 지속적으로 개선해 나가는 것이 중요합니다.