티스토리 뷰

매달 초가 되면 저는 습관처럼 AWS 청구서를 엽니다. 예전 회사에서 월 청구액이 예상보다 40% 넘게 튀어나온 적이 있었는데, 그때 원인을 추적하면서 알게 된 게 하나 있습니다. AWS 요금은 큰 실수 하나로 터지는 게 아니라, 아무도 안 보는 작은 낭비들이 조용히 쌓여서 터진다는 겁니다.

이번 글은 제가 실무에서 실제로 잡아냈던 AWS 비용 낭비 포인트들을 정리한 것입니다. 콘솔에서 바로 확인할 수 있는 것들 위주라, 오늘 점심시간에 하나씩 열어보면서 따라 해볼 수 있는 수준으로 썼습니다.

사진: Unsplash의 Growtika

0. 시작은 무조건 비용 가시화부터

비용 절감 얘기를 하면 다들 인스턴스 줄이는 것부터 떠올리는데, 순서가 틀렸습니다. 뭐가 얼마나 나가는지 모르는 상태에서 줄이는 건 감으로 하는 다이어트와 같습니다.

제가 새 계정을 맡으면 제일 먼저 하는 세 가지입니다.

  • Cost Explorer 활성화: 서비스별, 리전별, 태그별로 어디서 돈이 새는지 그래프로 보입니다. 활성화 자체는 무료입니다.
  • AWS Budgets 알람: 월 예산을 잡고 50%, 80%, 100% 도달 시 메일이 오게 겁니다. 5분이면 설정하는데, 이거 하나로 "월말에 청구서 보고 놀라는" 상황은 사라집니다.
  • 비용 할당 태그: 리소스마다 프로젝트/환경(prod, dev) 태그를 붙입니다. 태그가 없으면 "이 비용이 어느 서비스 건지"를 아무도 답 못 하는 순간이 반드시 옵니다.

이 세 개가 깔려 있어야 아래 항목들을 점검할 때 효과가 숫자로 보입니다.

1. EC2: 켜져 있는 것 자체가 돈이다

EC2는 대부분 조직에서 청구서의 가장 큰 덩어리입니다. 그런데 의외로 절감 포인트는 단순한 데 있습니다.

개발/스테이징 서버는 퇴근하면 끕니다. 평일 9시부터 21시까지만 켜도 한 달 가동 시간이 730시간에서 260시간 수준으로 떨어집니다. 인스턴스 요금이 3분의 1이 되는 셈입니다. EventBridge 스케줄러와 Lambda 몇 줄이면 자동으로 켜고 끌 수 있고, Instance Scheduler라는 AWS 공식 솔루션도 있습니다. 저희 팀은 이걸 적용하고 개발 계정 EC2 비용이 실제로 60% 넘게 줄었습니다.

인스턴스 세대를 올리는 것도 절감입니다. 같은 사양이면 신형 세대가 대체로 더 싸거나 성능이 좋습니다. 특히 Graviton(ARM) 계열은 동급 x86 대비 가격 대비 성능이 눈에 띄게 낫습니다. 저는 처음에 "ARM으로 바꾸면 뭔가 안 돌아가지 않을까" 걱정했는데, 요즘 웹 애플리케이션 스택은 웬만하면 그냥 돌아갑니다. 도커 이미지만 멀티 아키텍처로 빌드해두면 전환 부담이 크지 않았습니다.

1년 이상 켜둘 게 확실한 서버는 Savings Plans를 겁니다. 온디맨드 대비 대략 30~40% 아낍니다. 다만 약정은 "확실한 것만, 보수적으로"가 원칙입니다. 트래픽이 어떻게 될지 모르는 신규 서비스에 3년 약정부터 거는 건 절감이 아니라 도박입니다.

2. EBS: gp2로 남아 있는 볼륨은 그냥 손해

은근히 많이 놓치는 항목입니다. EBS 볼륨 타입이 아직 gp2라면 gp3로 바꾸는 것만으로 GB당 요금이 약 20% 내려갑니다. gp3는 기본 성능(3000 IOPS)이 보장되기 때문에, 소형 볼륨에서는 오히려 gp2보다 성능이 좋아지는 경우도 많습니다. 무중단으로 변경 가능해서 사실상 리스크 없는 절감입니다.

하나 더, 주인 잃은 볼륨과 스냅샷입니다. 인스턴스를 종료해도 EBS 볼륨이 남는 설정이었다면, 콘솔에서 상태가 available인 볼륨들이 조용히 과금되고 있을 겁니다. 오래된 AMI와 스냅샷도 마찬가지입니다. 분기에 한 번은 available 볼륨과 연결 안 된 스냅샷을 정리하는 걸 권합니다.

사진: Unsplash의 imgix

