본문 바로가기

AI 개발

AWS Kiro 3편—AgentCore 연동과 CDK 자동화, 코드 한 줄 없이 서버리스 풀스택 배포까지

반응형

 

스펙 쓰는 법, Steering 아키텍처 잡는 법 다 익혔다면 이제 목적지는 하나입니다. 스펙을 넣으면 AWS 인프라까지 자동으로 올라오는 파이프라인. Kiro + CDK + AgentCore가 연결되면 거기 도달합니다.


📌 핵심 요약
→ Kiro의 진짜 끝판: 스펙 → Lambda 핸들러 + CDK 인프라 코드 + 테스트 동시 생성
→ AgentCore MCP Server: Kiro에서 122개 AgentCore API를 대화로 조작
→ AgentCore Memory: 에이전트가 세션 넘어 컨텍스트 유지 — 장기 작업 필수
→ AgentCore Gateway: 기존 REST API를 에이전트 Tool로 변환 — 레거시 현대화
→ Lambda Durable Functions Power: 장기 실행 워크플로우 스펙 → CDK 자동 생성
→ Kiro + Security Agent + DevOps Agent 멀티에이전트 오케스트레이션 실전 구조
→ 풀스택 서버리스 실전: API GW + Lambda + DynamoDB + CDK 전체를 스펙 1개로
→ "Kiro가 AWS 날렸다" 이후 강화된 프로덕션 가드레일 적용법

실전1 — AgentCore MCP Server 연결: Kiro에서 AWS를 대화로 조작

AgentCore MCP Server는 Claude Code, Kiro, Cursor 같은 AI 에이전트에 AgentCore 플랫폼 API 직접 접근을 제공합니다. 에이전트는 런타임 생성·관리, 메모리 저장·조회, 신원 공급자 설정, 게이트웨이 배포, 정책 관리를 모두 표준 MCP 툴 호출로 수행할 수 있으며, 7개 운영 프리미티브에 걸쳐 122개 도구가 있습니다.

// .kiro/mcp.json — AgentCore MCP Server 연결
{
  "servers": {
    "agentcore": {
      "type": "stdio",
      "command": "uvx",
      "args": ["amazon-bedrock-agentcore-mcp-server"],
      "env": {
        "AWS_REGION": "us-east-1",
        "AWS_PROFILE": "kiro-dev"
      }
    },
    "aws-docs": {
      "type": "url",
      "url": "https://mcp.aws.amazon.com/docs",
      "description": "AWS 공식 문서 실시간 조회"
    },
    "cdk-constructs": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@aws-cdk/mcp-server"],
      "description": "CDK Construct 레퍼런스 실시간 조회"
    }
  }
}
[AgentCore MCP Server 7개 프리미티브]

1. Runtime    → 에이전트 실행 환경 생성·배포·스케일링
2. Memory     → 단기·장기 메모리 저장·조회·삭제
3. Gateway    → API·Lambda를 MCP 툴로 변환
4. Identity   → OAuth/Cognito/Entra ID 연동 인증
5. Observability → CloudWatch 대시보드·트레이스 조회
6. Policy     → 에이전트 권한 정책 생성·적용
7. Docs       → AgentCore 문서 검색·조회

→ 연결 후 Kiro에서 자연어로: "AgentCore에 새 런타임 만들고 내 에이전트 배포해줘"
→ Kiro가 AgentCore API 호출 → 실제 AWS 리소스 생성
→ AWS 콘솔 열 필요 없음

실전2 — 풀스택 서버리스: 스펙 1개 → Lambda + DynamoDB + CDK 전부

Kiro를 활용한 실제 서버리스 배포 결과: Lambda(Node 20, 256MB, esbuild 번들링), DynamoDB(GSI 포함, PAY_PER_REQUEST), API Gateway까지 포함해 단위 테스트 22개, 통합 테스트 5개가 자동 생성됩니다.

# .kiro/specs/task-api/requirements.md
# 이 파일 하나로 전체 스택이 생성됩니다

## 기능 요약
할일 관리 CRUD REST API — AWS 서버리스 스택

