Use Cases

Claude Code × AWS CodePipeline/CodeBuild 완전 가이드 | CI/CD 파이프라인 자동 구축

Claude Code로 AWS CodePipeline·CodeBuild CI/CD를 자동 구축. 파이프라인 설계·buildspec.yml 생성·테스트 자동화·CDK 인프라 정의까지 실전 코드로 해설.

“GitHub Actions로 충분한데 왜 굳이 AWS CodePipeline을 써야 해?”—자주 받는 질문입니다.

답은 AWS 리소스와의 깊은 통합에 있습니다. ECR 푸시, ECS 배포, CloudFormation 스택 업데이트—이 모든 것을 AWS 네이티브로 완결하고 싶을 때 CodePipeline + CodeBuild 조합이 가장 원활합니다.

저는 업무에서 여러 AWS 서비스를 조합한 파이프라인을 관리하는데, Claude Code에 파이프라인 요건을 전달하기만 하면 buildspec.yml·CDK 코드·IAM 정책이 한꺼번에 생성되기 시작한 이후로 신규 파이프라인 구축 시간이 1/4로 줄었습니다.


CodePipeline / CodeBuild 기본 구조

CodePipeline (오케스트레이터)
    │
    ├─ Source 스테이지:  GitHub / CodeCommit에서 코드 취득
    ├─ Build 스테이지:   CodeBuild로 빌드·테스트·Docker 이미지 생성
    ├─ Test 스테이지:    통합 테스트·보안 스캔 (옵션)
    └─ Deploy 스테이지:  ECS / Elastic Beanstalk / S3에 배포

CodeBuild는 buildspec.yml에 기술한 명령을 실행합니다. GitHub Actions의 steps:에 해당하는 것으로 이해하면 쉽습니다.


Step 1: buildspec.yml 자동 생성

claude -p "
다음 조건으로 CodeBuild의 buildspec.yml을 생성해.

【빌드 내용】
- Node.js 20 환경
- npm ci로 설치
- TypeScript 빌드 (npm run build)
- 유닛 테스트 실행 (npm test)
- Docker 이미지 빌드 후 ECR에 푸시
- 이미지 태그: CODEBUILD_RESOLVED_SOURCE_VERSION (Git SHA)
- latest 태그도 동시에 부여

【보안 스캔】
- ECR 이미지 푸시 후 Trivy로 스캔
- HIGH/CRITICAL 취약점 있으면 빌드 실패

【아티팩트】
- imagedefinitions.json 출력 (ECS 배포용)
"

생성되는 buildspec.yml:

version: 0.2

env:
  variables:
    AWS_DEFAULT_REGION: ap-northeast-2
    ECR_REPO_NAME: myapp
  parameter-store:
    ECR_REGISTRY: /myapp/ecr-registry

phases:
  install:
    runtime-versions:
      nodejs: 20
    commands:
      - echo "의존성 설치 중..."
      - npm ci

  pre_build:
    commands:
      - echo "테스트 실행 중..."
      - npm test
      - echo "Amazon ECR에 로그인 중..."
      - aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_REGISTRY
      - IMAGE_TAG=$CODEBUILD_RESOLVED_SOURCE_VERSION
      - IMAGE_URI=$ECR_REGISTRY/$ECR_REPO_NAME:$IMAGE_TAG

  build:
    commands:
      - echo "TypeScript 빌드 중..."
      - npm run build
      - echo "Docker 이미지 빌드 중..."
      - docker build -t $IMAGE_URI -t $ECR_REGISTRY/$ECR_REPO_NAME:latest .

  post_build:
    commands:
      - echo "ECR에 이미지 푸시 중..."
      - docker push $IMAGE_URI
      - docker push $ECR_REGISTRY/$ECR_REPO_NAME:latest
      - echo "이미지 취약점 스캔 중..."
      - |
        docker run --rm \
          -v /var/run/docker.sock:/var/run/docker.sock \
          aquasec/trivy:latest image \
          --exit-code 1 \
          --severity HIGH,CRITICAL \
          $IMAGE_URI
      - echo "imagedefinitions.json 생성 중..."
      - printf '[{"name":"app","imageUri":"%s"}]' $IMAGE_URI > imagedefinitions.json

