목록으로 가기

GitHub Actions와 GitLab CI/CD 파이프라인 구성 방법

CI/CD 개념, 파이프라인 구조, GitHub Actions와 GitLab CI/CD 설정, 환경 분리, Secrets 관리까지 정리했습니다.

GitHub Actions와 GitLab CI/CD 파이프라인 구성 방법 ko posts cicd CI/CD 개념, 파이프라인 구조, GitHub Actions와 GitLab CI/CD 설정, 환경 분리, Secrets 관리까지 정리했습니다.

개요

CI/CD는 코드를 변경하면 자동으로 빌드, 테스트, 배포까지 이어지게 만드는 자동화 파이프라인입니다.

이 글에서는 도구에 상관없이 공통으로 알아야 할 CI/CD 개념, 파이프라인 구조, 환경 분리, Secrets 관리를 정리합니다.

1. CI와 CD는 뭐가 다른가

정리 보기

CI (Continuous Integration) — 지속적 통합

개발자가 코드를 push하면 자동으로:

  • 빌드 (컴파일, 이미지 생성)
  • 테스트 (유닛, 통합)
  • 정적 분석 (린트, 보안 스캔)

“코드가 깨지지 않았는지 매번 확인하는 것"입니다.

CD (Continuous Delivery / Deployment) — 지속적 전달/배포

CI를 통과하면 자동으로:

  • 스테이징 환경에 배포
  • (승인 후) 프로덕션 배포
용어 차이
Continuous Delivery 프로덕션 배포 전에 수동 승인 필요
Continuous Deployment 승인 없이 자동으로 프로덕션까지 배포

두 용어의 차이는 프로덕션 배포에 사람의 승인이 들어가는지 여부입니다. Continuous Delivery는 프로덕션 배포를 수동 승인으로 두고, Continuous Deployment는 승인 없이 자동 배포합니다.

전체 흐름

개발자 push
  → CI: 빌드 → 테스트 → 이미지 생성 → Registry push
  → CD: dev 자동 배포 → stg 자동 배포 → prod 수동 승인 후 배포

2. 파이프라인 구조

정리 보기

파이프라인 = 스테이지의 연속

┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐
│  Build   │ → │   Test   │ → │  Deploy  │ → │  Notify  │
│  (빌드)   │   │  (테스트)  │   │  (배포)   │   │  (알림)   │
└──────────┘   └──────────┘   └──────────┘   └──────────┘

각 스테이지는 이전 스테이지가 성공해야 실행됩니다. 하나라도 실패하면 파이프라인 중단.

일반적인 스테이지 구성

스테이지 하는 일 예시
Checkout 코드 가져오기 git clone
Build 빌드/컴파일 npm run build, docker build
Test 테스트 실행 pytest, jest
Lint 코드 품질 검사 eslint, flake8
Scan 보안 취약점 스캔 trivy, snyk
Push 이미지를 Registry에 업로드 docker push
Deploy 환경에 배포 kubectl apply, helm upgrade
Notify 결과 알림 Slack, 이메일

트리거 — 언제 실행되냐

트리거 동작
push 특정 브랜치에 push하면 실행
merge request / PR MR 생성/업데이트 시 실행
schedule 정해진 시간에 실행 (야간 빌드)
manual 버튼 클릭 시 실행 (프로덕션 배포)
tag 태그 생성 시 실행 (릴리즈)

3. 환경 분리 (dev / stg / prod)

정리 보기

왜 분리하냐

  • 환경마다 데이터와 설정이 다르므로 검증 결과가 달라질 수 있음
  • 환경별로 DB, API 주소, 설정이 다름

일반적인 환경 구성

환경 용도 배포 방식
dev 개발자가 자유롭게 테스트 push하면 자동 배포
stg (staging) 프로덕션과 동일 환경에서 최종 검증 dev 통과 후 자동 or 수동
prod (production) 실제 사용자가 쓰는 환경 수동 승인 후 배포

브랜치 전략과 연결