## User Stories
1. 사용자는 할일을 생성할 수 있다 (POST /tasks)
2. 사용자는 할일 목록을 조회할 수 있다 (GET /tasks)
3. 사용자는 특정 할일을 조회할 수 있다 (GET /tasks/{id})
4. 사용자는 할일을 수정할 수 있다 (PUT /tasks/{id})
5. 사용자는 할일을 삭제할 수 있다 (DELETE /tasks/{id})

## 기술 스택 (Kiro가 이 섹션을 읽고 CDK 코드 생성)
- 런타임: Node.js 20 Lambda (esbuild 번들링)
- DB: DynamoDB (PAY_PER_REQUEST)
- API: API Gateway REST API
- IaC: AWS CDK v2 (TypeScript)
- 인증: Cognito User Pool (JWT)
- 모니터링: CloudWatch + X-Ray 트레이싱

## Acceptance Criteria
- POST /tasks → 201 + 생성된 task (id 자동 생성 UUID)
- GET /tasks → 200 + 배열 (cursor 기반 페이지네이션)
- PUT /tasks/{id} → 200 또는 404
- DELETE /tasks/{id} → 204 또는 404
- 인증 없는 요청 → 401
- 잘못된 입력 → 400 + 상세 에러 메시지

Kiro가 이 requirements.md를 읽고 자동 생성하는 파일들:

// infra/lib/task-api-stack.ts — Kiro가 생성한 CDK 스택
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import * as cognito from 'aws-cdk-lib/aws-cognito';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';

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

    // ── DynamoDB 테이블 ─────────────────────────────────
    const table = new dynamodb.Table(this, 'TasksTable', {
      tableName: 'tasks',
      partitionKey: { name: 'pk', type: dynamodb.AttributeType.STRING },
      sortKey:      { name: 'sk', type: dynamodb.AttributeType.STRING },
      billingMode:  dynamodb.BillingMode.PAY_PER_REQUEST,
      pointInTimeRecovery: true,                    // 백업
      encryption: dynamodb.TableEncryption.AWS_MANAGED,
    });

    // GSI: 상태별 조회
    table.addGlobalSecondaryIndex({
      indexName: 'status-index',
      partitionKey: { name: 'status', type: dynamodb.AttributeType.STRING },
      sortKey:      { name: 'createdAt', type: dynamodb.AttributeType.STRING },
    });

    // ── Cognito User Pool ────────────────────────────────
    const userPool = new cognito.UserPool(this, 'TaskUserPool', {
      selfSignUpEnabled: true,
      autoVerify: { email: true },
      passwordPolicy: {
        minLength: 8,
        requireUppercase: true,
        requireDigits: true,
      },
    });

    const userPoolClient = userPool.addClient('TaskAppClient');

    // ── Lambda 핸들러 (esbuild 번들) ──────────────────────
    const commonProps = {
      runtime: lambda.Runtime.NODEJS_20_X,
      environment: {
        TABLE_NAME: table.tableName,
        USER_POOL_ID: userPool.userPoolId,
      },
      tracing: lambda.Tracing.ACTIVE,              // X-Ray
      bundling: { minify: true, sourceMap: true },
    };

    const createTask = new NodejsFunction(this, 'CreateTask', {
      ...commonProps,
      entry: 'src/handlers/createTask.ts',
      memorySize: 256,
      timeout: cdk.Duration.seconds(10),
    });

    const listTasks = new NodejsFunction(this, 'ListTasks', {
      ...commonProps,
      entry: 'src/handlers/listTasks.ts',
      memorySize: 512,                              // 리스트 조회는 메모리 여유
      timeout: cdk.Duration.seconds(15),
    });

    const getTask   = new NodejsFunction(this, 'GetTask',    { ...commonProps, entry: 'src/handlers/getTask.ts',    memorySize: 128 });
    const updateTask = new NodejsFunction(this, 'UpdateTask', { ...commonProps, entry: 'src/handlers/updateTask.ts', memorySize: 256 });
    const deleteTask = new NodejsFunction(this, 'DeleteTask', { ...commonProps, entry: 'src/handlers/deleteTask.ts', memorySize: 128 });

    // Lambda에 DynamoDB 권한 부여
    table.grantReadWriteData(createTask);
    table.grantReadData(listTasks);
    table.grantReadData(getTask);
    table.grantReadWriteData(updateTask);
    table.grantReadWriteData(deleteTask);

    // ── API Gateway ──────────────────────────────────────
    const api = new apigateway.RestApi(this, 'TaskApi', {
      restApiName: 'task-api',
      deployOptions: {
        stageName: 'prod',
        tracingEnabled: true,                       // X-Ray
        loggingLevel: apigateway.MethodLoggingLevel.INFO,
      },
      defaultCorsPreflightOptions: {
        allowOrigins: apigateway.Cors.ALL_ORIGINS,
        allowMethods: apigateway.Cors.ALL_METHODS,
      },
    });

    // Cognito 인증
    const authorizer = new apigateway.CognitoUserPoolsAuthorizer(this, 'Authorizer', {
      cognitoUserPools: [userPool],
    });

    const authConfig = {
      authorizer,
      authorizationType: apigateway.AuthorizationType.COGNITO,
    };

    const tasks = api.root.addResource('tasks');
    tasks.addMethod('POST', new apigateway.LambdaIntegration(createTask), authConfig);
    tasks.addMethod('GET',  new apigateway.LambdaIntegration(listTasks),  authConfig);

    const task = tasks.addResource('{id}');
    task.addMethod('GET',    new apigateway.LambdaIntegration(getTask),    authConfig);
    task.addMethod('PUT',    new apigateway.LambdaIntegration(updateTask),  authConfig);
    task.addMethod('DELETE', new apigateway.LambdaIntegration(deleteTask),  authConfig);

    // ── 출력 ─────────────────────────────────────────────
    new cdk.CfnOutput(this, 'ApiUrl',          { value: api.url });
    new cdk.CfnOutput(this, 'UserPoolId',      { value: userPool.userPoolId });
    new cdk.CfnOutput(this, 'UserPoolClientId',{ value: userPoolClient.userPoolClientId });
  }
}
→ Kiro가 requirements.md 읽고 CDK 스택 전체를 한 번에 생성
→ 핸들러·테스트·인프라 코드가 스펙 기준으로 일관성 있게 생성됨
→ CDK Constructs MCP: 최신 L2 Construct API를 실시간 참조 → 구버전 코드 생성 방지
→ 배포: cdk deploy 한 줄로 전체 스택 올라감

