학습 데이터는 어딘가에서 흘러들어와야 한다. 클릭 로그·IoT 센서·거래 이벤트는 실시간 스트림으로 쏟아지고, 운영 DB나 외부 시스템의 데이터는 주기적 배치로 들어온다. "Kinesis"는 이름만 보고 헷갈리기 쉬워 정확히 구분해야 한다.
| 서비스 | 역할 | 핵심 특징 | 대표 ML 용도 |
|---|---|---|---|
| Data Streams (KDS) | 실시간 스트림 수집·저장 | 샤드 기반, 소비자 코드 필요, 데이터 보관(최대 365일), replay 가능 | 다소비자 이벤트 버스, 재처리 |
| Data Firehose | 스트림 → 목적지 적재 | 완전관리형, S3/Redshift/OpenSearch로 자동 배달, 버퍼링·포맷 변환 | 데이터레이크 축적 |
| Managed Service for Flink | 스트림 실시간 분석 | SQL/Flink로 윈도우 집계·이상 탐지 | 실시간 피처 계산 |
| Video Streams | 비디오 스트림 수집 | 영상 ML 입력 | 얼굴 인식, 영상 분석 |
스트림 데이터를 어떻게 쓸 것인가?
├─ 목적지(S3/Redshift/OpenSearch)로 자동 적재만 필요 → Firehose
│ · 소비자 코드 없음 · 버퍼링(크기 또는 시간) · Parquet 변환·압축 가능
└─ 여러 소비자가 같은 스트림을 다르게 처리
또는 커스텀 처리·장애 시 재생(replay)이 필요 → Data Streams
· 샤드 관리 · 보관(retention) · 소비자별 독립 오프셋
import boto3, json
kinesis = boto3.client("kinesis")
# Data Streams에 이벤트 넣기 — PartitionKey로 샤드 분배
kinesis.put_record(
StreamName="clickstream",
Data=json.dumps({"user_id": "u123", "event": "click", "ts": 1719300000}),
PartitionKey="u123", # 같은 키는 같은 샤드 → 순서 보장 단위
)# Firehose: 코드 없이 S3로 자동 배달 + 버퍼링 설정 (전송 스트림 구성 예)
firehose = boto3.client("firehose")
firehose.put_record(
DeliveryStreamName="to-datalake",
Record={"Data": json.dumps({"user_id": "u123", "amount": 42.0}) + "\n"},
)
# Firehose가 버퍼(예: 5MB 또는 60초)를 채우면 S3에 Parquet으로 변환·압축 적재💡 개념: KDS는 샤드(shard) 단위로 처리량을 확장한다. 샤드 하나가 쓰기 1MB/s·1,000 records/s, 읽기 2MB/s를 처리하므로 트래픽이 늘면 샤드를 늘려야 한다(또는 on-demand 모드). 또한 KDS는 데이터를 보관(retention)해 여러 소비자가 같은 데이터를 독립적으로 읽고 재처리할 수 있다(replay). 반면 Firehose는 보관·재생이 없고 목적지 적재만 책임지는 "fire and forget" 파이프다.
⚠️ 함정: "실시간이니까 무조건 KDS"는 오답 유도다. 지문에 소비자가 하나뿐이고 "코드 없이", "관리 부담 최소"라는 단서가 있으면 Firehose가 정답이다. 반대로 "재처리", "여러 팀이 각자 소비"가 보이면 Firehose는 탈락한다.
AWS Glue는 세 가지를 묶은 서버리스 서비스다.
# Glue ETL 잡 (PySpark) — 카탈로그 테이블을 읽어 정제 후 Parquet로 저장
import sys
from awsglue.context import GlueContext
from awsglue.transforms import DropNullFields
from pyspark.context import SparkContext
glueContext = GlueContext(SparkContext.getOrCreate())
# 카탈로그에 크롤러가 등록한 테이블을 DynamicFrame으로 로드
dyf = glueContext.create_dynamic_frame.from_catalog(
database="raw_db", table_name="clickstream"
)
clean = DropNullFields.apply(frame=dyf) # 결측 컬럼 제거
# 학습용 피처 위치에 Parquet으로 저장 (파티셔닝)
glueContext.write_dynamic_frame.from_options(
frame=clean,
connection_type="s3",
connection_options={"path": "s3://my-lake/features/", "partitionKeys": ["dt"]},
format="parquet",
)💡 개념: Glue의 DynamicFrame은 Spark DataFrame의 ML/ETL 친화 확장으로, 스키마가 제각각인 반정형 데이터(JSON 등)를 스키마 강제 없이 다룰 수 있다(스키마 불일치 행을 버리지 않고 보존). 정형 변환이 끝나면
toDF()로 일반 Spark DataFrame으로 바꿔 익숙한 연산을 쓴다. Crawler가 채운 Data Catalog 덕에 Athena로 즉시 SQL 탐색이 가능해, ML 전처리 전 데이터 이해(EDA) 단계가 빨라진다.
| 도구 | 하는 일 | 하지 않는 일 |
|---|---|---|
| Glue Crawler | 스키마 추론 + 카탈로그 테이블 등록 | 데이터 이동·변환을 하지 않는다 |
| Glue ETL Job | Spark로 정제·조인·집계·포맷 변환 | 실시간 스트림 수집을 담당하지 않는다 |
| Kinesis Firehose | 스트림을 목적지로 적재 | 보관·재생·다소비자를 지원하지 않는다 |
| Athena | 카탈로그 기반 SQL 조회 | 대규모 반복 ETL 실행 엔진이 아니다 |
| DMS | DB → 데이터레이크 마이그레이션·CDC | 피처 엔지니어링을 하지 않는다 |
모든 데이터가 스트림으로 오는 것은 아니다. 운영 DB·외부 파일·온프레미스 저장소에서 들어오는 경로도 알아 둬야 한다.
| 도구 | 하는 일 | 언제 고르나 |
|---|---|---|
| AWS DMS | DB → S3/Redshift 마이그레이션 및 CDC(변경 데이터 캡처) | 운영 RDB의 변경분을 계속 데이터레이크로 흘려보낼 때 |
| AWS DataSync | 온프레미스 NFS/SMB ↔ S3/EFS/FSx 대량 전송 | 사내 파일 서버의 학습 데이터를 주기적으로 옮길 때 |
| AWS Snow 패밀리 | 물리 장비로 대용량 오프라인 전송 | 네트워크로 옮기기엔 데이터가 너무 크거나 회선이 느릴 때 |
| AWS Batch / EMR | 대량 배치 연산 실행 | 수집 후 무거운 변환·집계를 돌릴 때 |
| S3 직접 업로드 | 가장 단순한 적재 | 파일이 이미 손에 있고 규모가 작을 때 |
⚠️ 함정: "페타바이트를 옮겨야 한다"는 지문에서 네트워크 전송(DataSync)만 보고 고르면 회선 속도라는 제약을 놓친다. 전송에 몇 주가 걸린다는 단서가 있으면 Snow 계열이 정답 후보다.
스트리밍은 배치보다 운영 난이도가 높다. 시험에도 이 어려움이 그대로 나온다.
PartitionKey를 사용자 ID로 둬야 한다.ML 데이터 수집은 두 패턴으로 나뉜다.
| 구분 | 배치(Batch) | 스트리밍(Streaming) |
|---|---|---|
| 도착 방식 | 주기적 대량 적재(매일/매시) | 이벤트가 도착하는 즉시 |
| 대표 도구 | Glue, EMR, Batch, S3 | Kinesis, MSK(Kafka) |
| 지연(latency) | 분~시간 | 초~밀리초 |
| 학습 적합 | 대부분의 모델 재학습 | 실시간 피처·온라인 학습 |
| 신선도 | 오래됨 허용 | 최신성이 곧 가치 |
| 운영 난이도 | 낮음(실패 시 재실행) | 높음(순서·중복·지연 처리) |
[람다 아키텍처]
이벤트 ──┬─▶ KDS ─▶ Flink(윈도우 집계) ─▶ 실시간 피처 ─▶ 추론 엔드포인트
│ (스피드 레이어: 저지연·근사)
└─▶ Firehose ─▶ S3 데이터레이크 ─▶ 배치 재학습 ─▶ 모델 갱신
(배치 레이어: 정확·완전)
💡 개념: 람다 아키텍처는 같은 데이터를 스피드 레이어(스트리밍, 저지연 근사)와 배치 레이어(주기적, 정확·완전)로 동시에 처리해 둘의 장점을 합친다. ML에서는 Firehose로 모든 이벤트를 S3에 축적(배치 재학습용)하면서, KDS+Flink로 실시간 피처를 계산(즉시 추론용)하는 형태로 자주 쓰인다. 다만 두 경로의 피처 계산 로직이 어긋나면 training-serving skew가 생기므로 일관성 관리가 중요하다.
⚠️ 함정: 람다 아키텍처의 진짜 비용은 인프라가 아니라 로직 이중 관리다. 실시간 경로와 배치 경로에서 "최근 5분 거래 횟수"를 다르게 계산하면 모델은 학습 때 본 적 없는 값을 추론 때 받는다. Feature Store로 정의를 한 곳에 모으는 것이 정석 대응이다.
Firehose는 "그냥 배달"만 하지 않는다. 배달 도중 가벼운 가공을 끼워 넣을 수 있어서, 단순 적재 시나리오의 정답 범위가 생각보다 넓다.
⚠️ 함정: "가벼운 변환이 필요하니 Firehose는 못 쓴다"고 단정하지 마라. 레코드 단위의 단순 변환이면 Firehose + Lambda로 충분하고, 조인·집계처럼 여러 레코드를 가로지르는 연산이 필요해야 Glue ETL이나 Flink가 등장한다.
시험 시나리오를 풀 때 순서대로 묻자.
이 다섯 질문이면 대부분의 수집 문제가 풀린다.
내일은 이렇게 모은 데이터에 정답을 붙이는 일(SageMaker Ground Truth, 액티브 러닝, 레이블 품질)을 다룬다.
선택지를 클릭하면 정답·해설이 펼쳐집니다.
문제 1
IoT 센서 스트림을 별도 변환·코드 없이 그대로 S3 데이터레이크에 Parquet으로 자동 적재하기만 하면 된다. 가장 적합한 서비스는?
문제 2
하나의 클릭스트림을 ① 실시간 대시보드, ② 사기 탐지 모델, ③ 추후 재처리를 위해 각각 독립적으로 소비하고, 장애 시 데이터를 다시 읽어야 한다. 적합한 서비스는?
문제 3
스키마를 모르는 대량의 JSON 로그가 S3에 쌓여 있다. Athena로 SQL 탐색을 시작하기 전에 테이블과 스키마를 자동으로 만들고 싶다. 사용할 도구는?
문제 4
대부분의 ML 모델 재학습이 스트리밍이 아니라 배치 방식으로 이뤄지는 가장 큰 이유는?
문제 5
같은 이벤트 데이터를 실시간 피처 계산(즉시 추론용)과 주기적 모델 재학습(정확·완전)에 모두 활용하기 위한 아키텍처 패턴은?