CI/CD Basics
분류: Layer 5 - 플랫폼 엔지니어링 & 자동화 | 선수지식: Docker Basics
1. 한 줄 정의
섹션 제목: “1. 한 줄 정의”CI/CD는 코드 변경을 자동으로 빌드·테스트(CI)하고, 검증된 코드를 자동으로 서버에 배포(CD)하는 파이프라인이다.
2. 왜 중요한가
섹션 제목: “2. 왜 중요한가”BackOps에서 배포는 일상 업무다. “코드를 머지하면 서버에 반영되기까지 무슨 일이 일어나는지”를 모르면 배포 실패를 진단할 수 없고, 파이프라인 개선도 불가능하다. 플랫폼 엔지니어링의 핵심 축(개발자 경험/DX 개선) 중 배포 자동화가 가장 체감이 큰 영역이다.
3. 핵심 개념
섹션 제목: “3. 핵심 개념”CI (Continuous Integration)
코드를 공유 브랜치에 자주 머지하고, 머지할 때마다 자동으로 빌드·테스트를 실행하는 것.
- PR을 올리면 자동으로 린트, 테스트, 빌드가 돌아감
- 깨진 코드가 메인 브랜치에 들어가는 것을 방지
CD (Continuous Delivery / Deployment)
- Continuous Delivery: 배포 가능한 상태까지 자동화. 실제 배포는 수동 승인.
- Continuous Deployment: 배포까지 완전 자동화. 테스트 통과하면 바로 프로덕션.
파이프라인 기본 흐름
코드 Push/PR → 빌드 → 테스트 → Docker 이미지 생성 → 레지스트리 Push → 배포 CI 영역 CD 영역CI/CD 파이프라인 일반 원칙 — 도구 독립적 사고 모델
GitHub Actions, GitLab CI, Jenkins, CircleCI 등 도구가 달라도 모든 CI/CD는 세 가지 불변 원칙을 공유한다:
- 격리된 환경에서 재현 가능한 빌드: 파이프라인은 매 실행마다 클린 상태에서 시작한다. “내 로컬에서는 됐는데”를 제거하는 것이 핵심 목적. Docker 컨테이너가 이 격리를 보장하는 표준 수단이다.
- 불변 아티팩트 원칙: 빌드 단계에서 생성된 이미지/바이너리는 이후 테스트·스테이징·프로덕션에서 동일한 아티팩트를 사용한다. 환경마다 다시 빌드하면 재현성이 깨진다. (예:
my-app:$GITHUB_SHA태그로 단 하나의 이미지가 모든 환경을 통과) - 파이프라인 as Code: CI 설정 파일(
.yml)을 앱 코드와 동일한 git 저장소에 보관한다. 파이프라인 변경도 PR 리뷰 대상이 되고, 롤백이 가능해진다.
# 도구별 동일 원칙 적용 비교GitHub Actions: runs-on: ubuntu-latest → 매 실행 클린 VMGitLab CI: image: node:20 → 매 Job 클린 컨테이너Jenkins: docker.image('node:20').inside { ... } → 동일GitHub Actions 내부 동작 원리
“.github/workflows/deploy.yml 파일 하나를 올리면 알아서 돌아간다”는 사실 뒤에 이런 흐름이 있다:
- Event 감지: GitHub이
push,pull_request등 이벤트를 감지 - Runner 할당: GitHub이 관리하는 Ubuntu VM(Runner)을 하나 할당
- Workflow 실행: YAML에 정의된 Jobs → Steps 순서대로 실행
- 결과 리포트: 성공/실패를 PR 체크 상태로 표시
Runner는 매 실행마다 새로 초기화되는 격리된 VM이다. 이전 실행의 파일/환경이 남아 있지 않아서 actions/checkout, npm ci 같은 준비 단계가 항상 필요하다.
Runner는 매 실행마다 새로 초기화되므로 이전 실행 결과가 남지 않는다. GitHub은 지속적으로 Runner 성능을 개선 중이며, 캐시를 잘 활용하면 빌드 시간을 크게 단축할 수 있다.
📖 더 보기: GitHub Actions CI/CD in 4 steps — GitHub 공식 블로그의 파이프라인 구축 가이드 (입문)
GitHub Actions — NestJS 배포 실제 예시
name: Deploy NestJS to ECSon: push: branches: [main]
jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" cache: "npm"
- name: Install & Test run: | npm ci npm test
- name: Build Docker image & Push to ECR run: | aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_REGISTRY docker build -t $ECR_REGISTRY/my-app:$GITHUB_SHA . docker push $ECR_REGISTRY/my-app:$GITHUB_SHA env: ECR_REGISTRY: ${{ secrets.ECR_REGISTRY }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Deploy to ECS run: | aws ecs update-service \ --cluster prod \ --service my-app \ --force-new-deployment# GitHub Actions 탭에서 보이는 실행 결과 예시✅ Setup Node.js 3s✅ Install & Test 45s✅ Build Docker image 1m 20s✅ Push to ECR 30s✅ Deploy to ECS 5s총 소요 시간: 2m 43sOIDC 인증 — AWS 자격증명 없이 배포하는 방법
비유하자면, OIDC는 “GitHub Actions가 AWS에게 ‘나 GitHub이야, 이 Repository에서 실행된 워크플로야’라고 신분증을 보여주면, AWS가 임시 통행증을 발급해주는 것”이다. 영구적인 AWS_ACCESS_KEY를 저장하지 않아도 된다.
장기 자격증명(Access Key/Secret Key)을 GitHub Secrets에 저장하면 키 유출 시 무기한으로 악용될 수 있다. OIDC를 사용하면 워크플로 실행마다 수명이 매우 짧은 임시 자격증명이 발급되어, 만료 후에는 자동으로 무효화된다.
# OIDC 기반 AWS 인증 (Access Key 없이 배포)name: Deploy with OIDCon: push: branches: [main]
permissions: id-token: write # OIDC 토큰 발급 권한 contents: read
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Configure AWS Credentials via OIDC uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole aws-region: ap-northeast-2
- name: Push to ECR & Deploy to ECS run: | aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_REGISTRY docker build -t $ECR_REGISTRY/my-app:$GITHUB_SHA . docker push $ECR_REGISTRY/my-app:$GITHUB_SHA aws ecs update-service --cluster prod --service my-app --force-new-deployment# OIDC vs 정적 키 비교정적 AWS 키: GitHub Secrets에 저장 → 유출 시 무기한 악용 가능OIDC 임시 키: 워크플로 실행 시 발급 → 실행 완료 후 자동 만료IAM 신뢰 정책에 특정 Repository와 브랜치만 역할 가정이 가능하도록 제한하면 보안이 더욱 강화된다.
OIDC 임시 자격증명 — 클라우드 공통 패턴
GitHub→AWS OIDC는 특정 도구 조합이 아니라 OIDC Workload Identity Federation이라는 범용 패턴의 구현이다. 세 클라우드 모두 동일한 교환 흐름을 따른다:
[CI 러너] → GitHub OIDC 토큰 발급 (https://token.actions.githubusercontent.com) → 클라우드 STS에 제시 → 클라우드가 신뢰 정책 검증 후 단기 자격증명 발급 (보통 1시간 TTL)| 클라우드 | 메커니즘 | GitHub Actions 설정 |
|---|---|---|
| AWS | IAM OIDC Identity Provider + 역할 신뢰 정책 | aws-actions/configure-aws-credentials |
| GCP | Workload Identity Pool + Provider 구성 | google-github-actions/auth |
| Azure | Entra ID Federated Credentials (서비스 주체) | azure/login with client-id + federated-credential |
공통 보안 원칙: 세 클라우드 모두
subject클레임(예:repo:org/repo:ref:refs/heads/main)으로 특정 저장소·브랜치만 신뢰하도록 제한할 수 있다. 장기 자격증명 없이 CI/CD를 구성하는 것이 2024년 이후 모범 사례다.
파이프라인 속도 최적화 — npm 캐시와 Docker 레이어 캐시
CI 파이프라인이 느리면 개발자 경험이 나빠진다. 두 가지 캐시가 핵심이다:
- npm 캐시:
package-lock.json이 변경되지 않으면node_modules를 재설치하지 않음 - Docker 레이어 캐시:
package.json이 변경되지 않으면npm install레이어를 재실행하지 않음
# npm 캐시 활용 (actions/setup-node에 내장)- uses: actions/setup-node@v4 with: node-version: "20" cache: "npm" # package-lock.json 기반 캐시 키 자동 생성
# Docker 레이어 캐시 활용 (GitHub Actions Cache)- name: Build with cache uses: docker/build-push-action@v5 with: cache-from: type=gha # GitHub Actions 캐시에서 이전 레이어 로드 cache-to: type=gha,mode=max tags: $ECR_REGISTRY/my-app:$GITHUB_SHA push: true# 캐시 적용 전후 비교 (실제 NestJS 프로젝트 기준)npm install (캐시 미적용): 1분 45초npm install (캐시 적용): 8초 ← 93% 단축
Docker build (캐시 미적용): 2분 30초Docker build (캐시 적용): 40초 ← 73% 단축배포 전략
- Rolling: 인스턴스를 하나씩 교체. 가장 기본.
- Blue-Green: 새 버전을 별도 환경에 띄우고, 트래픽을 한 번에 전환. 롤백이 빠름.
- Canary: 새 버전에 트래픽 일부만 먼저 보내서 검증 후 전체 전환.
배포 전략 선택 매트릭스
“어떤 전략을 쓸지”는 팀 규모·SLA·인프라 비용 세 축으로 판단한다. DORA 연구에 따르면 배포 전략이 Change Failure Rate와 MTTR(복구 시간) 양쪽에 직접 영향을 미친다.
| 기준 | Rolling | Blue-Green | Canary |
|---|---|---|---|
| 허용 다운타임 | 없음 (순차 교체) | 없음 (순간 전환) | 없음 (점진적 이동) |
| 롤백 속도 | 느림 (재배포 필요) | 빠름 < 1분 (트래픽 전환) | 중간 (가중치 복구) |
| 인프라 비용 | 낮음 (추가 자원 불필요) | 높음 (2배 환경 필요) | 중간 (일부 추가) |
| 적합 팀 규모 | 소 | 중~대 (10명+) | 대 (전담 옵저버빌리티) |
| SLA 요건 | 99.9% 이하 | 99.95%+ | 99.99% 목표 |
| 적합 서비스 | 내부 도구, 배치 | 결제·인증 (즉시 롤백 필수) | 사용자 facing A/B |
판단 기준: 롤백 1분 이내가 SLA 조건이면 Blue-Green이 강제된다. 인프라 예산이 제한적이면 Rolling이 기본. 새 기능의 비즈니스 임팩트를 실데이터로 검증해야 할 때 Canary가 유일한 선택이다.
배포 전략 심화 — ECS에서 각 전략이 어떻게 동작하는가
비유하자면, Rolling은 “버스를 달리는 중에 좌석을 하나씩 교체”하는 것이고, Blue-Green은 “새 버스를 준비해두고 신호등 바꾸듯 한 번에 전환”하는 것이며, Canary는 “탄광에 새 가스 탐지 카나리아를 먼저 보내보는 것”이다.
ECS Rolling 배포 동작: - maximumPercent: 200, minimumHealthyPercent: 100 설정 - 현재 2개 태스크 실행 중 → 신버전 2개 추가 (총 4개) - 신버전 헬스체크 통과 → 구버전 2개 종료 - 배포 중 구버전과 신버전이 동시에 트래픽 처리
Blue-Green (AWS CodeDeploy 통합): - ECS 서비스에 CodeDeploy AppSpec 연동 - 신버전 태스크셋 생성 → 테스트 리스너(8080)로 검증 - 검증 후 프로덕션 리스너(443) 전환 - 구버전은 설정한 시간(예: 1시간) 후 자동 삭제 - 롤백: 구버전으로 트래픽 전환이 1분 이내 완료
Canary (ALB 가중치 기반): - ALB Target Group 2개 (v1: 90%, v2: 10%) - CloudWatch 지표 이상 감지 시 자동 롤백 트리거 - 단계적 증가: 10% → 25% → 50% → 100%# ECS 배포 설정 확인 — 현재 전략이 뭔지 파악aws ecs describe-services \ --cluster prod \ --services my-app \ --query 'services[0].deploymentConfiguration'
# 예상 출력 (Rolling 배포):# {# "maximumPercent": 200,# "minimumHealthyPercent": 100,# "deploymentCircuitBreaker": {# "enable": true, ← 배포 실패 시 자동 롤백 활성화# "rollback": true# }# }Deployment Circuit Breaker — 배포 중 장애를 자동으로 롤백하는 방법
ECS의 Deployment Circuit Breaker를 활성화하면, 신버전 태스크가 연속으로 헬스체크에 실패할 때 ECS가 자동으로 이전 버전으로 롤백한다. 사람이 모니터링하지 않아도 배포 실패를 자동 감지하고 서비스를 보호한다.
# Terraform으로 Circuit Breaker 활성화resource "aws_ecs_service" "my_app" { name = "my-app" cluster = aws_ecs_cluster.prod.id task_definition = aws_ecs_task_definition.my_app.arn
deployment_circuit_breaker { enable = true # 배포 실패 감지 활성화 rollback = true # 실패 시 이전 버전으로 자동 롤백 }}⚠️ 시크릿 관리 주의
CI/CD 파이프라인에서 AWS 자격증명, API Key 등은 절대 코드에 직접 넣지 않는다. GitHub Secrets, AWS Secrets Manager 등을 통해 환경변수로 주입해야 한다.
Action 버전도 주의가 필요하다. uses: actions/checkout@main처럼 브랜치를 지정하면 외부 의존성에 보안 위협이 생길 수 있다. 반드시 @v4처럼 특정 버전 태그 또는 커밋 SHA를 고정해서 사용해야 한다.
GitHub Environments — 스테이징/프로덕션 배포 분리
GitHub Environments를 사용하면 스테이징과 프로덕션 배포를 안전하게 분리할 수 있다. 환경별로 다른 Secrets, 보호 규칙(Required Reviewers), 배포 조건을 설정할 수 있다.
# .github/workflows/deploy.yml — 환경별 배포 분리jobs: deploy-staging: runs-on: ubuntu-latest environment: staging # staging 환경 Secrets 사용 steps: - name: Deploy to Staging ECS run: | aws ecs update-service --cluster staging --service my-app --force-new-deployment env: AWS_REGION: ${{ secrets.AWS_REGION }} # staging 환경 Secrets ECR_REGISTRY: ${{ secrets.ECR_REGISTRY }}
deploy-production: runs-on: ubuntu-latest needs: deploy-staging # staging 완료 후 실행 environment: production # production 환경 Secrets + 수동 승인 규칙 적용 steps: - name: Deploy to Production ECS run: | aws ecs update-service --cluster prod --service my-app --force-new-deployment# GitHub 환경 보호 규칙 예시 (production 환경)Required reviewers: 2명 승인 필요Wait timer: 5분 대기 후 배포 진행Deployment branch: main 브랜치만 허용이미지 보안 취약점 스캔 — Trivy로 자동화
프로덕션에 취약한 패키지가 포함된 이미지가 배포되는 것을 방지하기 위해 CI 파이프라인에 이미지 스캔을 추가한다.
# CI 파이프라인에 Trivy 이미지 스캔 추가- name: Build Docker image run: docker build -t my-app:${{ github.sha }} .
- name: Scan image with Trivy uses: aquasecurity/trivy-action@master with: image-ref: my-app:${{ github.sha }} format: table exit-code: "1" # CRITICAL 취약점 발견 시 파이프라인 실패 severity: "CRITICAL,HIGH" # CRITICAL, HIGH만 검사# Trivy 스캔 결과 예시┌───────────────┬────────────────┬──────────┬───────────────────┐│ Library │ Vulnerability │ Severity │ Fixed Version │├───────────────┼────────────────┼──────────┼───────────────────┤│ node │ CVE-2023-XXXXX │ CRITICAL │ 20.11.1 ││ express │ CVE-2024-XXXXX │ HIGH │ 4.19.2 │└───────────────┴────────────────┴──────────┴───────────────────┘CRITICAL 취약점 1건 발견 → 파이프라인 중단4. 실무에서 어디에 쓰이나
섹션 제목: “4. 실무에서 어디에 쓰이나”- PR 머지 시 자동 배포 (main 브랜치 → 프로덕션)
- PR 생성 시 자동 테스트/린트 실행
- Docker 이미지 빌드 → ECR Push → ECS 배포 자동화
- 스테이징/프로덕션 환경 분리 배포
5. 현재 내 업무와 연결점
섹션 제목: “5. 현재 내 업무와 연결점”- 배포 파이프라인이 실패했을 때 어느 단계에서 실패했는지 진단해야 함
- 새 서비스 추가 시 CI/CD 파이프라인을 설정해야 함
- 배포 속도 개선 (Docker 레이어 캐시, 병렬 테스트 등)
- 팀의 배포 프로세스를 표준화하는 것이 플랫폼 엔지니어링의 시작
6. 자주 헷갈리는 개념 비교
섹션 제목: “6. 자주 헷갈리는 개념 비교”| 개념 A | 개념 B | 차이점 |
|---|---|---|
| CI | CD | CI는 빌드·테스트 자동화, CD는 배포 자동화 |
| Continuous Delivery | Continuous Deployment | Delivery는 배포 전 수동 승인 필요, Deployment는 완전 자동 |
| Rolling | Blue-Green | Rolling은 점진적 교체, Blue-Green은 한 번에 전환 (롤백이 빠름) |
| GitHub Actions | Jenkins | Actions는 GitHub 네이티브(SaaS), Jenkins는 자체 호스팅(유연하지만 관리 필요) |
| 정적 AWS 키 | OIDC 임시 자격증명 | 정적 키는 유출 위험, OIDC는 워크플로 실행마다 임시 발급 (만료 후 자동 무효화) |
6.5. 트러블슈팅
섹션 제목: “6.5. 트러블슈팅”🔧 워크플로가 실행 안 됨 — 트리거 조건 불일치
섹션 제목: “🔧 워크플로가 실행 안 됨 — 트리거 조건 불일치”증상: 코드를 push했는데 GitHub Actions 탭에 아무것도 안 뜸
원인: on: 트리거 설정이 실제 동작과 불일치. 예: branches: [main]인데 master에 push했거나, 워크플로 파일이 .github/workflows/ 하위에 없음
해결:
# ❌ 잘못된 예: main 브랜치 push에만 반응on: push: branches: [main]
# ✅ PR과 main push 모두 반응하도록 수정on: push: branches: [main] pull_request: branches: [main]파일 위치도 반드시 .github/workflows/deploy.yml 이어야 한다. workflows 폴더 밖에 있으면 무시된다.
🔧 “Error: npm ci” 실패 — package-lock.json 충돌
섹션 제목: “🔧 “Error: npm ci” 실패 — package-lock.json 충돌”증상: CI에서 npm ci 실행 시 에러. 로컬에서는 잘 되는데 Actions에서만 실패
원인: package.json과 package-lock.json이 싱크가 맞지 않거나, package-lock.json이 .gitignore에 포함되어 커밋이 안 된 경우
해결:
# 로컬에서 lock 파일 재생성 후 커밋rm package-lock.jsonnpm installgit add package-lock.jsongit commit -m "chore: regenerate package-lock.json"npm ci는 package-lock.json을 기준으로 설치하므로 lock 파일이 반드시 커밋되어 있어야 한다.
🔧 Docker 이미지 빌드는 성공인데 ECS 배포 후 502
섹션 제목: “🔧 Docker 이미지 빌드는 성공인데 ECS 배포 후 502”증상: GitHub Actions에서 모든 단계가 초록불인데, 배포 후 서비스에 502 응답
원인: 새 태스크 정의가 올바른 이미지 태그를 참조하지 않거나, ECS 서비스의 헬스체크가 새 컨테이너를 비정상으로 판단해서 롤백됨
해결:
- AWS ECS 콘솔 → 해당 서비스 → Events 탭에서 배포 이벤트 확인
- 태스크가
RUNNING상태인지 확인 (→STOPPED이면 컨테이너 자체 에러) - 멈춘 태스크 클릭 → Stopped Reason 확인 (헬스체크 실패 or OOM 등)
- NestJS 앱에
/health엔드포인트가 없으면 추가
// NestJS 헬스체크 엔드포인트 (ECS ALB 헬스체크 대응)@Controller("health")export class HealthController { @Get() check() { return { status: "ok" }; }}🔧 GitHub Actions Secrets가 워크플로에서 빈 값으로 처리됨
섹션 제목: “🔧 GitHub Actions Secrets가 워크플로에서 빈 값으로 처리됨”증상: 워크플로에서 ${{ secrets.AWS_ACCESS_KEY_ID }}를 사용했는데 빈 문자열로 처리되어 AWS 인증 실패
원인 3가지:
- Repository Secrets에 등록하지 않고 Environment Secrets에만 등록한 경우 (environment 지정 없이는 참조 불가)
- Fork된 PR에서 실행하는 경우 — 보안상 외부 기여자의 PR에는 Secrets가 노출되지 않음
- Secrets 이름에 오타 (대소문자 구분 있음)
해결:
# Secrets 디버깅 (값은 마스킹되지만 비어있는지 확인 가능)- name: Check secrets run: | echo "AWS key is set: ${{ secrets.AWS_ACCESS_KEY_ID != '' }}" # 예상 출력: AWS key is set: true (설정된 경우) # 예상 출력: AWS key is set: false (미설정 또는 빈 값)
# Environment Secrets 사용 시 environment 명시 필요jobs: deploy: runs-on: ubuntu-latest environment: production # ← Environment Secrets 사용 시 반드시 명시🔧 CI 파이프라인이 너무 느림 — 매 실행마다 5분 이상 소요
섹션 제목: “🔧 CI 파이프라인이 너무 느림 — 매 실행마다 5분 이상 소요”증상: PR을 올릴 때마다 CI가 5~10분이 걸려 개발 속도가 느려짐. npm install이 매번 전체 재실행됨
원인: npm 캐시와 Docker 레이어 캐시가 설정되지 않아 매 실행마다 전체 의존성을 새로 설치하고 이미지를 처음부터 빌드함
해결:
# npm 캐시 활성화- uses: actions/setup-node@v4 with: node-version: "20" cache: "npm" # ← 이 한 줄로 npm install 90% 단축
# Docker 레이어 캐시 활성화- name: Set up Docker Buildx uses: docker/setup-buildx-action@v3
- name: Build and push uses: docker/build-push-action@v5 with: cache-from: type=gha cache-to: type=gha,mode=max push: true tags: ${{ env.ECR_REGISTRY }}/my-app:${{ github.sha }}# 예상 결과:# 캐시 적용 전: 총 6분 30초# 캐시 적용 후: 총 1분 15초 (80% 단축)7. 체크리스트
섹션 제목: “7. 체크리스트”- CI와 CD의 차이를 설명할 수 있다
- 코드 Push부터 서버 배포까지의 파이프라인 흐름을 설명할 수 있다
- Rolling, Blue-Green, Canary 배포 전략의 차이를 설명할 수 있다
- GitHub Actions 워크플로 파일의 기본 구조를 읽을 수 있다
- 배포 실패 시 어느 단계를 확인해야 하는지 안다
- OIDC가 정적 AWS 키보다 왜 안전한지 설명할 수 있다
8. 추가 학습 키워드
섹션 제목: “8. 추가 학습 키워드”GitHub Actions, ArgoCD, GitOps, Docker 멀티스테이지 빌드, ECR, 배포 롤백, Feature Flag, Trunk-Based Development, OIDC 인증(GitHub → AWS), Trivy 이미지 스캔, GitHub Environments
8.5. 추천 리소스
섹션 제목: “8.5. 추천 리소스”📚 추천 리소스
섹션 제목: “📚 추천 리소스”- 📖 GitHub Actions 공식 문서 — 워크플로 문법, 트리거, 시크릿 관리까지 한국어로 제공되는 공식 레퍼런스 (입문)
- 🎬 GitHub Actions in 45 minutes — TechWorld with Nana — CI/CD 개념부터 GitHub Actions 실습까지 한 번에 정리 (입문)
- 📖 GitHub OIDC with AWS — AWS 공식 블로그 — GitHub Actions에서 OIDC로 AWS IAM 역할을 사용하는 공식 보안 가이드 (중급)
- 📖 GitHub Actions 트러블슈팅 공식 가이드 — 워크플로 실패 디버깅 방법과 디버그 로깅 활성화 방법 (중급)
- 📖 GitHub Actions 2026 Security Roadmap — GitHub Blog — 이그레스 방화벽, Actions Data Stream 등 2026년 보안 강화 계획 (중급)
9. 내가 직접 확인해볼 것
섹션 제목: “9. 내가 직접 확인해볼 것”- 팀 서비스의
.github/workflows/폴더를 열어보고 파이프라인 흐름 파악
# 워크플로 파일 목록 확인ls -la .github/workflows/
# 예상 출력:# -rw-r--r-- 1 user group 1.2K Apr 1 09:00 deploy.yml# -rw-r--r-- 1 user group 890 Apr 1 09:00 test.yml- GitHub Actions 탭에서 최근 배포 로그 확인 (어떤 단계를 거치는지)
# GitHub CLI로 최근 워크플로 실행 상태 확인gh run list --limit 5
# 예상 출력:# STATUS TITLE WORKFLOW BRANCH EVENT ID ELAPSED AGE# ✓ feat: add health check Deploy to ECS main push 12345678 2m43s 2h# ✓ fix: cors config Deploy to ECS main push 12345677 1m55s 5h# ✗ feat: new endpoint Deploy to ECS main push 12345676 45s 1d
# 실패한 워크플로 로그 확인gh run view 12345676 --log-failed- 배포 실패 이력이 있다면 어느 단계에서 실패했는지 확인
- 팀의 배포 전략이 Rolling인지 Blue-Green인지 확인
# AWS CLI로 ECS 서비스 배포 설정 확인aws ecs describe-services \ --cluster prod \ --services my-app \ --query 'services[0].deploymentConfiguration'
# 예상 출력:# {# "maximumPercent": 200,# "minimumHealthyPercent": 100# }# → maximumPercent: 200, minimumHealthyPercent: 100 이면 Rolling 배포# 워크플로에서 OIDC 사용 여부 확인 (팀 파이프라인 분석)grep -r "id-token" .github/workflows/# 출력이 있으면 OIDC 사용 중# 출력이 없으면 정적 AWS 키 사용 중 → 보안 개선 포인트10. 요약 — 이것만 기억해도 된다
섹션 제목: “10. 요약 — 이것만 기억해도 된다”배포 실패 진단 순서
섹션 제목: “배포 실패 진단 순서”파이프라인이 실패했다├── GitHub Actions 탭이 빨간색│ ├── 어느 Step에서 실패했는지 확인│ ├── npm ci 실패 → package-lock.json 싱크 맞는지 확인│ ├── docker build 실패 → Dockerfile 문법/경로 확인│ └── AWS 인증 실패 → Secrets 등록 여부 확인└── 파이프라인은 초록색인데 서비스가 안 됨 ├── ECS 콘솔 → Services → Events 탭 확인 ├── 태스크 STOPPED → Stopped Reason 확인 └── /health 엔드포인트 응답 여부 확인5줄 핵심
섹션 제목: “5줄 핵심”- CI는 코드 변경 시 자동 빌드·테스트, CD는 자동 배포이다
- 파이프라인: 코드 Push → 빌드 → 테스트 → 이미지 생성 → 배포
- 배포 전략(Rolling, Blue-Green, Canary)에 따라 안정성과 속도가 달라진다
- 시크릿은 코드에 넣지 말고 환경변수로 주입해야 하며, OIDC로 정적 키 없이 AWS 인증이 가능하다
- 배포 자동화는 플랫폼 엔지니어링에서 개발자 경험 개선의 핵심이다
최종 수정: 2026-04-01