Use Cases

Claude Code × AWS CloudWatch 완벽 가이드 | 로그 분석·알람 설정·대시보드 자동 구축

Claude Code로 AWS CloudWatch를 효율화하세요. 로그 패턴 분석·알람 자동 설정·메트릭 대시보드 구축·인시던트 조사까지 실전 코드로 해설합니다.

“프로덕션에서 에러가 났어요! 그런데 로그가 너무 많아서 어디를 봐야 할지 모르겠어요.” — 인시던트 대응에서 흔히 겪는 당혹스러운 상황입니다.

CloudWatch는 AWS의 표준 모니터링 서비스지만, 로그 양이 방대해서 핵심 정보가 묻히고 알람 설정도 뒤로 미루기 쉽습니다. 저는 업무에서 ECS + Lambda 시스템을 모니터링하고 있는데, Claude Code에 로그를 읽혀 원인을 특정시킴으로써 인시던트 대응 시간을 평균 40% 단축했습니다.

이 글에서는 CloudWatch 로그 분석·알람 설계·대시보드 구축을 Claude Code로 자동화하는 실전 절차를 해설합니다.


CloudWatch 주요 컴포넌트

CloudWatch Logs      : 앱·AWS 서비스의 로그 저장·검색
CloudWatch Metrics   : CPU 사용률·요청 수 등의 수치 데이터
CloudWatch Alarms    : 메트릭 임계값 초과를 감지하여 SNS 등에 알림
CloudWatch Dashboards: 메트릭·로그를 시각화하는 커스텀 화면
Log Insights         : 로그를 SQL 형태로 분석하는 쿼리 엔진

Step 1: 로그 패턴 분석을 Claude Code에 맡기기

인시던트 발생 시 먼저 “에러 로그의 패턴”을 파악하는 것이 중요합니다.

# 최근 1시간의 에러 로그 가져오기
aws logs filter-log-events \
  --log-group-name "/ecs/myapp" \
  --start-time $(date -d "1 hour ago" +%s000) \
  --filter-pattern "ERROR" \
  --output json > error-logs.json

claude -p "
다음 CloudWatch 에러 로그를 분석해줘:

1. 에러 종류별로 분류 (5xx, 4xx, DB 연결 에러, 타임아웃 등)
2. 가장 빈도가 높은 에러 특정
3. 에러가 급증한 시각 특정
4. 근본 원인 가설 제시
5. 조사해야 할 다음 액션 제안

$(cat error-logs.json | head -500)
"

Log Insights 쿼리 자동 생성

claude -p "
다음 목적의 CloudWatch Log Insights 쿼리를 생성해줘:

1. 최근 1시간의 엔드포인트별 에러율 (상위 10건)
2. 레이턴시가 500ms 이상인 요청의 상세
3. 특정 사용자 (user_id: 12345)의 모든 작업 로그
4. 배포 후 30분 이내에 발생한 최초 에러

로그 포맷: JSON (timestamp, level, message, user_id, endpoint, duration_ms, status_code)
"

생성되는 Log Insights 쿼리 예시:

-- 엔드포인트별 에러율
fields @timestamp, endpoint, status_code
| filter status_code >= 400
| stats count() as error_count by endpoint
| sort error_count desc
| limit 10

-- 레이턴시 500ms 초과 요청
fields @timestamp, endpoint, duration_ms, user_id
| filter duration_ms > 500
| sort duration_ms desc
| limit 50

-- 특정 사용자의 작업 로그
fields @timestamp, level, message, endpoint
| filter user_id = "12345"
| sort @timestamp desc
| limit 100

Step 2: 알람 설정 자동 생성

claude -p "
다음 시스템에 필요한 CloudWatch 알람을 모두 설계해줘.
CDK TypeScript로 구현할 것.

【시스템 구성】
- ECS Fargate (API 서버, 2~10대)
- RDS PostgreSQL
- ALB (Application Load Balancer)
- Lambda (배치 처리)