실전3 — Lambda Durable Functions Power: 장기 워크플로우 스펙 자동화

Lambda Durable Functions Kiro Power를 사용하면 리플레이 모델 모범 사례, 스텝·대기 작업, map·parallel 패턴을 활용한 동시 실행, 재시도 전략·보상 트랜잭션을 활용한 에러 처리, 테스트 패턴, CloudFormation·CDK·SAM을 활용한 배포까지 AI 에이전트가 직접 안내합니다.

# .kiro/specs/order-pipeline/requirements.md
# Lambda Durable Functions Power가 이 스펙을 읽고 워크플로우 생성

## 기능: 주문 처리 파이프라인

### 워크플로우 단계
1. 주문 접수 (즉시)
2. 재고 확인 (외부 API, 최대 30초)
3. 결제 처리 (Toss Payments, 최대 60초)
4. 배송 예약 (CJ대한통운 API, 최대 120초)
5. 완료 알림 (Kakao 알림톡)

### 실패 처리 요구사항
- 재고 부족: 주문 취소 + 환불 + 알림
- 결제 실패: 3회 재시도 (10초 간격) → 실패 시 취소
- 배송 실패: 2회 재시도 → 담당자 알림

### 특수 조건
- 전체 워크플로우 최대 10분 (Lambda Durable 필수)
- 중간 실패 시 이미 완료된 단계는 롤백 (Saga 패턴)
- 모든 단계 CloudWatch에 상태 로깅

Kiro + Lambda Durable Functions Power가 생성하는 코드:

// src/workflows/orderPipeline.ts — Kiro가 자동 생성
import { workflow, step, activity } from '@aws-lambda/durable-functions';

