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 Stream | Lambda 실행 환경 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일 |
aws logs put-retention-policy \
--log-group-name /aws/lambda/my-function \
--retention-in-days 30aws 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 로그 보내기 #
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 설치가 필요합니다.
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 100fields @timestamp, @message
| filter @message like /ERROR/
| sort @timestamp desc
| limit 50fields @timestamp, @duration
| filter @type = "REPORT"
| stats avg(@duration), max(@duration), count(*) by bin(5m)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의 거의 모든 서비스가 자동 송신합니다.
자주 보는 메트릭 #
| 서비스 | 자주 보는 메트릭 |
|---|---|
| EC2 | CPUUtilization, NetworkIn/Out, DiskReadOps |
| RDS | CPUUtilization, DatabaseConnections, FreeStorageSpace, ReadLatency |
| Lambda | Invocations, Errors, Duration, Throttles, ConcurrentExecutions |
| ECS | CPUUtilization, MemoryUtilization (Service / Task 별) |
| ALB | RequestCount, TargetResponseTime, HTTPCode_Target_5XX_Count |
| API Gateway | Count, Latency, 4XXError, 5XXError |
| S3 | BucketSizeBytes, NumberOfObjects (1일 1회) |
| DynamoDB | ConsumedReadCapacity/WriteCapacity, ThrottledRequests |
메트릭의 차원 (Dimensions) #
같은 메트릭이라도 차원으로 쪼개집니다.
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분으로 충분합니다.
커스텀 메트릭 보내기 #
애플리케이션이 직접 송신합니다.
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가 자동으로 메트릭으로 변환합니다.
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 됩니다. 알람이나 대시보드에 활용할 수 있습니다.
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-errorsAlarm의 상태 #
| 상태 | 의미 |
|---|---|
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 Scaling | ASG 스케일 in / out |
| Systems Manager | OpsItem 만들기 |
운영의 90%는 SNS → Slack / 이메일입니다.
Anomaly Detection #
기준선(band)을 자동으로 학습한 뒤 그 밖이면 알람을 냅니다. 트래픽이나 CPU처럼 패턴이 있는 메트릭에 효과적이며 정적 임계값보다 오탐이 적습니다.
SNS 통합 — 알림을 보내는 방법 #
대부분의 알람이 SNS Topic으로 가고, 거기서 다음 단계로 fanout 합니다.
| 구독 | 어디로 |
|---|---|
| 이메일 | |
| HTTPS | Slack incoming webhook |
| Lambda | 가공 후 다른 단계 |
| SMS | 휴대폰 (드물게) |
| SQS | 큐로 |
Slack 연동 — Lambda 패턴 #
직접 webhook으로 보내거나, AWS Chatbot으로 보냅니다.
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와 Lambda와 19장 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 / 총 요청 = 에러율” 같은 계산입니다. 잘 쓰면 대시보드와 알람이 훨씬 깔끔합니다.
연습문제 #
- §“Retention — 가장 중요한 설정"의 일괄 적용 스크립트를 본인 환경에서 dry-run으로 읽어 보고, 이 한 줄이 3장 비용 관리의 “로그 폭주” 사고를 어떻게 막는지 한 단락으로 설명해 보세요.
- §“CloudWatch Metrics"의 자주 보는 메트릭 표에서 Lambda와 ALB 행을 골라, 각각 어떤 메트릭에 알람을 걸어야 첫 운영 사고를 잡을 수 있는지 §“가입 직후 켜야 할 설정” 표와 연결해 적어 보세요.
- §“고카디널리티 커스텀 메트릭” 함정을 근거로, 사용자별 주문 수를 추적하고 싶을 때 커스텀 메트릭 대신 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 — 의 구조를 한 줄에 정리합니다.