3. NAT Gateway: 조용한 과금의 제왕

제가 겪은 비용 사고 중 제일 황당했던 게 이겁니다. NAT Gateway는 시간당 요금에 더해 처리한 데이터 GB당 요금이 붙습니다. 프라이빗 서브넷의 서버들이 S3나 외부 API로 데이터를 많이 보내면, 그 트래픽이 전부 NAT를 통과하면서 요금이 쌓입니다.

당시 저희는 프라이빗 서브넷의 배치 서버가 S3에 대용량 파일을 올리는 구조였는데, 이 트래픽이 몽땅 NAT를 타고 있었습니다. S3와 DynamoDB는 게이트웨이 VPC 엔드포인트가 무료입니다. 엔드포인트 하나 붙이는 것으로 그 트래픽의 NAT 비용이 통째로 사라졌습니다. VPC에 NAT Gateway를 쓰고 있다면 Cost Explorer에서 NatGateway 항목을 꼭 한번 확인해보세요. 생각보다 큰 금액이 잡혀 있는 경우가 많습니다.

4. S3: 수명주기 정책 없이 쌓기만 하면 창고비가 된다

S3는 쌓는 건 쉬운데 치우는 건 아무도 안 합니다. 로그, 백업, 임시 산출물이 Standard 클래스에 몇 년씩 쌓여 있는 버킷을 저는 여러 번 봤습니다.

  • 수명주기(Lifecycle) 정책: 30일 지나면 Standard-IA로, 90일 지나면 Glacier 계열로 내리고, 로그처럼 보존 기한이 있는 건 만료 삭제까지 걸어둡니다.
  • Intelligent-Tiering: 접근 패턴을 예측하기 어려운 버킷은 이걸로 두면 알아서 저렴한 계층으로 옮겨줍니다. 고민할 시간에 이걸 켜는 게 나은 경우가 많습니다.
  • 미완료 멀티파트 업로드 정리: 대용량 업로드가 중간에 실패하면 조각 파일이 보이지 않게 남아 과금됩니다. 수명주기 정책에서 "incomplete multipart upload 7일 후 중단" 규칙은 모든 버킷에 기본으로 넣어두는 게 좋습니다.

5. CloudWatch Logs: 보존 기간 기본값이 '무제한'이다

이건 아는 순간 바로 고치게 되는 항목입니다. CloudWatch 로그 그룹의 보존 기간 기본값은 무기한입니다. Lambda나 ECS를 쓰면 로그 그룹이 자동 생성되는데, 손대지 않으면 로그가 영원히 쌓입니다. 로그 그룹 목록에서 보존 기간을 30일이나 90일로 일괄 지정하는 것만으로 매달 나가던 저장 비용이 잡힙니다. 장기 보존이 필요한 로그는 S3로 내보내서 Glacier로 내리는 게 훨씬 쌉니다.

6. RDS: 스냅샷과 과잉 사양을 의심하라

RDS는 함부로 줄이기 무서운 영역이지만, 그래도 점검할 건 있습니다. CloudWatch에서 CPU와 메모리(FreeableMemory) 지표를 2주 이상 봤을 때 CPU가 늘 10% 아래라면 한 단계 다운사이징을 검토할 만합니다. 수동 스냅샷은 자동 백업과 달리 지우기 전까지 계속 과금되니, "혹시 몰라서" 만들어둔 오래된 수동 스냅샷을 정리합니다. 개발용 RDS는 EC2처럼 야간 중지가 가능합니다(최대 7일). 그리고 프로덕션이 아닌 DB에 멀티 AZ가 켜져 있다면, 그건 비용이 정확히 2배로 나가고 있다는 뜻입니다.

사진: Unsplash의 Recha Oktaviani

7. 데이터 전송 비용: 아키텍처 그림에는 안 보이는 요금

AWS 요금표에서 제일 읽기 어려운 게 데이터 전송입니다. 기억할 것만 추리면 이렇습니다. 들어오는 건 대체로 무료, 나가는 건 유료, 그리고 가용영역(AZ) 간 이동도 유료입니다.

실무에서 자주 걸리는 패턴은 두 가지였습니다. 첫째, 외부로 나가는 정적 콘텐츠를 EC2나 S3에서 직접 서빙하는 경우. CloudFront를 앞에 두면 전송 단가도 내려가고 원본 부하도 줍니다. 둘째, 마이크로서비스끼리 AZ를 넘나들며 통신하는 경우. 같은 AZ 안에서 통신하도록 배치만 조정해도 전송 비용이 내려갑니다. 트래픽이 커질수록 이 차이는 무시 못 할 금액이 됩니다.

번외 1. Lambda: 메모리 설정이 곧 요금 설정이다

