청구서 폭탄 원인 분석: EC2는 안 썼는데 요금이 나올 때 확인할 5가지

EC2 인스턴스를 모두 종료하거나 사용하지 않았다고 확신했음에도 불구하고, 매월 AWS 청구서에서 예상치 못한 요금(소위 ‘청구서 폭탄’)이 발생하는 경우가 있습니다. 이는 컴퓨팅 자원(EC2) 외에 네트워크, 스토리지, 관리 서비스 등 영구적으로 실행되거나 사용량에 따라 과금되는 숨어있는 요소가 남아있기 때문입니다. EC2 요금이 없는데도 과금이 될 때 반드시 확인해야 할 5가지 항목과 과금 원리를 분석합니다.

숨은 과금 원리: “EC2는 꺼도, 나머지는 살아있다”

카테고리과금 방식EC2 종료 후에도 과금 여부
스토리지GB-월 (EBS, 스냅샷)
네트워크GB 전송 (NAT, VPC Flow Logs)
데이터베이스시간/요청 (RDS, DynamoDB)
관리 서비스요청/시간 (CloudWatch, Config)
기타리소스 유지 (ELB, EIP)

반드시 확인해야 할 5가지 항목 (우선순위 순)


1. EBS 볼륨 & 스냅샷 – “EC2 껐지만 디스크는 살아있다” (42%)

항목과금 원리월 예상 비용
EBS 볼륨Available 상태라도 GB-월 과금30GB × $0.10 = $3/월
EBS 스냅샷S3에 저장 → GB-월100GB × $0.05 = $5/월
AMIEBS 스냅샷 기반 → 중복 저장10개 AMI = $50/월

실전 진단 스크립트

bash

#!/bin/bash
echo "EBS 볼륨 & 스냅샷 점검"

# 1. 연결 안 된 EBS 볼륨
echo "[1] Available EBS 볼륨"
aws ec2 describe-volumes --filters Name=status,Values=available --query 'Volumes[*].[VolumeId,Size,AvailabilityZone]' --output table

# 2. 스냅샷 용량
echo "[2] 스냅샷 총 용량"
TOTAL_GB=0
for snap in $(aws ec2 describe-snapshots --owner-ids self --query 'Snapshots[].SnapshotId' --output text); do
  SIZE=$(aws ec2 describe-snapshots --snapshot-ids $snap --query 'Snapshots[].VolumeSize' --output text)
  TOTAL_GB=$((TOTAL_GB + SIZE))
done
echo "총 스냅샷 용량: ${TOTAL_GB}GB → 월 $((TOTAL_GB * 5 / 100)) USD"

사례: EC2 종료 후 EBS 200GB 남음 → 월 $20 청구

2. Elastic IP (EIP) – “할당만 해도 돈 나간다” (28%)

상태과금 여부비용
EC2에 연결무료$0
미할당 (Detached)시간당 과금$0.005/시간 → 월 $3.6

진단 명령어

bash

aws ec2 describe-addresses --query 'Addresses[?InstanceId==null].[PublicIp,AllocationId]' --output table

사례: EIP 5개 미할당 → 월 $18 청구


3. NAT Gateway & VPC Flow Logs – “트래픽 없어도 기본 요금” (18%)

항목과금 원리월 최소 비용
NAT Gateway시간 + GB 처리$32/월 (기본)
VPC Flow LogsGB 로그 저장100GB → $50

진단 스크립트

bash

echo "[3] NAT Gateway"
aws ec2 describe-nat-gateways --query 'NatGateways[*].[NatGatewayId,State,SubnetId]' --output table

echo "[3] Flow Logs 활성 여부"
aws ec2 describe-flow-logs --query 'FlowLogs[?LogDestinationType!=`none`].[FlowLogId,LogGroupName]' --output table

사례: 테스트용 NAT 1개 → 월 $32 청구


4. CloudWatch Logs & Metrics – “로그는 영원하다” (9%)

항목과금 원리예상 비용
로그 저장GB-월50GB → $25
메트릭스Custom Metrics100개 → $30
대시보드월 $3/대시보드5개 → $15

