초당 6천 개 이벤트를 S3 데이터 레이크에 담기까지 — CloudWatch에서 출발한 3번의 시행착오

데이터 레이크 아키텍처

약 260만 개의 IoT 기기에서 초당 6천 개의 상태 이벤트가 쏟아져요. 이 이벤트를 가공 없이 날것 그대로 저장해야 하는 이유가 분명하더라고요. 과거 특정 시점에 기기가 어떤 상태였는지 확인하는 히스토리, 고객의 기기 동작 문의에 대응하는 근거, 외부 플랫폼의 이벤트 처리 여부를 증명하는 증적. 이 세 가지 때문에 "일단 다 저장해야" 했어요.

문제는 어디에 어떻게 담느냐.

CloudWatch에서 시작해서 Loki를 거쳐 S3에 도착했다

1차 시도는 단순했어요. 로그니까 CloudWatch Logs에 넣자. 근데 비용 문제가 바로 터졌어요. CloudWatch Logs는 수집, 저장, 분석 세 영역에서 비용이 발생하는데 수집 비용의 비중이 가장 커요. 서울 리전 기준 GB당 약 $0.76. 하루에 수백 GB가 발생하니까 단순 적재 비용으로는 감당이 안 됐어요.

2차 시도는 오픈소스 전환. Promtail + Loki 조합으로 바꾸고 백엔드 저장소를 S3로 설정해서 파일 시스템 크기에 구애받지 않으면서 순수 파일 저장 비용만 내는 구조를 만들었어요. 비용 문제는 해결됐는데, 이번엔 속도가 문제. Loki는 로그 메타데이터(레이블)만 인덱싱하고 내용은 그대로 저장하는 구조거든요. "최근 1시간 이내의 기기 이벤트 검색"처럼 인덱싱된 레이블 기반의 좁은 범위 검색은 빠르지만, "3일 동안 특정 기기의 모든 이벤트 검색" 같은 전체 스캔 쿼리에는 매우 취약했어요. 타임아웃이 잦아서 사용이 어려웠고요.

그렇다고 ELK를 올리자니, 검색 속도는 빠르지만 그렇게 빠를 필요가 없었어요. 가끔 사용하는 팀 상황에 비해 과한 비용과 관리 부담. 예상대로.

결국 S3를 중심으로 한 데이터 레이크를 직접 구성하기로 했어요. S3는 저장 비용이 매우 저렴하고 용량 확장에 신경 쓸 필요가 없잖아요. 특히 기준 시간이 지난 데이터는 Glacier로 자동 이동시켜서 증적 관리를 위한 저렴한 장기 보관 목적에도 딱 맞았어요.

Parquet + 파티셔닝 + 파일 분리 — Athena 스캔량을 줄이는 세 가지 축

데이터 조회는 서버리스 쿼리 엔진인 Athena를 사용해요. Athena는 스캔한 데이터 양에 따라 속도와 비용이 결정되니까 "어떻게 스캔량을 줄이는가"가 핵심이었어요.

첫 번째, Parquet 형식. 열 기반으로 데이터를 저장하는 파일 형식이에요. 쿼리를 실행하면 Athena는 전체가 아닌 출력이 필요한 컬럼 영역만 확인해요. 저장되는 데이터 중 실제 조회에 사용되는 컬럼이 소수인 팀 상황에 특히 적합했고요. 파일 내부에 최댓값, 최솟값 같은 통계 정보 메타데이터도 갖고 있어서 검색 조건에 포함되지 않는 파일은 무시하고 넘길 수 있어요. 스캔량이 줄고, 쿼리 속도 향상과 비용 절감으로 직결.

두 번째, 적절한 파일 분리. 파일이 너무 많으면 각 파일의 메타데이터를 확인하기 위해 읽고 닫는 오버헤드가 발생하고, 반대로 너무 큰 파일은 필요 없는 데이터까지 함께 읽을 확률이 높아져서 비효율적이에요. 이벤트를 배치로 모아 최적 크기의 파일 하나로 묶어서 저장하는 것으로 해결했어요.

세 번째, 파티션 기반 파일 경로. S3에 저장할 때 `year=2026/month=03/day=28/hour=15/` 같은 시간 단위로 경로를 구성했어요. Athena가 시간을 조건으로 검색할 때 이 파티션 기준으로 범위 내 경로와 파일만 스캔 대상으로 삼거든요. Athena는 Glue 카탈로그로 테이블 정보(스키마, 파일 형식, 위치, 파티션 정보)를 저장하고, 쿼리 실행 전에 카탈로그를 확인해서 스캔할 경로와 파일 형식을 미리 파악해요.

많은 양, 빠를 필요 없는 검색, 저렴한 비용. 팀 상황에 딱 맞는 조합이었죠.

Glue ETL로 통계까지 — 월 3~4만 원에 데이터 플랫폼을 굴린다

AWS Glue ETL에서는 Spark + Python을 사용한 대용량 데이터 처리 로직과 자동 스케줄링을 정의할 수 있어요. 수집한 기기 이벤트에서 제품별 기기 수, 각 제품에서 발생하는 이벤트 추이를 집계하고, 매시각 20분에 실행해서 한 시간 단위로 통계 자료를 저장하고, 다시 일별, 월별로 반복했어요.

이렇게 만들어진 통계가 실제로 쓰이는 곳이 두 군데예요. 특정 제품의 비정상적인 이벤트 발생을 감지해서 제품팀에 전달 — 펌웨어 개선의 근거가 됐고요. 단순 판매 수가 아닌 시간대별 활성화 기기 수, 자주 사용되는 기기 제어를 집계해서 마케팅 팀에 전달. 단순 보관에서 시작해서 사용자 기기 사용 추이를 집계하고 추출하는 데이터 관리 시스템으로 발전시킨 거예요.

여기서 가장 매력적인 건 비용이에요. 2 DPU로 실행했을 때 약 2분 소요, 월 3~4만 원 수준. 스케줄링이 서버리스 + Full managed라 유지비 부담이 없어요. (솔직히 이 가격에 이 정도 파이프라인이면 안 쓸 이유가 없잖아요.)

데이터 레이크 전체 아키텍처

CloudWatch의 GB당 $0.76에서 시작해서 S3 + Parquet + 파티셔닝 + Athena + Glue ETL까지 도달한 여정이에요. 화려한 기술 스택이 아니라 팀의 실제 상황 — 많은 양, 빠를 필요 없는 검색, 저렴한 비용 — 에 맞춰 저장소를 세 번 갈아탄 기록. 정답이 처음부터 있었던 게 아니라 시행착오 끝에 찾았다는 점이 오히려 참고할 만해요.