서버리스라서 싸다고 생각하고 방치하기 쉬운 게 Lambda입니다. Lambda 요금은 실행 시간 곱하기 할당 메모리로 계산되는데, 재미있는 건 메모리를 올리면 CPU도 같이 올라가서 실행 시간이 줄어든다는 점입니다. 그래서 메모리 128MB로 아껴 쓴다고 설정한 함수가, 512MB로 올린 함수보다 오히려 비싼 경우가 실제로 있습니다. 실행 시간이 4배 넘게 걸리면 손해거든요.

AWS Lambda Power Tuning이라는 오픈소스 도구를 쓰면 메모리 구간별 비용과 속도를 그래프로 뽑아줍니다. 저는 호출량 많은 함수 몇 개만 이걸로 점검했는데, 함수 두 개는 메모리를 올리는 게 더 싸다는 결과가 나왔습니다. "메모리를 올렸더니 요금이 내려간다"는 건 직접 보기 전엔 잘 안 믿기는 경험입니다.

또 하나, Lambda가 같은 VPC 안의 RDS를 붙는 구조라면 앞서 말한 NAT Gateway 비용과 CloudWatch 로그 비용이 함께 따라온다는 것도 기억해둘 필요가 있습니다. 서버리스 비용 사고는 함수 자체보다 주변 리소스에서 나는 경우가 더 많았습니다.

번외 2. 재발 방지: 사람 눈 말고 알람에게 맡겨라

한 번 정리하고 끝내면 6개월 뒤에 똑같은 낭비가 다시 쌓여 있습니다. 사람이 계속 들여다보는 건 지속 가능하지 않아서, 저는 감시를 시스템에 넘기는 쪽으로 정리했습니다.

  • Cost Anomaly Detection: 평소 패턴에서 벗어난 비용 급증을 잡아서 알려줍니다. 무료고, 설정도 몇 분이면 끝납니다. 특정 서비스 요금이 갑자기 튀는 사고는 월말 청구서가 아니라 이 알람으로 먼저 알게 되는 게 정상입니다.
  • Trusted Advisor / Compute Optimizer: 유휴 리소스, 과잉 사양 인스턴스를 자동으로 짚어줍니다. 분기 점검 때 이 리포트부터 열면 어디를 볼지 고민할 필요가 없습니다.
  • 태그 정책 강제: 태그 없는 리소스는 생성 단계에서 막거나, 최소한 주간 리포트로 잡아냅니다. 비용 추적의 절반은 태그 규율에서 나옵니다.

팀에 공유할 때는 "아끼자"라는 구호보다 숫자 하나를 보여주는 게 효과적이었습니다. 개발 서버 야간 중지 하나로 월 얼마가 줄었는지 슬랙에 공유했더니, 그다음부터는 팀원들이 먼저 "이 인스턴스 스케줄 걸까요?"라고 물어보기 시작했습니다.

점검 체크리스트 요약

위 내용을 실제 점검 순서로 정리하면 이렇습니다.

  1. Cost Explorer, Budgets 알람, 비용 태그부터 세팅한다.
  2. 개발/스테이징 EC2에 야간·주말 자동 중지를 건다.
  3. gp2 볼륨을 gp3로 바꾸고, available 볼륨과 고아 스냅샷을 정리한다.
  4. NAT Gateway 트래픽을 확인하고 S3/DynamoDB는 VPC 엔드포인트로 돌린다.
  5. S3 전 버킷에 수명주기 정책과 미완료 멀티파트 정리 규칙을 넣는다.
  6. CloudWatch 로그 그룹 보존 기간을 일괄 지정한다.
  7. RDS 지표를 보고 사양·스냅샷·멀티 AZ를 재검토한다.
  8. 안정 워크로드에만 보수적으로 Savings Plans를 적용한다.

경험상 1~6번까지는 서비스에 영향 없이 적용할 수 있는 것들이고, 이것만으로도 청구서가 두 자릿수 퍼센트로 내려가는 조직이 많습니다.

마치며

AWS 비용 최적화는 한 방이 없습니다. 새는 구멍을 하나씩 막고, 알람으로 재발을 감시하는 반복 작업에 가깝습니다. 저는 매월 첫 주에 30분짜리 "청구서 리뷰" 일정을 캘린더에 박아두는데, 애 셋 학원비 나가는 걸 생각하면 회사 돈이라도 새는 꼴을 못 보는 성격이 된 것 같습니다. 가정 경제든 클라우드든, 결국 가계부 쓰는 사람이 이깁니다.

다음 AWS 글에서는 이번에 짧게 언급한 개발 서버 자동 켜기/끄기를 EventBridge 스케줄러와 Lambda로 구현하는 과정을 코드와 함께 정리해보겠습니다.

댓글


최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday