/툴 리뷰/Loki vs ELK vs CloudWatch Logs 비용 비교 (월 100GB 기준 계산식)
툴 리뷰LokiElasticsearch

Loki vs ELK vs CloudWatch Logs 비용 비교 (월 100GB 기준 계산식)

월 20GB·100GB·500GB 시나리오로 Grafana Loki, Elasticsearch(OpenSearch), CloudWatch Logs의 수집·저장·쿼리·인건비를 계산식 그대로 비교합니다. 검색 성능 차이와 마이그레이션 실패 지점, 3축 의사결정표까지 정리했습니다.

Loki vs ELK vs CloudWatch Logs 비용 비교 (월 100GB 기준 계산식)

로그가 서버보다 비싸지는 순간

로그 비용이 갑자기 튀는 패턴은 실무에서 거의 정해져 있습니다.

  1. 디버그 로그 방치 — 배포 트러블슈팅 때 DEBUG로 올려놓고 되돌리지 않은 서비스 하나가 전체 수집량의 절반을 차지하는 경우.
  2. 보관기간 기본값 — CloudWatch Logs 로그 그룹의 보존 기간을 지정하지 않으면 기본이 "만료되지 않음(Never expire)"입니다. 3년 전 로그가 지금도 과금되고 있을 수 있습니다.
  3. 스캔 과금 구조 — CloudWatch Logs Insights는 쿼리가 스캔한 데이터량에 과금됩니다. 대시보드 자동 새로고침 하나가 조용히 청구서를 올립니다.
  4. 인덱스 오버헤드 — Elasticsearch는 원본 로그보다 인덱스가 더 커지는 경우가 흔합니다(필드 수·매핑 설계에 따라 크게 달라짐).

이 글은 "Loki가 짱이다" 같은 감상평을 쓰려는 게 아닙니다. 여러분의 로그량을 넣으면 답이 나오는 계산식과, 교체한 뒤에 후회하는 지점을 미리 보여드리는 게 목적입니다.

⚠️ 요금 표기 원칙: 이 글에는 임의로 만든 가정 요금표를 넣지 않습니다. 클라우드 단가는 리전·시점·약정에 따라 다르고 수시로 바뀌기 때문입니다. 대신 단가를 변수(P_*)로 두고 계산식을 완전히 공개합니다. 실제 숫자는 아래 공식 페이지에서 여러분이 쓰는 리전(예: ap-northeast-2 서울) 을 선택해 확인한 뒤 대입하세요.

  • AWS CloudWatch 요금: https://aws.amazon.com/cloudwatch/pricing/
  • Amazon S3 요금: https://aws.amazon.com/s3/pricing/
  • Amazon EC2 / EBS 요금: https://aws.amazon.com/ec2/pricing/
  • Amazon OpenSearch Service 요금: https://aws.amazon.com/opensearch-service/pricing/
  • Grafana Cloud Logs 요금: https://grafana.com/pricing/

압축률·쿼리 빈도·인건비 시급처럼 환경마다 다른 값은 전부 (추정) 으로 표시했습니다. 그대로 믿지 말고 여러분 값으로 바꿔 넣으세요.


공통 비용 분해 공식

세 스택 모두 아래 4항목으로 쪼개면 사과 대 사과 비교가 됩니다.

TEXT
총비용(월) = 수집 요금 + 저장 요금 + 쿼리/스캔 요금 + 운영 인건비

변수 정의

변수의미비고
G_in월 수집량(GB, 압축 전 원본)측정값
D보관 일수정책값
C_ratio압축률 (저장크기 ÷ 원본)(추정) 텍스트 로그 0.1~0.2 수준이 흔함
I_ratio인덱스 오버헤드 배수(추정) ES에서 매핑에 따라 1배 내외 추가 발생 가능
Q_scan월 쿼리 스캔량(GB)CloudWatch Insights 전용
H_ops월 운영 투입 시간(추정)
W팀 시급(원)연봉÷연간근로시간으로 산출
P_ingestGB당 수집 단가공식 요금 페이지 확인
P_storeGB·월당 저장 단가공식 요금 페이지 확인
P_scanGB당 쿼리 스캔 단가공식 요금 페이지 확인
P_node컴퓨트(EC2/OpenSearch 노드) 시간당 단가공식 요금 페이지 확인

스택별 전개식

① Loki 셀프호스팅 + S3

TEXT
수집 요금 = 0                      # 자체 수집, 별도 수집 과금 없음
저장 요금 = G_stored × P_store_s3
  where G_stored = (G_in / 30) × D × C_ratio      # 일평균 × 보관일 × 압축률(추정)
쿼리 요금 ≈ S3 GET 요청비 + 데이터 전송비        # 동일 리전 내부면 전송비 0, 요청비는 소액
컴퓨트   = (EC2 인스턴스 수 × 730h × P_node) + EBS(WAL/캐시)
인건비   = H_ops × W
총비용   = 저장 + 요청비 + 컴퓨트 + 인건비

② Elasticsearch / OpenSearch (셀프 또는 매니지드)

TEXT
저장 디스크 = (G_in / 30) × D × C_ratio × (1 + I_ratio) × (1 + 복제본수)
   # 복제본 1개면 ×2. 여기서 디스크가 두 배로 뜁니다.
저장 요금  = 저장 디스크 × P_store_ebs        # 또는 매니지드 스토리지 단가
컴퓨트     = 노드 수 × 730h × P_node          # 데이터노드 + (마스터) + Kibana/대시보드
수집 파이프라인 = Fluent Bit/Logstash 구동 비용 (사이드카면 사실상 0에 수렴, Logstash면 별도 인스턴스)
인건비     = H_ops × W                        # 샤드/ILM/롤오버 관리 포함

③ CloudWatch Logs

TEXT
수집 요금 = G_in × P_ingest
저장 요금 = (G_in / 30) × D × C_ratio_cw × P_store_cw
   # CloudWatch는 압축 저장되며, 요금 페이지의 저장 단가 기준을 그대로 확인할 것
쿼리 요금 = Q_scan × P_scan            # Logs Insights, 스캔한 데이터량 기준
인건비   = 0에 수렴 (관리형)

시나리오별 대입 템플릿

아래는 숫자를 채워 넣는 워크시트입니다. 단가 칸은 여러분이 공식 페이지에서 확인한 값을 넣으세요.

시나리오 A — 월 20GB / 7일 보관 (스타트업 초기, 서비스 3~5개)

항목Loki+S3ES/OpenSearchCloudWatch
저장 대상 용량(20/30)×7×0.15 ≈ 0.7GB (추정)0.7×(1+1)×2 ≈ 2.8GB (추정)0.7GB (추정)
컴퓨트t계열 1대 (단일 바이너리)최소 1노드 + Kibana없음
수집 과금없음없음20GB × P_ingest
쿼리 과금S3 요청비(소액)없음(컴퓨트에 포함)Q_scan × P_scan
인건비2h × W (추정)4h × W (추정)0

A 구간의 핵심: 저장 용량이 1GB 안팎이라 저장비 차이는 사실상 무의미합니다. 승부는 "인스턴스 1대 유지비 + 인건비" vs "CloudWatch 수집비"에서 납니다. 20GB 수준이면 대개 CloudWatch가 총비용에서 유리합니다. 셀프호스팅으로 아끼는 돈보다 EC2 1대 값과 사람 시간이 더 큽니다.

시나리오 B — 월 100GB / 30일 보관 (이 글의 기준선)