artifacts:
  files:
    - imagedefinitions.json

reports:
  test-reports:
    files:
      - "coverage/junit.xml"
    file-format: JUNITXML

Step 2: CDK로 파이프라인 전체 구축

claude -p "
lib/pipeline-stack.ts에 다음 CodePipeline을 CDK TypeScript로 구현해.

【파이프라인 구성】
- Source: GitHub (owner/repo의 main 브랜치)
- Build: CodeBuild (위의 buildspec.yml 사용)
- Deploy: ECS 서비스에 Blue/Green 배포

【알림】
- 파이프라인 실패 시 SNS → Slack으로 알림
- 배포 성공 시에도 Slack으로 알림

【아티팩트 스토어】
- S3 버킷 (암호화·버전 관리 활성화)
"
// lib/pipeline-stack.ts
import * as cdk from "aws-cdk-lib";
import * as codepipeline from "aws-cdk-lib/aws-codepipeline";
import * as codepipeline_actions from "aws-cdk-lib/aws-codepipeline-actions";
import * as codebuild from "aws-cdk-lib/aws-codebuild";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as iam from "aws-cdk-lib/aws-iam";
import * as sns from "aws-cdk-lib/aws-sns";

export class PipelineStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // 아티팩트 스토어 S3
    const artifactBucket = new s3.Bucket(this, "ArtifactBucket", {
      versioned: true,
      encryption: s3.BucketEncryption.S3_MANAGED,
      removalPolicy: cdk.RemovalPolicy.RETAIN,
    });

    // 아티팩트 정의
    const sourceOutput = new codepipeline.Artifact("SourceOutput");
    const buildOutput = new codepipeline.Artifact("BuildOutput");

    // CodeBuild 프로젝트
    const buildProject = new codebuild.PipelineProject(this, "BuildProject", {
      buildSpec: codebuild.BuildSpec.fromSourceFilename("buildspec.yml"),
      environment: {
        buildImage: codebuild.LinuxBuildImage.STANDARD_7_0,
        privileged: true,  // Docker 빌드에 필수
      },
      environmentVariables: {
        AWS_ACCOUNT_ID: { value: this.account },
      },
    });

    // ECR 접근 권한 부여
    buildProject.addToRolePolicy(new iam.PolicyStatement({
      actions: [
        "ecr:GetAuthorizationToken",
        "ecr:BatchCheckLayerAvailability",
        "ecr:PutImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload",
      ],
      resources: ["*"],
    }));

    // 파이프라인
    const pipeline = new codepipeline.Pipeline(this, "Pipeline", {
      pipelineName: "myapp-pipeline",
      artifactBucket,
      stages: [
        {
          stageName: "Source",
          actions: [
            new codepipeline_actions.GitHubSourceAction({
              actionName: "GitHub_Source",
              owner: "your-org",
              repo: "your-repo",
              branch: "main",
              oauthToken: cdk.SecretValue.secretsManager("github-token"),
              output: sourceOutput,
            }),
          ],
        },
        {
          stageName: "Build",
          actions: [
            new codepipeline_actions.CodeBuildAction({
              actionName: "Build_and_Test",
              project: buildProject,
              input: sourceOutput,
              outputs: [buildOutput],
            }),
          ],
        },
        {
          stageName: "Deploy",
          actions: [
            new codepipeline_actions.EcsDeployAction({
              actionName: "Deploy_to_ECS",
              service: ecs.FargateService.fromFargateServiceAttributes(
                this, "EcsService", {
                  cluster: ecs.Cluster.fromClusterArn(
                    this, "Cluster",
                    `arn:aws:ecs:${this.region}:${this.account}:cluster/myapp-cluster`
                  ),
                  serviceName: "myapp-service",
                }
              ),
              input: buildOutput,
            }),
          ],
        },
      ],
    });

    // 실패 알림
    const alertTopic = new sns.Topic(this, "AlertTopic");
    pipeline.notifyOnAnyStageStateChange("PipelineNotification", alertTopic, {
      events: [
        codepipeline.PipelineNotificationEvents.PIPELINE_EXECUTION_FAILED,
        codepipeline.PipelineNotificationEvents.PIPELINE_EXECUTION_SUCCEEDED,
      ],
    });
  }
}