진단

bash

aws logs describe-log-groups --query 'logGroups[?storedBytes>0].[logGroupName,storedBytes]' --output table

5. 기타 영구 서비스 – “깜빡하고 켜둔 서비스들” (3%)

서비스과금 방식확인 명령어
RDS/Aurora시간aws rds describe-db-instances
ElastiCache시간aws elasticache describe-cache-clusters
Elastic Load Balancer시간 + LCUaws elbv2 describe-load-balancers
S3 Glacier Deep ArchiveGB-월aws s3api list-objects-v2 –bucket my-bucket

자동 청구서 폭탄 탐지 스크립트 (매일 실행 추천)

bash

#!/bin/bash
# aws-cost-bomb-detector.sh
echo "숨은 과금 탐지 시작"

echo "1. 미할당 EIP"
aws ec2 describe-addresses --filters "Name=instance-id,Values=" --query 'Addresses[].PublicIp' --output text | wc -l

echo "2. Available EBS"
aws ec2 describe-volumes --filters Name=status,Values=available --query 'sum(Volumes[].Size)' --output text

echo "3. NAT Gateway"
aws ec2 describe-nat-gateways --query 'length(NatGateways[])'

echo "4. 활성 RDS"
aws rds describe-db-instances --query 'length(DBInstances[])'

echo "5. S3 스토리지 (GB)"
aws s3 ls s3://my-bucket --recursive --human-readable --summarize | grep "Total Size"

자동화: EventBridge → Lambda → Slack 알림


예방 조치 – “0원 청구”를 위한 5가지 정책

정책도구효과
EBS 자동 삭제Lifecycle Policy스냅샷 7일 보관
EIP 할당 강제IAM 정책ec2:AllocateAddress 제한
NAT Gateway 태그env=prod 필수테스트용 자동 삭제
CloudWatch 로그 만료30일 자동 삭제90% 비용 절감
Budget Alert$100 초과 → SNS즉시 알림

위 내용은 반드시 확인해야 할 5가지 항목 (우선순위 순)와 이에 대한 예방조치에 대해서 대략적으로 알아봤습니다. 그러면 아래에서 한 번, 구체적으로 원인을 파악하고 분석을 해보겠습니다.


1. 사용 중인 Elastic IP 주소 (EIP)

Elastic IP(EIP)는 동적 클라우드 환경에서 고정된 공인 IP 주소를 제공합니다. EIP 자체는 비용이 들지 않지만, AWS는 IP 고갈을 방지하기 위해 EIP가 EC2 인스턴스에 ‘연결되어 사용 중’이지 않을 때 요금을 부과합니다.

  • 과금 원리: EIP가 할당(Allocated)되어 있지만, 어떤 인스턴스에도 연결(Associated)되어 있지 않은 유휴(Idle) 상태일 경우 시간당 소액의 요금이 발생합니다.
  • 점검 및 조치: VPC 콘솔에서 EIP 목록을 확인하여 Association 열이 비어있는 EIP를 모두 릴리스(Release)해야 합니다.

2. 실행 중인 NAT Gateway (네트워크 주소 변환 게이트웨이)

NAT Gateway는 Private Subnet에 있는 인스턴스가 인터넷으로 아웃바운드 트래픽을 보낼 수 있도록 합니다. 이 서비스는 사용량과 관계없이 프로비저닝된 시간당 요금이 부과됩니다.

  • 과금 원리: NAT Gateway는 인프라 구성 요소로, EC2 인스턴스 유무와 관계없이 시간당 비용이 발생하며, 게이트웨이를 통과하는 데이터 처리량에 대해서도 요금이 부과됩니다.
  • 점검 및 조치: VPC 콘솔의 ‘NAT 게이트웨이’ 섹션을 확인하여 사용하지 않는 게이트웨이는 즉시 삭제(Delete)해야 합니다. 삭제 후 재활성화하는 데 시간이 걸리므로 신중하게 결정해야 합니다.

3. EBS 볼륨 및 스냅샷 (영구 스토리지)