항목Loki+S3ES/OpenSearchCloudWatch
저장 대상 용량(100/30)×30×0.15 = 15GB (추정)15×(1+1)×2 = 60GB (추정, 복제본 1)15GB (추정)
저장 단가 적용15 × P_store_s360 × P_store_ebs15 × P_store_cw
컴퓨트중형 12대데이터노드 2대 + 대시보드0
수집 과금00100 × P_ingest
쿼리 과금S3 GET 요청0Q_scan × P_scan
인건비 (추정)4h × W8h × W0.5h × W

B 구간의 핵심: S3 단가 × 15GBEBS 단가 × 60GB의 차이는 눈에 띄게 벌어집니다. 하지만 여전히 절대 금액 자체는 컴퓨트가 지배합니다. CloudWatch는 G_in × P_ingest가 100GB어치로 커지므로, 수집 단가가 저장 단가보다 훨씬 비싼 CloudWatch 요금 구조상 여기서부터 역전 가능성이 생깁니다. 반드시 P_ingest를 직접 확인해 100을 곱해보세요.

시나리오 C — 월 500GB / 90일 보관 (트래픽 있는 서비스)

항목Loki+S3ES/OpenSearchCloudWatch
저장 대상 용량(500/30)×90×0.15 = 225GB (추정)225×2×2 = 900GB (추정)225GB (추정)
컴퓨트컴포넌트 분리 3~5대데이터노드 3대+ (샤드 설계 필수)0
수집 과금00500 × P_ingest최대 항목
쿼리 과금S3 요청 + 캐시0대시보드 반복 조회 시 급증
인건비 (추정)8~12h × W16~24h × W1h × W

C 구간의 핵심: 500GB × 수집 단가는 웬만한 EC2 여러 대 값을 넘어섭니다. 이 구간에서 셀프호스팅 전환 검토가 경제적으로 정당화되기 시작합니다. 단, ES는 900GB 디스크와 샤드 설계 부담이 함께 옵니다.

위 표의 용량은 압축률 0.15, 인덱스 오버헤드 1배, 복제본 1개를 가정한 추정 계산입니다. 단가는 리전·시점·약정에 따라 변동하므로 반드시 공식 요금 페이지에서 재확인하세요.

3×3 요약 (총비용 우위 경향)

월 20GB / 7일월 100GB / 30일월 500GB / 90일
Loki+S3인건비 때문에 불리경쟁력 있음가장 유리한 경향
ES/OpenSearch과잉 스펙검색 요구 있으면 정당화검색이 제품 기능이면 필수
CloudWatch가장 유리한 경향수집 단가 확인 후 판단수집비가 지배적, 불리

검색 성능: 인덱스 구조가 곧 느려지는 지점

구조 요약

인덱싱 대상본문 검색 방식과금 트리거
Loki라벨(label)만청크를 가져와 스캔(grep)스캔 시 컴퓨트/IO 부하
Elasticsearch본문 전체 역색인역색인 조회컴퓨트·디스크 상시
CloudWatch Insights관리형 내부 인덱스스캔 기반스캔한 GB = 요금

어떤 쿼리에서 갈리는가

  • 라벨로 좁힌 뒤 최근 15분 grep → Loki 충분히 빠름. 세 스택 모두 실용적.
  • 라벨 없이 30일치 전체에서 특정 에러코드 문자열 검색 → Loki 급격히 느려짐(대상 청크를 전부 읽어야 함). ES 압승.
  • 필드 기반 집계 / 상위 N / 백분위 통계 → ES 우위. Loki는 unwrap·label_format 등으로 흉내 낼 수 있으나 표현력과 성능 모두 제약.
  • 비용 인지 쿼리 습관 → CloudWatch는 "스캔량 = 요금"이므로 시간 범위를 좁히는 습관이 강제됩니다. 장점이자 스트레스입니다.

동일 요구사항, 쿼리 3종 비교

요구사항: payment-api 서비스의 최근 1시간 로그에서 HTTP 500 발생 건을 찾고, 엔드포인트별 건수를 많은 순으로 집계한다.

