목차
7 장

CloudWatch 입문 — 로그 / 메트릭

CloudWatch Logs / Metrics / Alarms / Dashboards의 구조, 로그 그룹과 retention, Metric Filter, Logs Insights 쿼리 기초까지 — 모든 운영의 눈이 되는 관측 도구를 정리합니다.

2장부터 6장 까지로 AWS 셋업의 기반이 모였습니다. 계정, IAM, 비용, CLI, SSO, 보안 — 콘솔에 들어가기 전 머릿속 지도와 일상 셋업이 한 곳에 갖춰졌습니다. 이제 운영의 또 다른 축, 무엇이 어디서 무슨 일을 하고 있는지를 보는 도구를 다룹니다.

CloudWatch는 AWS의 관측(Observability) 표준입니다. AWS 안의 거의 모든 서비스가 기본으로 메트릭을 CloudWatch로 보내고, 로그도 CloudWatch Logs가 받습니다. 운영의 첫 시야는 여기서 시작합니다.

본 챕터는 1부의 마지막 챕터로, CloudWatch의 네 가지 구성 — Logs / Metrics / Alarms / Dashboards — 를 한 번에 정리합니다. 더 깊은 관측은 26장 모니터링과 X-Ray에서 분산 추적과 함께 이어집니다.

큰 그림 — CloudWatch의 네 가지 구성 #

구성 요소무엇흔한 사용처
Logs텍스트 로그 저장 / 검색EC2 / Lambda / ECS / API Gateway의 로그
Metrics시계열 숫자 (CPU%, 요청 수 등)모든 AWS 서비스가 자동 송신
Alarms메트릭이 임계 넘으면 알림 / 액션운영 알림, 자동 스케일
Dashboards그래프 / 위젯 페이지팀 / 서비스별 한눈 보기

이 넷이 한 흐름으로 엮입니다. 로그 → 메트릭 → 알람 → 대시보드입니다.

CloudWatch Logs #

로그 그룹과 로그 스트림 #

구조
Log Group           — 보통 한 애플리케이션 / 서비스 단위
  └── Log Stream    — 보통 한 프로세스 / 컨테이너 단위
        └── Log Event — 한 줄
항목
Log Group/aws/lambda/my-function, /ecs/my-service, /var/log/myapp
Log StreamLambda 실행 환경 ID, ECS Task ID, EC2 인스턴스 ID
Log Event한 줄 텍스트 + timestamp

Lambda와 ECS Fargate는 자동으로 로그를 CloudWatch Logs로 보냅니다. EC2는 CloudWatch Agent 또는 보조 도구(fluent-bit 등)가 필요합니다.

Retention — 가장 중요한 설정 #

기본 retention은 영구입니다. 그대로 두면 로그가 영원히 쌓여 비용이 폭주합니다. 가입 직후, 그리고 새 로그 그룹마다 retention을 정해야 합니다.

항목권장 retention
일반 애플리케이션 로그30~90일
디버그 / 개발 로그7일
보안 / 감사 로그 (CloudTrail)1~7년 (S3로 보내는 게 더 쌈)
Lambda 로그14~30일
retention 설정
aws logs put-retention-policy \
  --log-group-name /aws/lambda/my-function \
  --retention-in-days 30
모든 로그 그룹에 일괄 적용
aws logs describe-log-groups --query 'logGroups[].logGroupName' --output text \
  | tr '\t' '\n' \
  | while read name; do
      aws logs put-retention-policy --log-group-name "$name" --retention-in-days 30
    done

이 한 줄이 CloudWatch 비용 사고를 절반 이상 막아 줍니다(3장 비용 관리의 로그 폭주 사고가 이 설정 하나로 해소됩니다).

새 로그 그룹의 자동 retention #

새로 만들어지는 로그 그룹에 자동으로 retention을 적용하는 방법은 두 가지입니다. 첫째는 EventBridge + Lambda로, CreateLogGroup 이벤트를 받아 자동 적용하는 방식이며 실전에서 자주 씁니다. 둘째는 정책으로 강제해 만들 때 retention을 명시하지 않으면 거부하는 방식인데, 살짝 과합니다.

Lambda 로그 보내기 #

Lambda — 그냥 print
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def handler(event, context):
    logger.info("Received event: %s", event)
    return {"ok": True}

stdout / stderr가 자동으로 CloudWatch Logs로 흘러갑니다. 로그 그룹 이름은 /aws/lambda/<함수명>입니다.

EC2 / ECS — CloudWatch Agent #

EC2는 자동이 아닙니다. CloudWatch Agent 설치가 필요합니다.

Amazon Linux 2023 / Ubuntu
sudo yum install -y amazon-cloudwatch-agent       # AL
# 또는
wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
sudo dpkg -i amazon-cloudwatch-agent.deb

