Use Cases (업데이트: 2026. 6. 1.)

Claude Code × AWS CodePipeline 입문: stage, artifact, 승인, 안전 배포

Claude Code로 AWS CodePipeline을 설계합니다. stage/action/artifact, CodeBuild, 승인, S3, Lambda, 장애 확인까지 정리합니다.

Claude Code × AWS CodePipeline 입문: stage, artifact, 승인, 안전 배포

“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";
import * as ecs from "aws-cdk-lib/aws-ecs";

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"}]

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


Source-Build-Test-Deploy 최소 구조부터 정한다

초보자에게 CodePipeline은 릴리스 작업을 순서대로 흘려보내는 컨베이어 벨트라고 설명하는 편이 쉽습니다. pipeline은 전체 흐름, stage는 Source나 Build 같은 구간, action은 그 구간에서 실행되는 한 작업, artifact는 다음 작업으로 넘기는 결과물입니다. GitHub에서 가져온 소스는 SourceOutput, CodeBuild가 만든 dist나 zip은 BuildOutput이 됩니다.

AWS의 CodePipeline concepts도 같은 구조를 설명합니다. Claude Code에 요청할 때 이 네 단어를 명확히 쓰면, 너무 넓은 IAM이나 이상한 artifact 연결이 줄어듭니다.

첫 파이프라인은 Source -> Build -> Test -> Approve -> Deploy 정도면 충분합니다. AWS 생성 가이드에 따르면 파이프라인에는 Source stage와 Build 또는 Deploy stage가 최소로 필요합니다. 운영 배포 앞에 Manual approval을 넣으면, 실수로 바로 운영에 나가는 일을 줄일 수 있습니다.

aws codepipeline create-pipeline --cli-input-json file://pipeline.json
aws codepipeline get-pipeline-state --name webapp-main
aws codepipeline start-pipeline-execution --name webapp-main

S3/CloudFront와 Lambda 배포 예시

정적 사이트는 CodeBuild가 dist를 만들고, S3 deploy action이 bucket에 펼치는 구조가 단순합니다. CloudFront invalidation은 별도 CodeBuild action이나 Lambda invoke action으로 빼면 그래프가 읽기 쉬워집니다. Lambda는 CodeBuild에서 패키징하고 CloudFormation으로 배포하는 흐름이 안전합니다.

version: 0.2

env:
  variables:
    AWS_REGION: ap-northeast-1
    S3_BUCKET: my-webapp-prod
    CLOUDFRONT_DISTRIBUTION_ID: E1234567890ABC

phases:
  install:
    runtime-versions:
      nodejs: 20
    commands:
      - npm ci
  pre_build:
    commands:
      - npm test
      - npm run lint
  build:
    commands:
      - npm run build
  post_build:
    commands:
      - aws s3 sync ./dist s3://$S3_BUCKET/ --delete --cache-control "public,max-age=300"
      - aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths "/*"

artifacts:
  base-directory: dist
  files:
    - "**/*"

실전 예시는 세 가지로 나누면 좋습니다. Astro나 Next.js 정적 사이트를 S3/CloudFront에 배포하는 경우, API Lambda를 CloudFormation으로 갱신하는 경우, staging은 자동이지만 production은 승인 stage를 통과시키는 팀 운영입니다. 같은 stage에 다 넣지 말고 artifact 이름과 책임을 나누면 나중에 고치기 쉽습니다.

실패하면 pipeline 전체가 아니라 action부터 본다

Source 실패는 connection ARN, branch, artifact format을 봅니다. Build 실패는 CodeBuild log, buildspec, 환경 변수, IAM을 봅니다. Deploy 실패는 input artifact 이름, S3 bucket 권한, CloudFormation role, Lambda package 경로, region 불일치를 의심합니다.

aws codepipeline get-pipeline-state --name webapp-main
aws codepipeline list-action-executions --pipeline-name webapp-main --max-results 5
aws logs tail /aws/codebuild/webapp-build --since 30m --follow

자주 나는 실패는 BuildOutput을 만들었는데 Deploy에서 SourceOutput을 읽는 경우입니다. 다음은 CodeBuild service role에 S3, CloudFront, CloudFormation, Lambda 권한이 모자란 경우입니다. 세 번째는 secret을 평문 환경 변수에 둔 경우입니다. AWS actions guide는 Source, Build, Test, Deploy, Approval, Invoke action을 구분하므로 권한도 action 단위로 검토해야 합니다.

Claude Code에 안전하게 맡기는 프롬프트

이 저장소에 AWS CodePipeline + CodeBuild CI/CD를 추가하세요.
목표: GitHub main을 Source로 사용하고, CodeBuild에서 npm ci/test/build를 실행하며, smoke test는 별도 action으로 분리합니다. Production 앞에는 Manual approval을 넣고, dist는 S3에 배포한 뒤 CloudFront invalidation을 실행합니다.
제약: AdministratorAccess 금지, 넓은 wildcard IAM 금지, 승인 없는 운영 배포 금지, secret 평문 환경 변수 금지, 기존 pipeline과 bucket 삭제 금지.
산출물: buildspec.yml, pipeline.json 또는 CDK stack, 실패 확인 명령, README 운영 절차.
검증: 변경 전 현재 구조 설명, diff 제시, aws codepipeline get-pipeline-state와 CodeBuild log 확인법 문서화.

이 프롬프트는 Create a pipeline, stages, and actionsDefine CI/CD pipelines의 흐름에 맞춥니다. Claude Code가 어떤 공식 개념을 기준으로 만들었는지 설명하게 하면 리뷰가 훨씬 쉬워집니다.

Masa식 검증 메모와 다음 단계

Masa식으로 기록하면, 가장 효과가 컸던 것은 artifact 이름을 고정하는 일이었습니다. SourceOutput, BuildOutput, TestOutput만 명확해도 어디서 실패했는지 빨리 보입니다. 처음부터 전부 CDK로 숨기지 말고, 첫 번째는 콘솔이나 JSON으로 화면과 구조를 맞춰 본 뒤 CDK화하는 편이 이해가 빠릅니다.

이 주제는 AWS IAM 가이드, AWS S3 입문, AWS Lambda 가이드와 이어집니다. 개인 학습은 무료 PDF로 충분하지만, 팀 CI/CD는 buildspec, IAM, 승인, 롤백, 장애 대응까지 함께 설계해야 하므로 Claude Code 교육 및 상담에서 이어가면 좋습니다.

정리

태스크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
무료

무료 PDF: Claude Code 치트시트

이메일을 입력하면 명령, 리뷰 습관, 안전한 워크플로를 정리한 PDF를 받을 수 있습니다.

개인정보를 안전하게 관리하며 스팸을 보내지 않습니다.

Masa

작성자 소개

Masa

Claude Code 실무 워크플로와 팀 도입을 검증하는 엔지니어입니다.