LOGQL
# LogQL (Grafana Loki)
sum by (endpoint) (
  count_over_time(
    {app="payment-api", env="prod"}
      | json
      | status = "500"
      [1h]
  )
)
# 주의: endpoint를 라벨로 쓰면 카디널리티 폭발 위험.
# 위처럼 파싱 단계에서 추출한 값으로 집계하는 편이 안전하지만,
# 대상 로그를 모두 읽어야 하므로 범위가 길어질수록 느려집니다.
JSON
// Elasticsearch Query DSL
{
  "size": 0,
  "query": {
    "bool": {
      "filter": [
        { "term":  { "service.keyword": "payment-api" } },
        { "term":  { "http.status": 500 } },
        { "range": { "@timestamp": { "gte": "now-1h" } } }
      ]
    }
  },
  "aggs": {
    "by_endpoint": {
      "terms": { "field": "http.endpoint.keyword", "size": 20, "order": { "_count": "desc" } }
    }
  }
}
SQL
-- CloudWatch Logs Insights
fields @timestamp, endpoint, status
| filter status = 500
| stats count(*) as cnt by endpoint
| sort cnt desc
| limit 20
-- 실행 전 반드시 시간 범위를 1시간으로 좁힐 것.
-- 로그 그룹 선택 개수 × 시간 범위 = 스캔량 = 요금.

표현력만 보면 ES가 압도적입니다. Loki는 "이미 라벨로 좁혀진 좁은 구간을 빠르게 훑는" 용도에 최적화돼 있고, CloudWatch는 문법은 간결하지만 쿼리 한 번이 곧 비용이라는 점이 다릅니다.


셀프호스팅의 진짜 원가: 떠 있어야 하는 프로세스 개수

Loki (단일 바이너리)Loki (분산 모드)ELK/OpenSearch
필수 프로세스Loki 1 + Promtail/Alloydistributor, ingester, querier, query-frontend, compactorES 데이터노드(2~3), (전용 마스터), Kibana/OpenSearch Dashboards
수집 에이전트Promtail / Grafana Alloy / OTel Collector동일Fluent Bit / Filebeat / Logstash
스토리지 백엔드S3 등 오브젝트 스토리지동일로컬 디스크 / EBS (스냅샷은 S3)
상시 운영 업무보관정책(단순), 쿼리 튜닝, 카디널리티 감시+ 컴포넌트별 스케일링ILM 정책, 샤드 설계, 롤오버, 매핑 관리, 리밸런싱
장애 복구 난이도오브젝트 스토리지에 데이터 존재 → 재기동 위주노드 소실 시 샤드 복구·리밸런싱 대기

핵심 트레이드오프는 이렇습니다.

  • Loki: 저장 계층이 S3라 디스크 풀·샤드 관리 스트레스가 거의 없습니다. 대신 쿼리가 느릴 때 튜닝할 사람이 필요하고, 라벨 설계를 잘못하면 카디널리티 폭발로 ingester 메모리가 날아갑니다.
  • ES: 검색은 강력하지만 ILM·샤드·매핑이 상시 업무로 남습니다. 1~3인 팀에서 이건 결코 작은 비용이 아닙니다.
  • CloudWatch: 운영 시간이 0에 수렴합니다. 대신 요금이 곧 운영비입니다. 여기서 절감 레버는 오직 세 가지 — 보관기간 축소, 수집 필터링, 쿼리 스캔량 감소.

CloudWatch를 유지하면서 즉시 적용 가능한 절감 조치:

Bash
# 1) 보존 기간이 설정되지 않은(무기한) 로그 그룹 찾기
aws logs describe-log-groups \
  --query 'logGroups[?retentionInDays==`null`].[logGroupName,storedBytes]' \
  --output table --region ap-northeast-2

# 정상 결과: 무기한 보관 그룹 목록이 표 형태로 출력됨.
# 결과가 비어 있다면 모든 그룹에 보존 정책이 있다는 뜻 → 다음 단계로.