EC2 인스턴스를 종료하더라도, 인스턴스에 연결되어 있던 EBS 볼륨(Volume)이 Delete on Termination 옵션이 false로 설정되어 있었다면, 해당 볼륨은 Available 상태로 남아있게 됩니다.

  • 과금 원리: EBS 볼륨은 데이터가 저장되어 있는 한, 인스턴스의 실행 여부와 관계없이 할당된 용량(GB-월)에 대해 지속적으로 요금이 부과됩니다. 또한, 삭제된 인스턴스의 EBS 스냅샷(Snapshot) 역시 S3에 저장되므로 별도로 요금이 발생합니다.
  • 점검 및 조치: EC2 콘솔의 ‘EBS’ -> ‘볼륨’ 목록을 확인하여 상태가 Available인 불필요한 볼륨은 모두 삭제해야 합니다. ‘스냅샷’ 목록도 확인하여 오래된 스냅샷을 정리해야 합니다.

4. S3 PUT, POST 요청 및 수명 주기 관리

Amazon S3 자체는 저장 용량(GB-월)에 대한 요금이 주를 이루지만, 의외로 비용이 많이 발생하는 부분은 데이터를 업로드/조작하는 API 요청(Request)입니다. EC2는 없지만 서버리스(Lambda 등) 기능이 로그를 S3에 기록하고 있을 수 있습니다.

  • 과금 원리: S3에 데이터를 업로드하는 PUT 요청, 객체를 복사하는 POST 요청, 그리고 객체의 속성을 변경하는 LIST 요청 등은 1,000회당 비용이 발생합니다. 자동화된 백업이나 로그 기록 파이프라인이 계속 실행되면서 이 요청 수가 기하급수적으로 늘어날 수 있습니다.
  • 점검 및 조치: S3 버킷의 Metrics 탭을 확인하여 All RequestsPut Requests의 추이를 확인합니다. 불필요한 수명 주기 규칙(Lifecycle Rule)이 너무 자주 실행되거나, 알 수 없는 프로세스가 지속적으로 S3에 데이터를 업로드하고 있는지 확인해야 합니다.

5. 로드 밸런서 (ALB/NLB) 및 데이터 전송

로드 밸런서(ALB, NLB)는 연결된 EC2 인스턴스가 없어도 프로비저닝된 상태로 유지되는 한 지속적인 비용이 발생합니다. 또한, AWS는 특정 영역(Region, AZ)을 벗어나는 모든 데이터 전송(Data Transfer Out)에 대해 요금을 부과합니다.

  • 과금 원리: 로드 밸런서는 시간당 비용(LCU 또는 시간당 비용)이 발생하며, In-Use 상태가 아니더라도 Provisioned 상태라면 요금이 나옵니다. 또한, EC2 인스턴스 간 통신이더라도 다른 가용 영역(AZ)으로 트래픽이 이동하면 AZ 간 데이터 전송 요금이 발생합니다.
  • 점검 및 조치: EC2 콘솔의 ‘로드 밸런싱’ -> ‘로드 밸런서’ 목록을 확인하여 사용하지 않는 ALB나 NLB는 즉시 삭제해야 합니다. 청구서에서 ‘Data Transfer Out’ 항목의 상세 내역을 확인하여, 데이터 전송이 유독 많은 소스(예: S3, CloudFront)를 추적하여 최적화해야 합니다.

최종 조치: AWS Cost Explorer 확인

예상치 못한 요금을 가장 정확하게 진단하는 방법은 AWS Cost Explorer입니다. Cost Explorer에서 서비스별 요금월별/일별로 시각화하여 확인하고, 가장 높은 비용이 발생하는 서비스(예: EC2, S3, Data Transfer)를 격리한 후 해당 서비스의 구성 요소(EIP, NAT Gateway 등)를 위 체크리스트 순서대로 상세히 확인하면 됩니다.


Disclaimer: 본 블로그의 정보는 개인의 단순 참고 및 기록용으로 작성된 것이며, 개인적인 조사와 생각을 담은 내용이기에 오류가 있거나 편향된 내용이 있을 수 있습니다.