AWS CUR 기반 비용 시각화 파이프라인 구현
리소스 사용 증가나 예상치 못한 비용 폭증을 빠르게 감지하기 위해
AWS CUR → S3 → Glue → Athena → Grafana로 이어지는 비용 시각화 파이프라인을 구축한 과정을 정리
AWS CUR S3 Glue Crawler Athena Grafana IAM Role
1. 왜 비용 시각화 파이프라인이 필요한가?
AWS 콘솔의 Billing Dashboard나 Cost Explorer도 비용 확인에 쓸 수 있지만 몇 가지 한계가 있습니다.
- 갱신 지연 — Cost Explorer는 최대 24~48시간 지연이 발생할 수 있어 당일 비용 급증을 즉시 파악하기 어렵습니다.
- 커스텀 대시보드 한계 — 리소스별 비용 분포, 일별 누적 추이 등을 원하는 형태로 조합하려면 별도 시각화 도구가 필요합니다.
- 운영 대시보드와의 통합 — 인프라 모니터링(Prometheus + Grafana)과 비용 모니터링을 하나의 Grafana에서 함께 보면 운영 판단이 훨씬 빨라집니다.
이런 이유로 AWS CUR(Cost and Usage Report)을 데이터 소스로 활용하고 Glue + Athena로 쿼리 가능한 상태를 만든 뒤 Grafana로 시각화하는 파이프라인을 설계했습니다.
2. 파이프라인 아키텍처
전체 데이터 흐름은 다음과 같습니다.

| 구성 요소 | 역할 |
|---|---|
| AWS CUR | 매일 00:00에 계정의 전체 비용·사용량 데이터를 CSV/Parquet 형식으로 생성 |
| S3 | CUR 리포트 원본 파일을 저장하는 데이터 레이크 역할 |
| Glue Crawler | S3에 저장된 CUR 파일을 크롤링하여 테이블 스키마를 자동으로 추출·갱신 |
| Athena | Glue 카탈로그 기반으로 S3 데이터를 SQL로 쿼리 (서버리스) |
| Grafana | Athena를 데이터소스로 연결하여 비용 대시보드 시각화 |
3. 구축 과정
3-1. CUR(Cost and Usage Report) 설정
AWS Billing 콘솔에서 CUR을 생성합니다.
- Report name — 식별 가능한 이름 지정 (예:
daily-cost-report) - Time granularity —
Daily(일별 비용 추이 확인 목적) - Report data integration —
Amazon Athena선택 (Parquet 포맷 + Athena 통합 자동 구성) - S3 bucket — 리포트가 저장될 전용 버킷 지정
💡 Athena 통합을 선택하면
CUR이 Parquet 포맷으로 생성되고 S3 경로에 Athena용 CloudFormation 템플릿(crawler-cfn.yml)이 함께 제공됩니다. 이 템플릿을 활용하면 Glue Crawler와 데이터베이스를 자동으로 구성할 수 있습니다.
CUR은 설정 후 첫 리포트가 생성되기까지 최대 24시간이 소요될 수 있습니다.
이후부터는 매일 00:00(KST)에 자동으로 S3에 새 데이터가 적재됩니다.
3-2. S3 버킷 구조
CUR이 S3에 저장되면 아래와 같은 경로 구조가 만들어집니다.
s3://<BUCKET_NAME>/<PREFIX>/<REPORT_NAME>/
├── <REPORT_NAME>-00001.snappy.parquet
├── <REPORT_NAME>-00002.snappy.parquet
├── ...
└── crawler-cfn.yml
Parquet 포맷은 CSV 대비 파일 크기가 작고 Athena 쿼리 성능이 훨씬 빠릅니다.
비용 데이터가 누적되면 스캔량 차이가 곧 Athena 비용 차이로 이어지므로 Parquet 선택을 권장합니다.
3-3. Glue Crawler 설정
Glue Crawler가 S3의 CUR 데이터를 크롤링하여 Athena에서 쿼리 가능한 테이블을 생성합니다.
- Data source — CUR이 저장된 S3 경로 지정
- Database — Athena에서 사용할 데이터베이스 이름 지정 (예:
cur_database) - Schedule — CUR 갱신 주기에 맞춰 일 1회 실행 (예: 매일 01:00 KST, CUR 생성 후 1시간 여유)
Crawler가 실행되면 S3의 Parquet 파일 구조를 분석해서 컬럼명, 데이터 타입 등의 스키마를 자동으로 Glue Data Catalog에 등록합니다.
이후 CUR 구조가 변경되더라도 Crawler가 재실행되면 스키마가 자동으로 갱신됩니다.
3-4. Athena 쿼리 확인
Glue Crawler가 정상 실행되면 Athena 콘솔에서 바로 SQL 쿼리를 실행할 수 있습니다.
-- 일별 총 비용 확인
SELECT
DATE(line_item_usage_start_date) AS usage_date,
ROUND(SUM(line_item_unblended_cost), 2) AS daily_cost
FROM cur_database.cost_report
WHERE line_item_line_item_type = 'Usage'
GROUP BY DATE(line_item_usage_start_date)
ORDER BY usage_date DESC
LIMIT 30;
-- 리소스(서비스)별 비용 분포
SELECT
line_item_product_code AS service,
ROUND(SUM(line_item_unblended_cost), 2) AS total_cost
FROM cur_database.cost_report
WHERE line_item_line_item_type = 'Usage'
AND DATE(line_item_usage_start_date) = CURRENT_DATE - INTERVAL '1' DAY
GROUP BY line_item_product_code
ORDER BY total_cost DESC;
✅ Athena 비용 팁
Athena는 스캔한 데이터량 기준으로 과금됩니다(1TB당 $5)
Parquet 포맷을 사용하면 필요한 컬럼만 읽어 스캔량을 대폭 줄일 수 있고 WHERE 절로 날짜 범위를 제한하면 추가로 비용을 절감할 수 있습니다.
3-5. IAM Role 생성 및 Grafana 연동
Grafana에서 Athena 데이터소스에 접근하려면 적절한 권한을 가진 IAM Role이 필요합니다.
IAM Policy 주요 권한:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"athena:GetQueryExecution",
"athena:GetQueryResults",
"athena:StartQueryExecution",
"athena:StopQueryExecution"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"glue:GetTable",
"glue:GetDatabase",
"glue:GetPartitions"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::<CUR_BUCKET_NAME>",
"arn:aws:s3:::<CUR_BUCKET_NAME>/*",
"arn:aws:s3:::<ATHENA_RESULTS_BUCKET>",
"arn:aws:s3:::<ATHENA_RESULTS_BUCKET>/*"
]
}
]
}
IAM Role을 생성한 뒤 Grafana의 Athena 데이터소스 설정에서 Assume Role ARN에 해당 Role의 ARN을 입력합니다.
S3 권한에는 CUR 원본 버킷뿐 아니라 Athena 쿼리 결과가 저장되는 버킷(보통 aws-athena-query-results-*)도 포함해야 합니다.
3-6. Grafana 대시보드 구성
Athena 데이터소스가 연결되면 SQL 쿼리를 기반으로 세 가지 핵심 패널을 구성합니다.
① Daily Cost (일별 비용 추이)
일별 총 비용을 Time Series 패널로 표시합니다. 비용이 갑자기 튀는 날이 있으면 한눈에 파악할 수 있습니다.
SELECT
DATE(line_item_usage_start_date) AS time,
ROUND(SUM(line_item_unblended_cost), 2) AS daily_cost
FROM cur_database.cost_report
WHERE line_item_line_item_type = 'Usage'
GROUP BY DATE(line_item_usage_start_date)
ORDER BY time
② Cumulative Cost (월 누적 비용)
해당 월의 누적 비용을 표시하여 월 예산 대비 현재 소진율을 확인합니다.
SELECT
DATE(line_item_usage_start_date) AS time,
ROUND(SUM(SUM(line_item_unblended_cost)) OVER (ORDER BY DATE(line_item_usage_start_date)), 2) AS cumulative_cost
FROM cur_database.cost_report
WHERE line_item_line_item_type = 'Usage'
AND YEAR(line_item_usage_start_date) = YEAR(CURRENT_DATE)
AND MONTH(line_item_usage_start_date) = MONTH(CURRENT_DATE)
GROUP BY DATE(line_item_usage_start_date)
ORDER BY time
③ Resource별 비용 분포 (Pie Chart)
EC2, EBS, RDS, S3, ELB 등 서비스별 비용 비중을 Pie Chart로 시각화하여 어느 서비스에 비용이 집중되는지 파악합니다.
SELECT
line_item_product_code AS service,
ROUND(SUM(line_item_unblended_cost), 2) AS total_cost
FROM cur_database.cost_report
WHERE line_item_line_item_type = 'Usage'
AND DATE(line_item_usage_start_date) >= CURRENT_DATE - INTERVAL '7' DAY
GROUP BY line_item_product_code
HAVING SUM(line_item_unblended_cost) > 0
ORDER BY total_cost DESC