export const orderPipelineWorkflow = workflow(async (ctx, orderId: string) => {

  // Step 1: 재고 확인 (타임아웃 30초, 재시도 없음)
  const inventory = await step(ctx, 'check-inventory', {
    timeout: 30,
    retries: 0,
  }, () => checkInventoryActivity(orderId));

  if (!inventory.available) {
    // 보상 트랜잭션: 주문 취소 + 환불
    await step(ctx, 'cancel-order', {}, () => cancelOrderActivity(orderId));
    await step(ctx, 'notify-cancel', {}, () => sendKakaoActivity(orderId, 'CANCEL'));
    return { status: 'CANCELLED', reason: 'OUT_OF_STOCK' };
  }

  // Step 2: 결제 처리 (3회 재시도, 10초 간격)
  let payment;
  try {
    payment = await step(ctx, 'process-payment', {
      timeout: 60,
      retries: 3,
      retryDelay: 10,
    }, () => processPaymentActivity(orderId));
  } catch (err) {
    // 결제 실패 보상: 재고 예약 해제
    await step(ctx, 'release-inventory', {}, () => releaseInventoryActivity(orderId));
    await step(ctx, 'notify-fail', {}, () => sendKakaoActivity(orderId, 'PAYMENT_FAIL'));
    return { status: 'FAILED', reason: 'PAYMENT_FAILED' };
  }

  // Step 3: 배송 예약 (2회 재시도)
  let shipping;
  try {
    shipping = await step(ctx, 'schedule-delivery', {
      timeout: 120,
      retries: 2,
      retryDelay: 30,
    }, () => scheduleDeliveryActivity(orderId, payment.txId));
  } catch (err) {
    // 배송 실패 → 담당자 알림 (자동 환불 아님, 수동 처리)
    await step(ctx, 'alert-ops', {}, () => alertOpsActivity(orderId));
    return { status: 'DELIVERY_FAILED', txId: payment.txId };
  }

  // Step 4: 완료 알림
  await step(ctx, 'notify-complete', {}, () =>
    sendKakaoActivity(orderId, 'COMPLETE', { trackingNo: shipping.trackingNo })
  );

  return {
    status: 'COMPLETED',
    trackingNo: shipping.trackingNo,
    txId: payment.txId,
  };
});
// infra/lib/order-pipeline-stack.ts — CDK도 함께 생성
import * as cdk from 'aws-cdk-lib';
import { DurableFunction } from '@aws-lambda/durable-functions-cdk';

export class OrderPipelineStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string) {
    super(scope, id);

    const pipeline = new DurableFunction(this, 'OrderPipeline', {
      workflowEntry:  'src/workflows/orderPipeline.ts',
      activityEntry:  'src/activities/',
      timeout:        cdk.Duration.minutes(10),   // 최대 10분
      logGroup:       '/kiro/order-pipeline',
      tracing:        true,
    });

    // API Gateway 트리거
    // ... (Kiro가 추가 생성)
  }
}
→ 핵심: 장기 실행(10분), Saga 패턴, 재시도 로직을 스펙으로만 정의
→ Durable Functions Power가 리플레이 모델 안티패턴 자동 방지
→ CDK까지 함께 생성 → 인프라·코드 분리 없이 한 번에 배포
→ step()으로 감싸면 중간 실패 시 이미 완료된 step은 재실행 안 함 (멱등성)

실전4 — AgentCore Memory: 에이전트가 세션 넘어 기억하게 만들기

AgentCore Memory는 단기 및 장기 메모리 모두를 유지하는 완전 관리형 서비스입니다. 세션 내 이벤트는 시간순으로 저장돼 정확한 내러티브 흐름을 유지하며, 계층적 네임스페이스로 구조화된 메모리 조직과 세밀한 접근 제어를 제공합니다.

// Kiro Autonomous Agent + AgentCore Memory 연동 패턴

// .kiro/mcp.json 에 agentcore 연결 후
// Kiro에서 자연어로 Memory 조작 가능

// 실제 코드에서는 이렇게 사용:
import {
  BedrockAgentCoreClient,
  CreateMemoryCommand,
  StoreMemoryCommand,
  RetrieveMemoryCommand,
} from '@aws-sdk/client-bedrock-agentcore';

const client = new BedrockAgentCoreClient({ region: 'us-east-1' });

// ── 메모리 생성 (프로젝트당 1회) ─────────────────────────
async function initProjectMemory(projectId: string) {
  const cmd = new CreateMemoryCommand({
    name: `kiro-project-${projectId}`,
    description: '프로젝트 컨텍스트 — 아키텍처 결정, 이전 작업 내역',
    memoryExecutionRoleArn: process.env.MEMORY_ROLE_ARN,
  });
  return client.send(cmd);
}

// ── 작업 완료 후 메모리 저장 ─────────────────────────────
async function saveWorkContext(memoryId: string, task: string, result: string) {
  const cmd = new StoreMemoryCommand({
    memoryId,
    namespace: 'task-history',
    content: {
      text: `[${new Date().toISOString()}] 작업: ${task}\n결과: ${result}`,
    },
    metadata: {
      taskType: 'implementation',
      files: 'spec referenced',
    },
  });
  return client.send(cmd);
}

// ── 새 작업 시작 시 관련 메모리 조회 ─────────────────────
async function loadRelevantContext(memoryId: string, query: string) {
  const cmd = new RetrieveMemoryCommand({
    memoryId,
    namespace: 'task-history',
    query,
    maxResults: 5,
  });
  const result = await client.send(cmd);
  return result.memoryRecords?.map(r => r.content?.text).join('\n\n');
}

// ── Kiro Autonomous Agent와 연동 ──────────────────────────
// .kiro/hooks/save-memory.yaml
/*
name: "작업 완료 시 AgentCore Memory 저장"
trigger:
  type: task_complete    # tasks.md 체크박스 완료 시
action:
  prompt: |
    방금 완료된 태스크 내용을 AgentCore Memory에 저장해줘.
    memoryId: ${env.PROJECT_MEMORY_ID}
    저장 내용: 태스크명, 구현 결정 사항, 주의할 점
*/
→ AgentCore Memory 활용 시나리오:
   1) 장기 프로젝트: Autonomous Agent가 어제 한 작업 기억
   2) 팀 공유: 여러 개발자의 Kiro 세션이 같은 Memory 참조
   3) 아키텍처 결정 이력: "왜 이 라이브러리 썼는지" 메모리에 기록
→ 단기 메모리: 현재 세션 컨텍스트 (자동 관리)
→ 장기 메모리: 프로젝트·팀 수준 지식 (개발자가 설계)
→ 비용: GB당 저장 + 조회 횟수 과금 → 중요 컨텍스트만 저장 권장

실전5 — AgentCore Gateway: 레거시 API를 에이전트 Tool로 변환

AgentCore Gateway와 Kiro Powers를 활용하면 레거시 애플리케이션의 소스 코드를 건드리지 않고도 에이전트 AI 기능을 추가하는 패턴이 가능합니다.

# .kiro/hooks/legacy-gateway.yaml
# 레거시 REST API → AgentCore Gateway → Kiro Tool
name: "레거시 API 현대화 — AgentCore Gateway 등록"
trigger:
  type: manual
  label: "레거시 API를 에이전트 Tool로 등록"
action:
  prompt: |
    다음 OpenAPI 스펙을 AgentCore Gateway에 등록해서
    Kiro 에이전트가 직접 호출할 수 있는 Tool로 만들어줘.

    API 스펙 위치: docs/legacy-api.yaml
    Gateway 이름: legacy-inventory-tool
    인증: API Key (AWS Secrets Manager에서 가져와)

    등록 후 테스트 호출 1번 실행해서 동작 확인해줘.
// Kiro가 AgentCore MCP를 통해 실행하는 Gateway 등록 코드 (자동 생성)
// src/infra/gateway.ts

import {
  BedrockAgentCoreClient,
  CreateGatewayCommand,
  CreateGatewayTargetCommand,
} from '@aws-sdk/client-bedrock-agentcore';