설정 파일은 /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json입니다.

간단 설정
{
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "file_path": "/var/log/myapp/*.log",
            "log_group_name": "/myapp/server",
            "log_stream_name": "{instance_id}",
            "retention_in_days": 30
          }
        ]
      }
    }
  },
  "metrics": {
    "metrics_collected": {
      "mem":  { "measurement": ["mem_used_percent"] },
      "disk": { "measurement": ["used_percent"], "resources": ["*"] }
    }
  }
}

ECS의 Fargate는 컨테이너 정의에 awslogs 드라이버를 적으면 자동입니다. 이건 15장 ECS와 Fargate에서 자세히 다룹니다.

Logs Insights — 쿼리로 검색 #

CloudWatch Logs의 검색 / 분석 도구입니다. SQL 비슷한 자체 문법을 씁니다.

가장 단순한 쿼리
fields @timestamp, @message
| sort @timestamp desc
| limit 100
ERROR만
fields @timestamp, @message
| filter @message like /ERROR/
| sort @timestamp desc
| limit 50
요청 시간 분포 (Lambda)
fields @timestamp, @duration
| filter @type = "REPORT"
| stats avg(@duration), max(@duration), count(*) by bin(5m)
API Gateway — 5xx 비율
fields @timestamp, status, path
| filter status >= 500
| stats count(*) as errors by path
| sort errors desc

자주 쓰는 명령어는 다음과 같습니다.

명령무엇
fields보일 필드
filter조건 필터
parse문자열에서 필드 추출
stats집계 (count, avg, max, percentile)
sort정렬
limit최대 결과 수
bin(5m)시간 버킷

Logs Insights 비용 주의 #

쿼리 시 스캔한 데이터 GB 당 과금됩니다(~$0.005/GB). 큰 로그 그룹을 무제한 시간으로 쿼리하면 비용 사고가 납니다. 항상 시간 범위를 좁게 둡니다.

CloudWatch Metrics #

메트릭은 시계열 숫자입니다. AWS의 거의 모든 서비스가 자동 송신합니다.

자주 보는 메트릭 #

서비스자주 보는 메트릭
EC2CPUUtilization, NetworkIn/Out, DiskReadOps
RDSCPUUtilization, DatabaseConnections, FreeStorageSpace, ReadLatency
LambdaInvocations, Errors, Duration, Throttles, ConcurrentExecutions
ECSCPUUtilization, MemoryUtilization (Service / Task 별)
ALBRequestCount, TargetResponseTime, HTTPCode_Target_5XX_Count
API GatewayCount, Latency, 4XXError, 5XXError
S3BucketSizeBytes, NumberOfObjects (1일 1회)
DynamoDBConsumedReadCapacity/WriteCapacity, ThrottledRequests

메트릭의 차원 (Dimensions) #

같은 메트릭이라도 차원으로 쪼개집니다.

예: CPUUtilization
Service: AWS/EC2
Metric:  CPUUtilization
Dimensions:
  - InstanceId: i-1234567890
  - InstanceId: i-2345678901
  - InstanceId: i-3456789012

차원이 다르면 별도 메트릭입니다. 메트릭 수가 곧 비용이라 차원이 폭발하면 비용 사고가 납니다.

통계 (Statistic) #

통계무엇
Sum합계 — Invocations, RequestCount
Average평균 — CPU, Latency
Maximum최대 — Spike 감지
Minimum최소
p95 / p99백분위수 — Latency
SampleCount데이터 포인트 수

대부분의 경우 Average + p95가 의미 있습니다. p99 / p99.9는 SLA와 사용자 경험에 직접 영향을 줍니다.

표준 vs 고해상도 #

종류해상도비용
표준1분표준
고해상도1초고가 — 스파이크 짧은 경우만

대부분 표준 1분으로 충분합니다.

커스텀 메트릭 보내기 #

애플리케이션이 직접 송신합니다.

Python — boto3
import boto3

cloudwatch = boto3.client("cloudwatch")
cloudwatch.put_metric_data(
    Namespace="MyApp",
    MetricData=[{
        "MetricName": "OrderCreated",
        "Value": 1,
        "Unit": "Count",
        "Dimensions": [
            {"Name": "Environment", "Value": "prod"},
            {"Name": "Region", "Value": "ap-northeast-2"},
        ],
    }],
)

비용은 메트릭당 $0.30 / 월이고 차원의 조합마다 별도입니다. 사용자 ID 같은 고카디널리티 차원은 절대 금지합니다.

EMF (Embedded Metric Format) — Lambda 용 패턴 #

Lambda에서는 put_metric_data 호출 자체가 비용과 지연 부담입니다. 로그에 특정 JSON 형식으로 적으면 CloudWatch가 자동으로 메트릭으로 변환합니다.