4. 전체 파이프라인 동작 흐름
파이프라인이 구축되면 매일 자동으로 다음 순서로 동작합니다.
- 00:00 KST — AWS CUR이 전일 비용 데이터를 Parquet 포맷으로 S3에 적재
- 01:00 KST — Glue Crawler가 S3를 크롤링하여 Data Catalog 스키마 갱신
- 이후 — Grafana 대시보드 접속 시 Athena가 최신 데이터를 쿼리하여 시각화
사람이 개입할 필요 없이 전 과정이 자동으로 돌아갑니다. CUR 데이터가 S3에 쌓이기만 하면 Glue → Athena → Grafana 순서로 자동 반영됩니다.
5. 성과 정리
| 항목 | 도입 전 | 도입 후 |
|---|---|---|
| 비용 확인 방식 | AWS 콘솔 수동 접속 | Grafana 대시보드 자동 시각화 |
| 확인 주기 | 필요할 때 수동 확인 | 매일 자동 갱신 |
| 리소스별 분석 | Cost Explorer에서 수동 필터링 | Pie Chart로 즉시 확인 (EC2, EBS, RDS, S3, ELB 등) |
| 비용 이상 탐지 | 사후 인지 | 일별 추이 그래프로 폭증 조기 감지 |
| 운영 통합 | 비용/인프라 모니터링 분리 | 하나의 Grafana에서 통합 관리 |
마무리
AWS CUR → S3 → Glue → Athena → Grafana 파이프라인은 한 번 구축하면 추가 운영 비용 없이(Athena 쿼리 비용 제외) 지속적으로 비용 데이터를 시각화할 수 있는 구조입니다.
특히 이미 인프라 모니터링용 Grafana가 운영 중이라면 Athena 데이터소스만 추가하면 비용 대시보드를 바로 붙일 수 있어서 구축 비용 대비 효과가 큽니다. 일별 비용 추이와 리소스별 분포를 한눈에 확인할 수 있게 되면 예상치 못한 비용 폭증을 조기에 감지하고 빠르게 대응할 수 있습니다.
'Project' 카테고리의 다른 글
| Prometheus + Grafana 모니터링 & Slack 알람 구축 (0) | 2026.05.04 |
|---|