# 2) 30일로 일괄 조정 (정책 확정 후 실행)
aws logs put-retention-policy \
  --log-group-name /aws/lambda/my-func \
  --retention-in-days 30 --region ap-northeast-2

# 정상 결과: 출력 없음(exit code 0).
# AccessDeniedException이 나면 IAM에 logs:PutRetentionPolicy 권한 추가 필요.

# 3) 용량 큰 순으로 정렬해 범인 찾기
aws logs describe-log-groups --region ap-northeast-2 \
  --query 'reverse(sort_by(logGroups,&storedBytes))[:10].[logGroupName,storedBytes]' \
  --output table

수집량 자체를 줄이는 것도 잊지 마세요. OpenTelemetry Collector나 Fluent Bit 단계에서 헬스체크 로그·정적 리소스 접근 로그를 버리는 필터 한 줄이 스택 교체보다 효과가 클 때가 많습니다.

YAML
# Fluent Bit: 헬스체크 로그 제거 예시
[FILTER]
    Name    grep
    Match   kube.*
    Exclude log  (GET /healthz|GET /readyz|kube-probe)

한국 환경 체크리스트

  • 리전 단가 확인: 서울 리전(ap-northeast-2) 단가는 다른 리전과 다를 수 있습니다. 요금 페이지에서 반드시 리전을 서울로 선택한 뒤 값을 읽고, 확인 날짜를 사내 문서에 적어두세요.
  • 데이터 전송비: 로그를 리전 밖(예: 해외 SaaS)으로 보내면 아웃바운드 전송비가 붙습니다. 계산식의 숨은 항목입니다.
  • 한글 로그 검색: Elasticsearch에서 한글 본문을 제대로 검색하려면 nori 등 형태소 분석기 설정이 필요합니다. 기본 분석기로는 "결제실패"가 원하는 대로 매칭되지 않을 수 있습니다. 반대로 Loki는 substring 매칭 기반이라 형태소 이슈가 아예 없습니다 — 한글 로그 검색에서는 오히려 단순함이 장점이 되는 역설이 있습니다.
  • 인코딩: 애플리케이션 로그를 UTF-8로 통일했는지 확인. EUC-KR 잔재가 있으면 어느 스택에서도 검색이 깨집니다.
  • 지원 옵션: 클라우드 벤더 지원 플랜, 국내 MSP, Grafana Cloud/Elastic Cloud의 한국어 지원 범위를 계약 전에 확인하세요.
  • 국내 보관 요건: 업종·계약에 따라 로그의 국내 리전 보관이 요구될 수 있습니다. 해외 리전 SaaS로 보내기 전에 내부 법무/보안 검토와 관련 규정 원문 확인이 필요합니다(요건은 업종별로 다르므로 공식 자료 확인 필요).

결론: 3축 의사결정표

팀 규모월 로그량주 쿼리 패턴선택
1~2인~50GB최근 로그 확인 위주CloudWatch 유지 + 보존기간 30일, 헬스체크 필터링
1~2인50~200GB라벨로 좁혀 최근 로그 조회Loki 단일 바이너리 + S3
2~3인200GB~라벨 기반 조회 + 간단 집계Loki 분산 모드 + S3
규모 무관규모 무관검색·집계가 제품 기능 수준ES/OpenSearch (다른 선택지 없음)
인프라 담당 사실상 0명~200GB무엇이든CloudWatch 유지 (인건비가 절감액을 초과)
2~3인500GB~핫 로그 조회 + 장기 분석 병행Loki(핫) + S3/데이터레이크(콜드) 분리

교체 후 후회하는 지점 (솔직한 실패 분기)

1) Kibana 대시보드가 그대로 안 옮겨집니다.