EMF 형식
import json
print(json.dumps({
    "_aws": {
        "Timestamp": int(time.time() * 1000),
        "CloudWatchMetrics": [{
            "Namespace": "MyApp",
            "Dimensions": [["Environment"]],
            "Metrics": [{"Name": "OrderCreated", "Unit": "Count"}],
        }],
    },
    "Environment": "prod",
    "OrderCreated": 1,
}))

aws-embedded-metrics-python 같은 SDK가 이걸 더 깔끔하게 도와줍니다.

Metric Filter — 로그에서 메트릭 만들기 #

이미 로그에 있는 정보(ERROR 발생, 응답 시간 등)를 메트릭으로 변환합니다.

콘솔에서 만들기
CloudWatch → Log groups → 그룹 선택 → Metric filters → Create
- Filter pattern: ERROR
- Metric namespace: MyApp
- Metric name: ErrorCount
- Metric value: 1

이제 ERROR가 한 번 발생할 때마다 메트릭이 +1 됩니다. 알람이나 대시보드에 활용할 수 있습니다.

Filter pattern 예
ERROR                       # ERROR 단어 포함
[..., level="ERROR", ...]   # 구조화된 로그의 필드
{ $.level = "ERROR" }       # JSON 로그의 키

CloudWatch Alarms #

메트릭이 임계를 넘으면 액션을 합니다. 알림의 본진입니다.

첫 알람 — Lambda Errors #

콘솔
CloudWatch → Alarms → Create alarm
- Metric: AWS/Lambda → Errors → Function: my-function
- Statistic: Sum
- Period: 1 minute
- Threshold: > 0 for 1 datapoint within 5 minutes
- Action: SNS → 알림 토픽
- Name: lambda-my-function-errors

Alarm의 상태 #

상태의미
OK임계 안
ALARM임계 초과 — 액션 발생
INSUFFICIENT_DATA데이터 부족 — 새로 만든 경우 / 메트릭 안 옴

INSUFFICIENT_DATA를 알람 처리(알림)할지는 옵션입니다. 새 알람 평가 중에 자주 뜨는 상태라 일반적으로는 무시합니다.

Composite Alarms #

여러 알람의 AND / OR로 조합합니다. “ALB 5xx ≥ 1% AND CPU > 80%” 같은 패턴입니다.

조합 예
ALARM("alb-5xx") AND ALARM("ec2-high-cpu")

오탐을 줄이는 데 효과적입니다.

Alarm 액션 #

액션무엇
SNS Topic이메일 / Slack / SMS / Lambda 등으로 fanout
EC2 Action인스턴스 stop / terminate / reboot / recover
Auto ScalingASG 스케일 in / out
Systems ManagerOpsItem 만들기

운영의 90%는 SNS → Slack / 이메일입니다.

Anomaly Detection #

기준선(band)을 자동으로 학습한 뒤 그 밖이면 알람을 냅니다. 트래픽이나 CPU처럼 패턴이 있는 메트릭에 효과적이며 정적 임계값보다 오탐이 적습니다.

SNS 통합 — 알림을 보내는 방법 #

대부분의 알람이 SNS Topic으로 가고, 거기서 다음 단계로 fanout 합니다.

구독어디로
Email이메일
HTTPSSlack incoming webhook
Lambda가공 후 다른 단계
SMS휴대폰 (드물게)
SQS큐로

Slack 연동 — Lambda 패턴 #

직접 webhook으로 보내거나, AWS Chatbot으로 보냅니다.

Lambda — SNS → Slack 변환
import json, os, urllib.request

WEBHOOK = os.environ["SLACK_WEBHOOK"]

def handler(event, context):
    msg = json.loads(event["Records"][0]["Sns"]["Message"])
    payload = json.dumps({
        "text": f"🚨 *{msg['AlarmName']}* — {msg['NewStateValue']}",
        "blocks": [...]
    }).encode()
    req = urllib.request.Request(WEBHOOK, data=payload,
                                  headers={"Content-Type": "application/json"})
    urllib.request.urlopen(req)

18장 API Gateway와 Lambda19장 EventBridge / SQS / SNS에서 더 깊게 다룹니다.

CloudWatch Dashboards #

위젯 페이지입니다. 팀 / 서비스별 한눈 보기에 씁니다. JSON으로 정의해 코드로 관리할 수 있습니다.

자주 만드는 대시보드 #

종류무엇
서비스 대시보드한 서비스의 핵심 메트릭 (요청, 지연, 에러, 인프라)
인프라 대시보드EC2/RDS의 CPU / 메모리 / 네트워크
비즈니스 대시보드가입 / 결제 / 주문 같은 비즈니스 메트릭
온콜 대시보드활성 알람 / 최근 사고 / 핵심 지표