async function registerLegacyApiAsGateway() {
  const client = new BedrockAgentCoreClient({ region: 'us-east-1' });

  // Gateway 생성
  const gateway = await client.send(new CreateGatewayCommand({
    name: 'legacy-inventory-tool',
    description: '레거시 재고 관리 API — 에이전트 Tool',
    protocolType: 'MCP',              // MCP 프로토콜로 노출
    authorizerType: 'NONE',           // Gateway 자체는 내부 호출만
  }));

  // 레거시 API 엔드포인트 등록
  await client.send(new CreateGatewayTargetCommand({
    gatewayIdentifier: gateway.gatewayId!,
    name: 'inventory-api',
    description: '재고 확인·예약·해제 API',
    targetConfiguration: {
      openApi: {
        schema: {
          // OpenAPI 스펙을 인라인으로 또는 S3에서 참조
          s3: { uri: 's3://my-bucket/legacy-api.yaml' },
        },
        credentialConfiguration: {
          apiKeyCredential: {
            apiKeySecretArn: process.env.LEGACY_API_KEY_ARN!,
          },
        },
      },
    },
  }));

  console.log('✅ 레거시 API가 AgentCore Gateway에 등록됨');
  console.log('이제 Kiro에서 "재고 확인해줘"라고 하면 이 API가 자동 호출됨');
}
→ 레거시 현대화의 핵심: 소스 코드 0 수정으로 에이전트 Tool 화
→ 기존 API → Gateway 등록 → Kiro가 MCP Tool로 호출
→ 보안: IAM + Secrets Manager로 자격증명 격리
→ 활용: Kiro 에이전트가 레거시 재고·ERP·결제 API를 직접 조회하며 코드 생성

실전6 — 멀티에이전트 오케스트레이션: Kiro + Security + DevOps Agent

멀티에이전트 협업 구조에서 Kiro는 Security Agent에 리뷰를 요청하거나 DevOps Agent에 카나리 롤아웃을 맡기는 방식으로 Bedrock의 멀티에이전트 기능을 통해 협력합니다.

# .kiro/hooks/multi-agent-review.yaml
name: "PR 오픈 시 멀티에이전트 리뷰 파이프라인"
trigger:
  type: pr_open
action:
  steps:
    # Step 1: Kiro가 코드 품질 리뷰
    - name: "코드 품질 리뷰"
      prompt: |
        변경된 파일의 코드 품질을 리뷰하고 steering 규칙 준수 여부 확인.
        결과를 PR 코멘트로 작성.

    # Step 2: Security Agent 호출 (AgentCore 멀티에이전트)
    - name: "보안 취약점 분석"
      invoke_agent: "arn:aws:bedrock:us-east-1::foundation-model/aws.security-agent"
      prompt: |
        변경된 코드에서 OWASP Top 10 기준 취약점 분석.
        발견된 취약점은 심각도(Critical/High/Medium/Low)로 분류.
        Critical 발견 시 PR 머지 차단.

    # Step 3: 결과 종합 후 최종 판정
    - name: "리뷰 종합"
      prompt: |
        코드 품질 리뷰와 보안 분석 결과를 종합해
        APPROVE / REQUEST_CHANGES / BLOCK 중 하나로 판정.
[멀티에이전트 실전 역할 분담]

Kiro Autonomous Agent (개발 에이전트)
  ∟ 스펙 읽고 코드 구현
  ∟ 단위·통합 테스트 작성
  ∟ PR 오픈

          ↓ PR 오픈 시 자동 호출

Security Agent (보안 에이전트)
  ∟ SAST: 정적 분석
  ∟ 시크릿 탐지
  ∟ 취약 의존성 감지
  ∟ Critical 발견 시 머지 차단

DevOps Agent (인프라 에이전트)
  ∟ CDK diff 검토
  ∟ 비용 영향 분석
  ∟ 카나리 배포 실행
  ∟ 롤백 트리거

→ 세 에이전트가 모두 통과해야 자동 머지
→ 인간은 이상 케이스·Critical 이슈만 개입

실전7 — 프로덕션 가드레일: "Kiro가 AWS 날렸다" 이후 필수 설정