Kibana 항목Loki 이식 가능성
라벨 기반 로그량 추이가능
에러율 시계열가능 (rate + 파싱)
필드 기반 Top-N 테이블(장기 구간)사실상 불가/매우 느림
백분위·다차원 상관분석불가
자유 텍스트 전역 검색불가에 가까움 (라벨 없이는 스캔 지옥)

2) 카디널리티 폭발. user_id, trace_id, request_id를 라벨로 넣는 순간 Loki는 무너집니다. 라벨은 값의 종류가 유한하고 적은 것(app, env, namespace, level)만 사용하고, 나머지는 본문에 두고 파싱하세요. 이건 선택이 아니라 규칙입니다.

3) 집계 성능 기대치. Loki에서 30일치 집계 대시보드를 만들면 타임아웃을 자주 만나게 됩니다. 장기 집계는 메트릭(Prometheus)으로 뽑아두거나, Recording rule로 미리 계산해두는 설계가 필요합니다.

액션 3단계

  1. 측정 — 현재 월 수집량(G_in), 로그 그룹별 저장량, 월 쿼리 스캔량을 뽑습니다. 위의 describe-log-groups 명령이 출발점입니다.
  2. 대입 — 본문 계산식에 공식 요금 페이지에서 확인한 단가와 여러분의 인건비 시급을 넣습니다. 셀프호스팅 쪽 인건비 줄을 절대 0으로 두지 마세요.
  3. 파일럿 — 전체를 옮기지 말고 서비스 1개만 이관해 2~4주 운영합니다. 이때 확인할 것: 자주 쓰는 쿼리 3개의 응답 시간, 대시보드 이식률, 실제 주당 운영 시간.

자주 묻는 질문 (FAQ)

Q. 월 100GB면 Loki로 옮기는 게 무조건 싼가요? A. 아닙니다. 저장 비용만 보면 S3 기반 Loki가 유리하지만, EC2 인스턴스 유지비와 월 운영 시간(추정 4시간 이상)을 인건비로 환산해 더하면 역전되는 경우가 있습니다. 100GB 구간은 "계산해봐야 아는 구간"입니다. 수집 단가(P_ingest)를 공식 요금 페이지에서 확인해 100을 곱한 값과, EC2+S3+인건비 합계를 나란히 놓고 비교하세요.

Q. CloudWatch를 유지하면서 비용을 줄일 수 있는 가장 빠른 방법은? A. 세 가지 순서로 처리하세요. ① 보존 기간이 무기한인 로그 그룹을 찾아 30~90일로 조정, ② 수집 에이전트 단계에서 헬스체크·정적 리소스 로그 제외, ③ Logs Insights 쿼리의 시간 범위와 로그 그룹 선택을 최소화. 특히 ②는 수집·저장·스캔 요금을 동시에 줄이므로 효과가 가장 큽니다.

Q. Loki와 Elasticsearch를 같이 쓰는 건 낭비 아닌가요? A. 규모가 커지면 오히려 표준적인 구성입니다. 최근 7~14일의 핫 로그는 Loki에서 저렴하게 조회하고, 장기 분석·집계가 필요한 일부 로그(감사 로그, 결제 로그 등)만 선별해 ES나 데이터레이크로 보내는 방식입니다. 전량을 두 곳에 중복 저장하는 게 아니라 용도별로 흐름을 나누는 것이 핵심이며, 이 절충안이 마이그레이션 실패 위험도 가장 낮습니다.

✦ ✦ ✦
편집 검토 · Editorial Review

이 글은 AI 에이전트가 자료 조사와 1차 초안 작성을 담당하고, 사람 편집자가 사실관계·출처·톤과 맥락을 검토한 뒤 발행했습니다. 환경(OS·버전)에 따라 결과가 다를 수 있으니 적용 전 공식 문서를 함께 확인하세요. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.

초안 · AI (Content Reviewer)·검토 · Nodelog 편집자·발행 ·

댓글

첫 번째 댓글을 남겨보세요.