위젯 종류 #

  • 메트릭 그래프(line, stacked, number)
  • 로그(Logs Insights 쿼리 결과)
  • 텍스트(Markdown — 대시보드 안내)
  • Alarm status

좋은 대시보드는 “이 한 페이지를 30초 보면 시스템 상태를 안다"가 되는 것입니다.

가입 직후 켜야 할 설정 #

1부가 끝나는 시점에는 다음 설정들이 갖춰져 있어야 합니다.

항목어디서
새 로그 그룹에 retention 자동 적용콘솔 / EventBridge + Lambda
Lambda Errors 알람함수마다
RDS FreeStorageSpace 알람DB마다
ALB 5xx 알람LB마다
빌링 알람 (3장 비용 관리)계정 단위
GuardDuty findings 알람 (6장 보안 기본)계정 단위

이 여섯 가지가 작은 운영의 알림 기반입니다.

자주 만나는 함정 #

  • 로그 retention 영구 — 가장 흔한 비용 사고입니다. 로그 그룹마다 retention을 명시하고 새 그룹은 자동화합니다. 이 한 줄이 비용을 절반 이상 절감합니다.
  • 고카디널리티 커스텀 메트릭Dimensions: [{Name: 'UserId', Value: user_id}]처럼 두면 사용자 1만 명일 때 메트릭 1만 개 × 차원 조합으로 한 달 $3000+ 가 됩니다. 사용자별은 로그(Logs Insights)가 답입니다.
  • Logs Insights 무제한 시간 쿼리 — 큰 로그 그룹에 시간 범위를 안 정하면 GB 단위 스캔 비용이 듭니다. 항상 시간 범위를 좁게 둡니다.
  • Alarm의 Period 너무 짧음 — 1분 1 데이터포인트로 알람을 걸면 일시적 spike 마다 알람이 폭주합니다. 보통 5분 / 3 데이터포인트 정도가 노이즈를 적당히 줄입니다.
  • Alarm 액션 안 붙임 — 알람을 만들고 SNS나 액션을 안 붙이면 콘솔에서만 빨갛게 됩니다. 아무도 모릅니다. 만들 때 액션을 같이 붙입니다.
  • 대시보드만 만들고 안 봄 — 만든 직후엔 모두 보지만 시간이 지나면 잊힙니다. 온콜이나 일일 standup의 첫 체크 항목으로 정착시킵니다.
  • Metric Math 미사용 — 여러 메트릭의 비율 / 합계 / 변환을 계산할 수 있는 Metric Math가 있습니다. “5xx / 총 요청 = 에러율” 같은 계산입니다. 잘 쓰면 대시보드와 알람이 훨씬 깔끔합니다.

연습문제 #

  1. §“Retention — 가장 중요한 설정"의 일괄 적용 스크립트를 본인 환경에서 dry-run으로 읽어 보고, 이 한 줄이 3장 비용 관리의 “로그 폭주” 사고를 어떻게 막는지 한 단락으로 설명해 보세요.
  2. §“CloudWatch Metrics"의 자주 보는 메트릭 표에서 Lambda와 ALB 행을 골라, 각각 어떤 메트릭에 알람을 걸어야 첫 운영 사고를 잡을 수 있는지 §“가입 직후 켜야 할 설정” 표와 연결해 적어 보세요.
  3. §“고카디널리티 커스텀 메트릭” 함정을 근거로, 사용자별 주문 수를 추적하고 싶을 때 커스텀 메트릭 대신 Logs Insights를 써야 하는 이유를 비용 관점에서 설명해 보세요.

한 줄 요약: CloudWatch는 Logs · Metrics · Alarms · Dashboards 네 구성으로 운영의 눈이 되며, 로그 → 메트릭 → 알람 → 대시보드로 한 흐름을 이룬다. 로그 retention을 명시하지 않으면 비용이 폭주하니 가입 직후 설정이 필수다. 메트릭은 차원 수가 곧 비용이라 고카디널리티 차원을 금지하고, 알람은 SNS 액션을 반드시 붙여야 의미가 있다.

다음 챕터 #

이로써 1부 AWS 시작이 끝났습니다. 콘솔 / 계정 / IAM / 비용 / CLI / SSO / 보안 / CloudWatch — AWS 위에서 무언가를 시작하는 데 필요한 도구상자가 한 곳에 모였습니다. 이제 진짜 자원을 만들 차례입니다. 2부의 첫 챕터인 8장 EC2와 VPC에서는 가상 머신 EC2와, 그 EC2가 사는 가상 네트워크 VPC — Subnet / Internet Gateway / Route Table / Security Group / NACL — 의 구조를 한 줄에 정리합니다.

X