Step 3: 테스트 결과 리포트 설정

claude -p "
CodeBuild에서 테스트 결과를 CodeBuild Reports에 전송해
PR마다 품질 리포트를 확인할 수 있도록 하고 싶어.

- 테스트 프레임워크: Vitest
- 커버리지 리포트: Istanbul (lcov 형식)
- buildspec.yml에 reports 섹션 추가
- CDK로 리포트 그룹도 정의
"
# buildspec.yml의 reports 섹션
reports:
  UnitTestResults:
    files:
      - "test-results/junit.xml"
    file-format: JUNITXML
  CodeCoverage:
    files:
      - "coverage/lcov.info"
    file-format: CLOVERXML

Step 4: 멀티 환경 파이프라인 설계

claude -p "
dev → staging → prod 3개 환경으로의 단계 배포 파이프라인을 CDK로 설계해.

- dev: main 브랜치에 push하면 자동 배포
- staging: dev 배포 성공 후, 수동 승인 후 배포
- prod: staging 배포 성공 후, 수동 승인 후 배포
- 각 환경 배포 완료를 Slack에 알림
"
// staging → prod 수동 승인 게이트 추가
{
  stageName: "Approve_Staging",
  actions: [
    new codepipeline_actions.ManualApprovalAction({
      actionName: "Approve_Deploy_to_Staging",
      notificationTopic: alertTopic,
      additionalInformation: "Staging 배포를 승인하시겠습니까?",
    }),
  ],
},
{
  stageName: "Deploy_Staging",
  actions: [
    new codepipeline_actions.EcsDeployAction({
      actionName: "Deploy_to_Staging",
      service: stagingService,
      input: buildOutput,
    }),
  ],
},

주의할 함정 4가지

1. CodeBuild의 privileged: true를 잊는 경우

Docker 이미지를 빌드하려면 privileged: true가 필수입니다. 없으면 Cannot connect to the Docker daemon 에러가 납니다.

2. GitHub OAuth 토큰 권한 부족

GitHub 소스에는 repo 스코프가 필요합니다. public_repo만으로는 프라이빗 리포지토리에 사용할 수 없습니다.

3. S3 아티팩트 버킷 리전

파이프라인과 아티팩트 S3 버킷은 같은 리전이어야 합니다. 크로스 리전 파이프라인은 별도 설정이 필요합니다.

4. ECS 배포 액션의 imagedefinitions.json 형식

ECS 배포에는 정확한 형식이 필요합니다:

[{"name": "컨테이너명", "imageUri": "이미지URI"}]

컨테이너 이름은 태스크 정의의 컨테이너 이름과 완전히 일치해야 합니다.


정리

태스크Claude Code의 기여
buildspec.yml 생성빌드·테스트·Docker·보안 스캔 포함해서 생성
CDK 파이프라인Source→Build→Deploy 전 스테이지 자동 생성
멀티 환경 설계수동 승인 게이트 포함한 단계 배포 설계
테스트 리포트CodeBuild Reports 설정 자동화

CodePipeline 설정은 복잡해 보이지만, Claude Code에 “이런 파이프라인이 필요해”라고 전달하기만 하면 buildspec.yml도 CDK 코드도 한꺼번에 갖춰집니다. 먼저 buildspec.yml부터 시도해 보세요.

관련 기사

참고 자료

#claude-code #aws #codepipeline #codebuild #cicd #devops

Claude Code 워크플로우를 한 단계 업그레이드하세요

지금 바로 Claude Code에 복사해 쓸 수 있는 검증된 프롬프트 템플릿 50선.

무료 제공

무료 PDF: 5분 완성 Claude Code 치트시트

이메일 주소만 등록하시면 A4 한 장짜리 치트시트 PDF를 즉시 보내드립니다.

개인정보는 엄격하게 관리하며 스팸은 보내지 않습니다.

Masa

이 글을 작성한 사람

Masa

Claude Code를 적극 활용하는 엔지니어. 10개 언어, 2,000페이지 이상의 테크 미디어 claudecode-lab.com을 운영 중.