【알람 요건】
- 프로덕션 환경: 5분 이내에 알아챌 수 있는 알람 설정
- 알림처: SNS → Slack과 PagerDuty
- 단계적 알람 (Warning/Critical 2단계)
- 비즈니스 시간 외에는 Critical만 알림
"
// lib/monitoring-stack.ts
import * as cdk from "aws-cdk-lib";
import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
import * as actions from "aws-cdk-lib/aws-cloudwatch-actions";
import * as sns from "aws-cdk-lib/aws-sns";

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

    const alertTopic = sns.Topic.fromTopicArn(
      this, "AlertTopic",
      `arn:aws:sns:${this.region}:${this.account}:prod-alerts`
    );
    const warnTopic = sns.Topic.fromTopicArn(
      this, "WarnTopic",
      `arn:aws:sns:${this.region}:${this.account}:prod-warnings`
    );

    // ALB 5xx 에러율 알람
    const alb5xxAlarm = new cloudwatch.Alarm(this, "Alb5xxAlarm", {
      alarmName: "prod-alb-5xx-critical",
      alarmDescription: "ALB 5xx 에러율이 5% 초과",
      metric: new cloudwatch.Metric({
        namespace: "AWS/ApplicationELB",
        metricName: "HTTPCode_Target_5XX_Count",
        dimensionsMap: { LoadBalancer: "app/myapp/xxx" },
        statistic: "Sum",
        period: cdk.Duration.minutes(5),
      }),
      threshold: 10,
      evaluationPeriods: 2,
      comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
      treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
    });
    alb5xxAlarm.addAlarmAction(new actions.SnsAction(alertTopic));

    // ECS CPU 사용률 알람 (Warning/Critical)
    const ecsCpuWarning = new cloudwatch.Alarm(this, "EcsCpuWarning", {
      alarmName: "prod-ecs-cpu-warning",
      metric: new cloudwatch.Metric({
        namespace: "AWS/ECS",
        metricName: "CPUUtilization",
        dimensionsMap: { ClusterName: "myapp-cluster", ServiceName: "myapp-service" },
        statistic: "Average",
        period: cdk.Duration.minutes(5),
      }),
      threshold: 70,
      evaluationPeriods: 3,
    });
    ecsCpuWarning.addAlarmAction(new actions.SnsAction(warnTopic));

    const ecsCpuCritical = new cloudwatch.Alarm(this, "EcsCpuCritical", {
      alarmName: "prod-ecs-cpu-critical",
      metric: new cloudwatch.Metric({
        namespace: "AWS/ECS",
        metricName: "CPUUtilization",
        dimensionsMap: { ClusterName: "myapp-cluster", ServiceName: "myapp-service" },
        statistic: "Average",
        period: cdk.Duration.minutes(5),
      }),
      threshold: 90,
      evaluationPeriods: 2,
    });
    ecsCpuCritical.addAlarmAction(new actions.SnsAction(alertTopic));

    // RDS 연결 수 알람
    const rdsConnectionAlarm = new cloudwatch.Alarm(this, "RdsConnectionAlarm", {
      alarmName: "prod-rds-connections-critical",
      metric: new cloudwatch.Metric({
        namespace: "AWS/RDS",
        metricName: "DatabaseConnections",
        dimensionsMap: { DBInstanceIdentifier: "myapp-db" },
        statistic: "Maximum",
        period: cdk.Duration.minutes(5),
      }),
      threshold: 80,  // db.t3.micro 최대 연결 수의 80%
      evaluationPeriods: 2,
    });
    rdsConnectionAlarm.addAlarmAction(new actions.SnsAction(alertTopic));

    // Lambda 에러율 알람
    const lambdaErrorAlarm = new cloudwatch.Alarm(this, "LambdaErrorAlarm", {
      alarmName: "prod-lambda-errors-critical",
      metric: new cloudwatch.Metric({
        namespace: "AWS/Lambda",
        metricName: "Errors",
        dimensionsMap: { FunctionName: "myapp-batch" },
        statistic: "Sum",
        period: cdk.Duration.minutes(15),
      }),
      threshold: 5,
      evaluationPeriods: 1,
    });
    lambdaErrorAlarm.addAlarmAction(new actions.SnsAction(alertTopic));
  }
}

Step 3: 커스텀 대시보드 자동 생성

claude -p "
다음 정보를 표시하는 CloudWatch 대시보드를 CDK로 생성해줘.

【대시보드 구성】
Row 1: 시스템 전체 헬스 (ALB 요청 수·5xx율·레이턴시 P50/P95/P99)
Row 2: ECS 서비스 (CPU·메모리·실행 태스크 수)
Row 3: RDS (연결 수·레이턴시·CPU 사용률)
Row 4: Lambda (실행 횟수·에러 수·실행 시간)
Row 5: 비즈니스 메트릭 (신규 가입 수·결제 성공률) ← 커스텀 메트릭
"
// 대시보드 정의 (발췌)
const dashboard = new cloudwatch.Dashboard(this, "AppDashboard", {
  dashboardName: "myapp-production",
});

dashboard.addWidgets(
  new cloudwatch.Row(
    new cloudwatch.GraphWidget({
      title: "ALB 요청 수",
      left: [new cloudwatch.Metric({
        namespace: "AWS/ApplicationELB",
        metricName: "RequestCount",
        statistic: "Sum",
        period: cdk.Duration.minutes(1),
      })],
      width: 8,
    }),
    new cloudwatch.GraphWidget({
      title: "ALB 5xx 에러율 (%)",
      left: [new cloudwatch.MathExpression({
        expression: "5xx / (2xx + 3xx + 4xx + 5xx) * 100",
        usingMetrics: {
          "5xx": new cloudwatch.Metric({ metricName: "HTTPCode_Target_5XX_Count", namespace: "AWS/ApplicationELB", statistic: "Sum" }),
          "2xx": new cloudwatch.Metric({ metricName: "HTTPCode_Target_2XX_Count", namespace: "AWS/ApplicationELB", statistic: "Sum" }),
          "3xx": new cloudwatch.Metric({ metricName: "HTTPCode_Target_3XX_Count", namespace: "AWS/ApplicationELB", statistic: "Sum" }),
          "4xx": new cloudwatch.Metric({ metricName: "HTTPCode_Target_4XX_Count", namespace: "AWS/ApplicationELB", statistic: "Sum" }),
        },
        period: cdk.Duration.minutes(1),
      })],
      width: 8,
    }),
  )
);

