머신러닝 파이프라인의 첫 관문은 "데이터를 어디서, 어떻게 가져오는가"다. MLA-C01 도메인 1(Data Preparation)이 전체의 약 28%를 차지하는데 그 출발점이 수집(ingestion)이다.
AWS에서 ML 데이터의 사실상 단일 진실 공급원(single source of truth)은 Amazon S3다. SageMaker의 학습 잡, Glue의 ETL, Athena의 쿼리가 모두 S3를 입출력으로 사용한다. 이유는 셋이다.
사실상 무제한 용량: 객체 하나당 최대 5TB, 버킷당 객체 수 제한 없음. 페타바이트 규모 학습 데이터도 수용.
컴퓨트와 스토리지 분리: 데이터를 S3에 두고 필요할 때만 SageMaker/EMR/Glue 컴퓨트를 붙인다. 비용이 사용량에 비례.
광범위한 통합: 거의 모든 AWS 분석/ML 서비스가 S3를 네이티브로 읽고 쓴다.
데이터 레이크는 보통 존(zone)으로 계층화한다.
존
별칭
내용
포맷
덮어쓰기
Raw
Bronze / Landing
원본 그대로 수집된 데이터
원본(JSON, CSV, 로그)
절대 금지
Cleaned
Silver
정제·검증된 데이터
Parquet
재처리로 재생성
Curated
Gold
피처 엔지니어링 완료, 학습 직전
Parquet
재처리로 재생성
이 Bronze/Silver/Gold 계층화는 Databricks가 대중화한 메달리온 아키텍처(Medallion Architecture)다. 핵심 발상은 "원본을 절대 덮어쓰지 말고, 각 변환 단계를 별도 존에 보존하라"이다. 이렇게 하면 변환 로직에 버그가 발견됐을 때 Raw로 돌아가 재처리할 수 있고, 데이터 lineage(계보) 추적이 쉬워진다. 불변성(immutability)을 데이터 레이아웃 수준에서 강제하는 패턴이다.
S3 스토리지 클래스도 ML 맥락에서 중요하다.
클래스
ML에서의 용도
S3 Standard
자주 학습에 쓰는 활성 데이터셋
S3 Intelligent-Tiering
접근 패턴이 들쭉날쭉한 데이터(자동 티어 이동)
S3 Glacier 계열
규제 보존용 과거 데이터, 드문 재학습 대비
import boto3s3 = boto3.client("s3")# 학습 데이터 업로드 (curated 존)s3.upload_file( Filename="train.parquet", Bucket="ml-datalake-prod", Key="curated/customer-churn/year=2026/month=06/train.parquet",)
위 Key의 year=2026/month=06/ 부분이 바로 Hive 스타일 파티셔닝이다. Athena와 Glue가 이 키=값 디렉터리 구조를 읽어 파티션을 자동 인식한다. 파티셔닝은 Day 4에서 깊게 다룬다.
KDS는 샤드(shard) 단위로 처리량을 정한다. 샤드 하나당 쓰기 1MB/s(또는 1,000 레코드/s), 읽기 2MB/s. 처리량이 부족하면 샤드를 늘려야(resharding) 한다. 반면 Firehose는 서버리스라 샤드 관리가 없는 대신, "실시간"이 아니라 버퍼링된 "near-real-time"이다.
Kinesis는 분산 로그(distributed log) 추상화를 따른다. 같은 패러다임의 오픈소스가 Apache Kafka다. 핵심은 데이터를 append-only 로그에 순서대로 쓰고, 여러 소비자가 각자의 오프셋(체크포인트)을 들고 독립적으로 읽는 것이다. 이 덕분에 한 스트림을 실시간 대시보드와 ML 피처 파이프라인이 동시에 소비할 수 있다.
계산 예시 — "온프레미스 100TB를 S3로, 인터넷 회선 100Mbps". 100TB를 100Mbps로 보내면 약 92일 걸린다. 이 경우 Snowball(물리 디바이스 배송)이 정답이다. 회선이 충분하면 DataSync. DMS는 "관계형 DB의 지속적 복제(CDC, Change Data Capture)"가 키워드일 때 답이다.
열 기반 저장: 학습에 필요한 피처 컬럼만 읽으면 되므로 I/O가 급감. 100개 컬럼 중 5개만 쓰면 5개만 스캔.
컬럼 단위 압축: 같은 타입의 값이 인접해 압축률이 높다. CSV 대비 보통 2~10배 작다.
predicate pushdown: Athena/Spark가 "이 파티션·이 값만" 필요할 때 불필요한 데이터 블록을 건너뛴다.
스키마 내장: 타입 정보가 파일에 들어 있어 별도 스키마 파일이 불필요.
[행 기반 CSV] 행1: a,b,c,...,z │ 행2: a,b,c,...,z │ ...
→ 26개 컬럼 중 3개만 필요해도 전부 읽는다
[열 기반 Parquet] a열 블록 │ b열 블록 │ c열 블록 │ ... │ z열 블록
→ 필요한 3개 블록만 읽는다 + 컬럼별 압축
import pandas as pd# CSV → Parquet 변환 (Snappy 압축)df = pd.read_csv("raw/transactions.csv")df.to_parquet("curated/transactions.parquet", compression="snappy", index=False)
열 기반 저장(columnar storage)은 OLAP(분석) 워크로드에 최적화돼 있다. 분석 쿼리는 "수백만 행 × 소수 컬럼의 집계"가 전형적인데, 행 기반 저장은 필요 없는 컬럼까지 디스크에서 읽어야 한다. 열 기반은 컬럼을 따로 저장해 필요한 것만 읽고, 같은 타입이 인접해 run-length/dictionary 인코딩으로 압축률도 높다. 반대로 OLTP(트랜잭션)는 "한 행 전체"를 자주 다뤄 행 기반이 유리하다. ML 학습은 대부분 OLAP 성격이라 Parquet이 맞다.
⚠️ 함정: JSON은 사람이 읽기 좋고 nested 구조에 강하지만, 학습 데이터 포맷으로는 비효율적이다. 텍스트라 용량이 크고, 매번 파싱 비용이 들며, 컬럼 단위 스킵이 불가능하다. Raw 존에는 JSON으로 받더라도, Cleaned/Curated 존으로 갈 때 Parquet으로 변환하는 게 표준 패턴이다.
데이터가 어떻게 도착하나?
│
├─ 끊임없이 흘러온다(스트리밍)
│ ├─ 코드 없이 S3에 쌓기만 → Firehose
│ ├─ 1초 미만 처리 + 여러 앱이 소비 → Kinesis Data Streams
│ ├─ 스트림에 SQL 집계 필요 → Kinesis Data Analytics
│ └─ 영상 스트림 → Kinesis Video Streams
│
└─ 주기적으로 덩어리로 온다(배치)
├─ 온프레 파일 서버 → DataSync
├─ 파트너가 SFTP 업로드 → Transfer Family
├─ 관계형 DB 지속 복제(CDC) → DMS
├─ 변환까지 함께 → Glue ETL
└─ 회선으로는 몇 달 걸림 → Snowball