2026년 2월 Kiro로 생성된 코드가 AWS 서비스 장애를 유발했다는 사건이 바이럴됐습니다. AWS는 공식 부인했지만, 이 사건 이후 프로덕션 인프라를 건드리는 AI 생성 코드에 가드레일이 필요하다는 점이 부각됐습니다. Kiro는 이후 위험 행동 전 AgentCore 정책 검사를 강화했습니다.

# .kiro/steering/production-guardrails.md
---
inclusion: always
---

## 프로덕션 가드레일 — 절대 규칙

### Kiro·Autonomous Agent 공통
- cdk destroy 명령 절대 실행 금지 (직접 제안도 금지)
- 프로덕션 DynamoDB 직접 수정 쿼리 제안 금지
- IAM 역할 권한 확대 코드 생성 시 반드시 경고 표시
- 환경변수 NODE_ENV=production 일 때 파괴적 작업 제안 금지

### CDK 코드 생성 시 필수 포함
- removalPolicy: cdk.RemovalPolicy.RETAIN  (프로덕션 리소스)
- deletionProtection: true  (RDS, DynamoDB 중요 테이블)
- terminationProtection: true  (스택 레벨)

### Autonomous Agent 제한
- PR 오픈 전 반드시 diff 출력하고 인간 확인 대기
- 프로덕션 환경 직접 배포 금지 — staging까지만
- 외부 API 호출 코드 생성 시 rate limit·timeout 반드시 포함
// infra/lib/task-api-stack.ts — 가드레일 적용 패턴
import * as cdk from 'aws-cdk-lib';

// ✅ 프로덕션 스택 보호 설정 — Kiro Steering에 의해 자동 적용
export class TaskApiStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, env: string) {
    super(scope, id, {
      terminationProtection: env === 'prod',        // 프로덕션은 삭제 보호
    });

    const table = new dynamodb.Table(this, 'Tasks', {
      // ...
      removalPolicy: env === 'prod'
        ? cdk.RemovalPolicy.RETAIN                  // 프로덕션: 삭제해도 테이블 유지
        : cdk.RemovalPolicy.DESTROY,                // 개발: 깔끔하게 삭제
      pointInTimeRecovery: env === 'prod',          // 프로덕션만 PITR
    });
  }
}
[배포 전 체크리스트 — Hook으로 자동화]

# .kiro/hooks/pre-deploy-check.yaml
trigger:
  type: manual
  label: "🚀 배포 전 최종 점검"
action:
  prompt: |
    다음 항목 전부 확인하고 결과 출력:
    □ removalPolicy RETAIN 설정 (프로덕션 리소스)
    □ 하드코딩된 ARN·계정ID 없음
    □ 환경변수 .env.example 최신 상태
    □ CDK diff 실행 → 예상치 못한 리소스 삭제 없음
    □ 보안그룹 0.0.0.0/0 인바운드 없음
    □ 단위 테스트 전부 통과
    □ Staging 환경 배포 및 동작 확인 완료

    위 항목 중 하나라도 ❌ 이면 배포 중단 권고.

✅ 3편 핵심 정리
✅ AgentCore MCP Server: Kiro에서 122개 API로 AWS 리소스 대화로 조작
✅ 스펙 1개 → Lambda + DynamoDB + CDK 전체 자동 생성 — 실전 코드 포함
✅ Lambda Durable Functions: 장기 워크플로우·Saga 패턴을 스펙으로
✅ AgentCore Memory: 세션 넘어 프로젝트 컨텍스트 유지
✅ AgentCore Gateway: 레거시 API 소스 수정 없이 에이전트 Tool 화
✅ 멀티에이전트: Kiro + Security + DevOps Agent PR 자동 파이프라인
✅ 프로덕션 가드레일: removalPolicy·terminationProtection·배포 전 체크리스트

❌ AgentCore Memory 비용: 저장·조회 과금 → 중요 컨텍스트만 선별 저장
❌ 멀티에이전트 파이프라인은 Security/DevOps Agent 별도 설정 필요
❌ Lambda Durable Functions: 리플레이 모델 이해 없이 쓰면 무한 루프 위험
❌ CDK 자동 생성 코드는 반드시 cdk diff로 검토 후 배포

관련글

반응형