읽는 포인트는 userName(누가), eventTime(언제), sourceIPAddress(어디서), userAgent(어떤 도구로), requestParameters(무엇에). 이 다섯 개만 보면 "admin-user가 CLI로 특정 인스턴스를 종료시켰다"가 한 줄로 복원된다.
처음엔 둘 다 "로그 보는 거 아닌가" 싶었는데, CloudTrail은 행위(API 호출), CloudWatch는 상태(지표·로그)로 축이 완전히 다르다. "EC2가 종료됐다"는 사실은 CloudWatch 지표에서 인스턴스가 사라진 걸로, "누가 종료했나"는 CloudTrail에서 본다.
비유로 정리하니 명확해졌다. CloudTrail = CCTV(누가 언제 무슨 행동을 했는지 기록), CloudWatch = 센서 + 알람(상태를 감지하고 경고).
실무에선 둘을 같이 쓴다. CloudTrail에서 특정 API 호출(예: 보안그룹 변경)을 EventBridge로 잡아 → CloudWatch/SNS로 알림 보내는 식으로 엮으면, "수상한 행위 발생 즉시 통보"가 된다.
항목
CloudTrail
CloudWatch
목적
행위 추적 (무엇을 했는가)
상태 모니터링 (무엇이 일어났는가)
데이터
API 호출 로그
지표(Metrics), 로그(Logs)
예시
EC2 생성, IAM 권한 변경
EC2 CPU 사용률, 로그 이벤트
주 사용처
보안, 감사, 규정 준수
운영, 모니터링, 자동 대응
3. SNS / SQS — 알림의 전달 계층
알람이 울렸을 때 그걸 사람한테 보내는 게 SNS다.
SNS (Simple Notification Service)
Publisher가 SNS Topic에 메시지를 던지면, Topic을 구독한 모든 엔드포인트(Email, SMS, Mobile Push, HTTP(S))로 푸시된다. 일대다 발송이고, 구독자가 여럿이면 동시에 다 받는다.
SQS (Simple Queue Service)
완전 관리형 메시지 큐. SNS와 자주 비교된다.
SNS
SQS
메시지 지속성
X
O (큐에 쌓임)
전송 방식
Push (구독자에게 밀어줌)
Polling (소비자가 가져감)
모델
게시/구독 (1:N)
생산자/소비자 (1:1)
핵심 차이는 지속성과 방향이다. SNS는 던지고 끝(받는 쪽이 없으면 유실), SQS는 큐에 남아 있어서 소비자가 나중에 처리한다. 그래서 트래픽 폭증·장애 흡수가 필요하면 SNS → SQS를 앞에 두는 fan-out 패턴을 쓴다. (SNS Topic이 여러 SQS 큐로 뿌리고, 각 큐 뒤의 워커가 독립적으로 소비)
4. 콘솔 데모 — CloudWatch 알람 + SNS 연동
목표: DynamoDB board 테이블에 쓰기가 발생하면 이메일 알림을 받는다. 흐름: SNS Topic 생성 → 모니터링 대상(DynamoDB) 생성 → 알람 생성 → 테스트
조건(Conditions): Threshold type Static, Greater than 0
알림 수단(SNS): 앞서 만든 mytopic 선택
알람 이름·설명 작성 후 생성
📸 [스크린샷: 알람 생성 직후 상태 — Insufficient data]
4-4. 테스트
board 테이블에 아이템을 하나 넣어 쓰기를 발생시킨다. ConsumedWriteCapacityUnits가 0을 초과하면 알람이 ALARM으로 전환되고, SNS를 통해 이메일이 날아온다.
📸 [스크린샷: 알람 상태 ALARM 전환 + 수신한 경고 이메일]
💡 알람 + SNS 연동에서 막혔던 점
구독 확인을 안 하면 알림이 절대 안 온다. Topic만 만들고 Confirm 메일을 무시한 채로 테스트하면, 알람은 ALARM으로 잘 가는데 이메일이 안 와서 한참 헤맸다. SNS subscription의 Status가 Confirmed인지부터 확인하는 게 먼저다.
알람을 만들자마자 상태가 Insufficient data라 "설정이 틀렸나" 싶었는데, 지표 데이터가 아직 수집 전이라 정상이었다. 쓰기가 한 번 발생하고 Period가 지나야 OK 또는 ALARM으로 평가된다.
임계값을 > 0으로 잡은 건 데모용이라 쓰기가 한 번이라도 일어나면 무조건 울리는 세팅이다. 실무에선 이렇게 하면 알람 폭탄을 맞는다. 정상 트래픽 baseline 위로 의미 있는 임계값을 잡거나, Period·Datapoints to alarm을 조정해서 일시적 스파이크를 걸러내야 한다.
DynamoDB 지표는 온디맨드 모드면 프로비저닝 용량 개념이 없어서ConsumedWriteCapacityUnits 해석이 달라진다. 데모는 용량 단위를 그대로 쓰지만, 실제 테이블 모드에 따라 어떤 지표를 볼지 달라진다는 점은 기억해둘 만하다.
5. CLI로 가능
콘솔로 한 작업은 전부 CLI로도 된다. 반복 세팅이나 IaC 직전 단계에선 CLI가 빠르다. 위 데모를 명령으로 옮기면 이렇다.
SNS Topic 생성 + 구독
# Topic 생성 (출력된 TopicArn을 이후 단계에 사용)
aws sns create-topic --name mytopic
# 이메일 구독 (실행 후 메일함에서 Confirm 필요)
aws sns subscribe \
--topic-arn arn:aws:sns:ap-northeast-2:123456789012:mytopic \
--protocol email \
--notification-endpoint me@example.com
# 구독 상태 확인 (PendingConfirmation → 정상 ARN 으로 바뀌면 확인 완료)
aws sns list-subscriptions-by-topic \
--topic-arn arn:aws:sns:ap-northeast-2:123456789012:mytopic
콘솔은 metric 선택을 트리(DynamoDB → Table Metrics → board)로 클릭하지만, CLI는 --namespace + --metric-name + --dimensions를 직접 명시해야 한다. 네임스페이스와 차원 이름을 정확히 모르면 알람이 만들어져도 데이터가 안 붙는다.aws cloudwatch list-metrics로 실제 존재하는 지표를 먼저 확인하는 게 안전하다.
콘솔에서 SNS Topic 선택은 드롭다운이지만, CLI --alarm-actions는 TopicArn 문자열을 직접 넣어야 한다. ARN을 잘못 적어도 에러 없이 생성되고, 막상 알람이 울려도 알림만 안 온다. 조용히 실패하는 케이스라 주의.
put-metric-alarm은 생성/수정이 같은 명령이다. 동일 이름으로 다시 실행하면 덮어쓴다. 콘솔처럼 "수정" 버튼이 따로 없고, idempotent하게 동작하는 게 자동화엔 오히려 편하다.
학습 정리
CloudWatch는 상태(지표·로그·알람)를, CloudTrail은 행위(API 호출)를 본다. 축이 다르다
CloudWatch 지표는 Namespace + Dimension + Statistic + Period로 식별된다. EC2 기본 수집은 5분, 상세 모니터링 시 1분(+과금)
CloudTrail 관리 이벤트는 기본 무료, 데이터/인사이트 이벤트는 명시적 설정 + 과금. Event History는 90일, 그 이상은 Trail로 S3 저장
알람 → SNS 알림은 구독 Confirm이 안 되면 동작하지 않는다. 새 알람의 Insufficient data는 정상 초기 상태