feature/* → develop 브랜치 → dev 환경 자동 배포
develop → main(또는 release) 브랜치 → stg 환경 배포
main + 태그 → prod 환경 배포 (수동 승인)

환경별 설정 분리 방법

방법 1: 환경변수로 분리
  - dev: DB_HOST=dev-db.internal
  - prod: DB_HOST=prod-db.internal

방법 2: 설정 파일 분리
  - config/dev.yaml
  - config/prod.yaml

방법 3: Helm values 분리 (K8s)
  - values-dev.yaml
  - values-prod.yaml

4. Secrets 관리

정리 보기

Secrets = DB 비밀번호, API 키, 인증서처럼 저장소와 분리해 관리하는 값

코드에 하드코딩하면:

  • Git 히스토리에 영구 기록
  • 레포 접근 가능한 사람 전부 볼 수 있음
  • 커밋 기록에서 값을 제거하려면 히스토리 재작성이 필요함

도구별 Secrets 관리

도구 방법
Jenkins Credentials 메뉴에서 등록 → Jenkinsfile에서 참조
GitLab CI Settings > CI/CD > Variables에서 등록
GitHub Actions Settings > Secrets and variables > Actions에서 등록 (레포/환경/조직 단위)
K8s Secret 오브젝트 or 외부 연동

GitHub Actions에서는 ${{ secrets.NAME }}으로 참조하고, 워크플로가 fork된 레포에서 트리거된 경우 GITHUB_TOKEN을 제외한 시크릿은 러너로 전달되지 않습니다. 클라우드 자격증명이라면 OIDC를 지원하는 클라우드 제공자에 직접 인증해서 장기 시크릿 저장을 없앨 수 있습니다.

외부 Secrets Manager

도구 특징
AWS Secrets Manager 시크릿 자동 교체(rotation) 지원, AWS SDK/서비스에서 직접 조회
AWS Parameter Store 키-값 저장. 표준 티어는 추가 비용 없이 계정·리전당 10,000개, 값 최대 4KB. advanced 티어는 100,000개, 8KB이며 과금 대상
HashiCorp Vault 온프레미스·클라우드·하이브리드 환경 모두 대상. 중앙화된 시크릿 관리와 정책 기반 접근 제어, 모든 접근을 감사 로그로 남김

5. 도구 비교 — Jenkins vs GitLab CI

정리 보기
항목 Jenkins GitLab CI
설치 별도 서버 필요 (직접 운영) GitLab에 내장 (서버 불필요)
설정 파일 Jenkinsfile .gitlab-ci.yml
실행 환경 Controller가 Agent(Node)에 작업 분배 Runner (Docker/Kubernetes 등 executor)
확장 방식 플러그인 설치로 기능 추가 내장 기능 + 컴포넌트
UI 웹 대시보드 GitLab UI 통합
확장성 Agent 추가로 확장 Runner 추가로 확장
설정 언어 Groovy 기반 Jenkinsfile YAML 기반 .gitlab-ci.yml

Jenkins 용어는 controller와 agent입니다. 예전에 쓰인 master/slave 표기는 같은 대상을 가리키는 옛 표기입니다.

언제 뭘 쓰냐

상황 선택
회사가 GitLab 쓰고 있음 GitLab CI
레거시 시스템 + 복잡한 빌드 Jenkins
GitHub 쓰는 오픈소스/개인 GitHub Actions

6. 파이프라인 구성

정리 보기

파이프라인 실행 시간

  • 스테이지는 순차 실행이므로 스테이지가 늘어나면 전체 실행 시간도 늘어남
  • GitHub Actions와 GitLab CI 모두 의존성·빌드 산출물 캐시 기능을 제공함 (npm cache, Docker layer cache)
  • 테스트를 여러 Job으로 나누면 Job은 병렬로 실행됨

실패 알림

  • 스테이지가 실패하면 파이프라인이 중단되고, 실패한 Job과 로그가 도구 UI에 남음
  • GitLab CI는 파이프라인 결과를 이메일과 Slack 등으로 알리는 통합을 제공하고, GitHub Actions는 워크플로 실행 결과를 알림 설정과 API로 전달함

멱등성

  • 같은 코드로 같은 파이프라인 돌리면 같은 결과
  • 컨테이너 이미지로 빌드 환경을 고정하면 러너 호스트의 설치 상태에 따른 차이가 줄어듦

롤백과 이미지 태그

  • 이미지 태그를 git commit SHA로 지정하면 태그와 코드 리비전이 1:1로 대응함
  • 릴리즈 태그를 쓰면 배포된 버전이 어느 릴리즈인지 태그로 식별됨
이미지 태그 예시:
  myapp:abc123f  (commit SHA 앞 7자리)
  myapp:v1.2.3   (릴리즈 태그)

시크릿과 이미지

  • GitLab CI의 masked variable과 GitHub Actions의 시크릿은 Job 로그에 값이 그대로 출력되지 않도록 마스킹됨
  • 멀티 스테이지 빌드에서 최종 이미지에는 마지막 스테이지에 복사한 파일만 포함되므로 빌드 단계의 소스 코드는 남지 않음

7. 파이프라인 디버깅

정리 보기

디버깅 방법

  • Jenkins: Replay 기능으로 커밋하지 않고 스크립트를 고쳐서 다시 실행 가능
  • GitLab CI: 특정 Job만 retry 가능
  • GitLab CI: 파이프라인 에디터의 Validate 탭에서 CI Lint로 문법·로직 검증, “Simulate pipeline creation"으로 needs·rules 관련 문제까지 확인 가능. 파이프라인 에디터는 문법을 자동으로 검증합니다.
  • 예전에 로컬 실행에 쓰던 gitlab-runner exec는 deprecated된 뒤 제거되어, 현재 GitLab Runner 공식 명령 목록에 없습니다.
  • Jenkins: CLI/HTTP POST로 Declarative Pipeline을 실행 전에 lint할 수 있습니다.
  • GitHub Actions는 커뮤니티 도구 act로 로컬 실행을 시도해볼 수 있습니다 (공식 도구 아님)