Step 4: 인시던트 조사를 Claude Code에 맡기기

claude -p "
프로덕션 인시던트를 조사하고 싶어. 다음 커맨드를 실행해서 결과를 분석해줘:

1. aws logs filter-log-events --log-group-name '/ecs/myapp' \
   --start-time \$(date -d '2 hours ago' +%s000) \
   --filter-pattern 'ERROR' --limit 100

2. aws cloudwatch get-metric-statistics \
   --namespace AWS/ApplicationELB \
   --metric-name HTTPCode_Target_5XX_Count \
   --start-time \$(date -d '2 hours ago' -u +%Y-%m-%dT%H:%M:%SZ) \
   --end-time \$(date -u +%Y-%m-%dT%H:%M:%SZ) \
   --period 300 --statistics Sum

위 결과를 바탕으로:
- 인시던트 발생 시각
- 영향받은 사용자 수 (추정)
- 근본 원인 가설 (TOP3)
- 즉시 대응 액션
을 정리해줘
"

Step 5: 커스텀 메트릭 자동 설계

claude -p "
EC 사이트의 비즈니스 KPI를 CloudWatch 커스텀 메트릭으로
Node.js (AWS SDK v3)로 측정하는 코드를 생성해줘.

측정할 메트릭:
- 결제 성공 수·실패 수 (1분마다)
- 카트 이탈율 (5분마다)
- 신규 회원 가입 수 (1시간마다)

네임스페이스: MyApp/Business
각 메트릭에 환경 태그 (Production/Staging) 부여
"
// src/monitoring/business-metrics.ts
import { CloudWatchClient, PutMetricDataCommand } from "@aws-sdk/client-cloudwatch";

const cw = new CloudWatchClient({ region: process.env.AWS_REGION });
const NAMESPACE = "MyApp/Business";
const ENV = process.env.NODE_ENV ?? "development";

export async function recordPaymentSuccess() {
  await cw.send(new PutMetricDataCommand({
    Namespace: NAMESPACE,
    MetricData: [{
      MetricName: "PaymentSuccess",
      Value: 1,
      Unit: "Count",
      Dimensions: [{ Name: "Environment", Value: ENV }],
    }],
  }));
}

export async function recordPaymentFailure(reason: string) {
  await cw.send(new PutMetricDataCommand({
    Namespace: NAMESPACE,
    MetricData: [{
      MetricName: "PaymentFailure",
      Value: 1,
      Unit: "Count",
      Dimensions: [
        { Name: "Environment", Value: ENV },
        { Name: "Reason", Value: reason },
      ],
    }],
  }));
}

주의할 함정 4가지

1. 알람의 evaluationPeriods가 너무 짧음

// ❌ 순간적인 스파이크에도 즉시 알람
evaluationPeriods: 1,
threshold: 10,

// ✅ 3기간 연속 초과 시에만 알람 (오탐 방지)
evaluationPeriods: 3,
threshold: 10,
datapointsToAlarm: 2,  // 3기간 중 2회 초과 시 알람

2. Log Insights의 비용을 고려하지 않음

Log Insights는 스캔한 데이터 양에 따라 과금됩니다. 시간 범위를 좁히지 않고 실행하면 예상치 못한 요금이 발생합니다. --start-time --end-time을 반드시 지정하세요.

3. 커스텀 메트릭의 고해상도는 고비용

표준 메트릭 (60초)은 무료지만 고해상도 메트릭 (1초)은 비용이 약 10배입니다. 비즈니스 메트릭은 1분 집계로 충분한 경우가 많습니다.

4. Lambda의 로그 보존 기간을 설정하지 않음

기본값은 “무기한”이어서 스토리지 비용이 계속 증가합니다. 로그 그룹의 보존 기간을 반드시 설정하세요.

new logs.LogGroup(this, "AppLogGroup", {
  logGroupName: "/ecs/myapp",
  retention: logs.RetentionDays.ONE_MONTH,  // 30일 후 자동 삭제
});

정리

태스크Claude Code의 기여
로그 분석에러 로그를 읽어 원인 가설과 대응책 제시
Log Insights 쿼리분석 목적을 전달하기만 하면 쿼리 생성
알람 설정시스템 구성을 전달하면 CDK 코드 일괄 생성
대시보드표시하고 싶은 정보를 전달하면 위젯 정의 생성
인시던트 조사AWS CLI 커맨드를 실행시켜 결과 분석

“모니터링은 나중에 설정하자”고 미룬 결과, 인시던트 발생 시 아무것도 모르는 상황은 피하고 싶습니다. Claude Code를 사용하면 30분에 프로덕션 수준의 알람과 대시보드가 갖춰집니다.

관련 글

참고 자료

#claude-code #aws #cloudwatch #monitoring #observability #devops

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

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

무료 제공

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

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

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

Masa

이 글을 작성한 사람

Masa

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