
서버 개발자에게 "요청이 들어오면 즉시 응답한다"는 자연스러운 사고방식이다. 하지만 데이터 처리의 세계에서는 "언제 처리할 것인가" 자체가 아키텍처를 결정하는 첫 번째 질문이 된다.
- 어제 하루치 주문 데이터를 집계해서 리포트를 만든다 → 배치
- 최근 10초간 쌓인 클릭 로그를 모아서 대시보드를 갱신한다 → 마이크로배치
- 사용자가 결제 버튼을 누른 바로 그 순간 이상 거래를 탐지한다 → 스트리밍
세 가지 모델은 "진화의 단계"가 아니다. 각각 고유한 트레이드오프를 가진 선택지다. 이 글에서는 세 모델의 차이를 명확히 정리하고, 스트리밍이 필요한 순간에 왜 Apache Flink가 강력한 선택지인지를 이야기한다.
| 레이턴시 | 처리 모델 | 대표 기술 |
| 일 단위 | Batch | Spark, Hive |
| 분 단위 | Micro-batch | Spark Structured Streaming |
| 초 ~ 밀리초 단위 | Stream Processing | Flink, Kafka Streams |
목차
- 세 가지 처리 모델 비교
- 스트리밍이 어려운 이유 — 배치에는 없는 문제들
- Flink 소개
- Flink 핵심 개념 심화 소개
- 처리 모델 선택 가이드 — 그래서 무엇을 써야 하는가?
- Flink vs Spark Structured Streaming 비교
1. 세 가지 처리 모델 비교
배치 (Batch Processing)
배치 처리는 유한한 데이터셋(bounded dataset) 을 한꺼번에 읽어서 처리하고 결과를 쓰는 모델이다. 가장 오래되고, 가장 단순하며, 여전히 가장 많이 쓰인다.
동작 원리

- 입력 데이터가 완전히 준비된 후 처리를 시작한다.
- 처리 단위: 파일, 파티션, 테이블 전체.
- 스케줄러(Airflow, cron 등)가 주기적으로 트리거한다.
대표 기술: Apache Spark (batch mode), Apache Hive, AWS Glue, traditional ETL 도구
장점
- 구현이 단순하고 디버깅이 쉽다 (입력이 고정되어 있으므로 재현 가능)
- 처리량(throughput) 최적화에 유리하다 — 대규모 데이터를 한 번에 처리
- 장애 시 전체 재실행이 가능하다 (멱등성 확보가 상대적으로 쉬움)
한계
- 레이턴시가 높다 — 데이터가 모일 때까지 기다려야 한다
- "지금 일어나고 있는 일"에 대응할 수 없다
- 데이터 도착 지연 시 전체 파이프라인이 밀린다
적합한 유스케이스: 일별/주별 리포트, 대규모 집계(매출 정산), ML 모델 학습, 데이터 웨어하우스 적재
유스케이스 예시: 일별 매출 정산

마이크로배치 (Micro-batch Processing)
마이크로배치는 "작은 배치의 연속" 이다. 데이터를 짧은 간격(수 초~수 분)으로 잘라서 각 구간을 배치처럼 처리한다.
동작 원리
- 연속적으로 들어오는 데이터를 시간 간격(trigger interval) 으로 잘라서 배치 처리한다.
- 각 마이크로배치는 독립적인 작은 배치 잡이다.
대표 기술: Spark Structured Streaming (기본 모드)
배치와 스트리밍 사이의 트레이드오프
- 배치의 안정성(재실행 가능, 단순한 장애 복구)을 유지하면서
- 레이턴시를 분 단위 → 초 단위로 줄인다.
레이턴시 한계와 그 원인
- 각 마이크로배치는 스케줄링 → 데이터 수집 → 처리 → 커밋 사이클을 거친다.
- 이 사이클의 오버헤드가 하한선이 된다 — 일반적으로 수백 ms ~ 수 초가 최소 레이턴시.
- 트리거 간격을 아무리 줄여도 "배치를 만들고 제출하는" 구조적 오버헤드를 제거할 수 없다.
적합한 유스케이스: 준실시간 대시보드, 수 초~수 분 허용 파이프라인, 기존 Spark 인프라를 활용한 스트리밍 전환
유스케이스 예시: 준실시간 클릭 로그 대시보드

스트리밍 (True Stream Processing)
스트리밍은 이벤트가 발생하는 그 즉시, 레코드 단위(record-at-a-time) 로 처리하는 모델이다. 데이터를 모아서 처리하는 것이 아니라, 흘러가는 데이터를 파이프라인이 연속적으로 통과시킨다.
동작 원리
- 각 레코드는 도착 즉시 오퍼레이터 체인을 통과한다.
- 집계가 필요한 경우 윈도우(Window) 와 상태(State) 를 활용한다.
- 처리 엔진은 항상 실행 중(long-running)이다.
대표 기술: Apache Flink, Kafka Streams, Apache Storm (레거시)
스트리밍과 마이크로배치의 차이
| 구분 | 마이크로배치 | 스트리밍 |
| 처리 트리거 | 시간 간격(trigger) | 이벤트 도착 |
| 최소 레이턴시 | 수백 ms ~ 수 초 | 수 ms ~ 수십 ms |
| 상태 관리 | 배치 간 외부 저장소 의존 | 엔진 내장 상태 (in-memory + checkpoint) |
| 시간 처리 | Processing Time 중심 | Event Time 네이티브 지원 |
적합한 유스케이스: 실시간 이상 거래 탐지, CEP(Complex Event Processing), 실시간 추천, 실시간 집계/모니터링, IoT 센서 데이터 처리
유스케이스 예시: 실시간 이상 거래 탐지

| 항목 | 배치 (Batch) | 마이크로배치 (Micro-batch) | 스트리밍 (Stream) |
| 처리 단위 | 파일/파티션 전체 | 시간 간격별 작은 배치 | 레코드 단위 |
| 레이턴시 | 분 ~ 시간 | 수백 ms ~ 수 분 | 수 ms ~ 수십 ms |
| 처리량(Throughput) | ★★★ 최적화 용이 | ★★☆ 양호 | ★★☆ 상태 관리 비용 존재 |
| 구현 난이도 | ★☆☆ 낮음 | ★★☆ 중간 | ★★★ 높음 |
| 주요 구현 어려운 포인트 | 스케줄링, 멱등성 | 트리거 간격 튜닝, 상태 관리 한계 | 시간 의미론, 순서 보장, 상태 관리, 장애 복구 |
| Exactly-once | 재실행으로 달성 (비교적 쉬움) | 프레임워크 지원 (Spark 체크포인트) | 엔진 + Source + Sink 모두 협력 필요 |
| 상태 관리 | 불필요 (stateless) | 제한적 (배치 간 상태 전달) | 엔진 내장 (Keyed State, RocksDB 등) |
| 장애 복구 | 전체 재실행 | 마이크로배치 단위 재실행 | Checkpoint/Savepoint 기반 복구 |
| 구현 방향 | 스케줄러 + 잡 제출 | 기존 배치 프레임워크 확장 | 전용 스트리밍 엔진 도입 |
| 대표 기술 | Spark, Hive, Glue | Spark Structured Streaming | Flink, Kafka Streams |
| 유스케이스 | 일별 리포트, 정산, ML 학습 | 준실시간 대시보드, 로그 집계 | 이상 탐지, CEP, 실시간 추천 |

배치는 모든 데이터가 모인 후 한 번에 처리한다. 마이크로배치는 구간을 나눠 처리하지만 구간 내 지연이 존재한다. 스트리밍은 각 이벤트를 도착 즉시 처리한다.
2. 스트리밍이 어려운 이유 — 배치에는 없는 문제들
배치 처리에서는 당연하게 여겨지던 것들이 스트리밍에서는 전혀 당연하지 않다. 스트리밍 아키텍처를 도입하기 전에, 이 모델이 본질적으로 어떤 문제를 안고 있는지 이해해야 한다.
시간(Time)의 의미가 하나가 아니다
배치에서 "시간"은 단순하다 — 파일의 파티션 키(예: dt=2026-03-15)가 곧 시간이다. 하지만 스트리밍에서는 세 가지 시간이 존재한다.
| 시간 유형 | 정의 | 예시 |
| Event Time | 이벤트가 실제로 발생한 시각 | 사용자가 결제 버튼을 누른 시각 |
| Ingestion Time | 이벤트가 처리 시스템에 도착한 시각 | Kafka에 메시지가 적재된 시각 |
| Processing Time | 이벤트가 처리 엔진에서 처리되는 시각 | Flink 오퍼레이터가 레코드를 읽은 시각 |
이 세 시간은 항상 다르다. 네트워크 지연, 모바일 기기의 오프라인 상태, 카프카 파티션 리밸런싱 등으로 인해 Event Time과 Processing Time 사이에 수 초~수 분의 차이가 발생한다.
"오후 3시에 발생한 이벤트"를 "오후 3시 윈도우"에 넣으려면, 처리 엔진은 Event Time을 기준으로 동작해야 한다. 이것이 단순해 보이지만, 다음 문제와 결합되면 복잡해진다.
순서 보장 불가 (Out-of-order Events)
실제 발생 순서: e1(3:00:01) → e2(3:00:02) → e3(3:00:03)
처리 엔진 도착: e2(3:00:02) → e3(3:00:03) → e1(3:00:01) ← e1이 늦게 도착
분산 시스템에서 이벤트의 도착 순서는 발생 순서와 다를 수 있다. 배치에서는 전체 데이터를 모은 후 정렬하면 되지만, 스트리밍에서는 "아직 안 온 이벤트가 있을 수 있다" 는 불확실성을 안고 처리해야 한다.
이 문제를 해결하기 위해 등장하는 개념이 Watermark다 (섹션 4에서 상세 설명).
무한 데이터셋에서의 집계: Window는 왜 필요한가
데이터에 끝이 있으니 배치에서 GROUP BY는 자연스럽다.
-- 배치: 전체 데이터가 있으므로 가능
SELECT user_id, COUNT(*) FROM orders GROUP BY user_id
하지만 스트리밍에서 데이터는 끝이 없다(unbounded). "전체 데이터에 대한 집계"는 의미가 없거나, 상태가 무한히 커진다.
스트리밍 데이터: e1, e2, e3, e4, e5, e6, e7, ... (끝이 없음)
질문: "주문 수를 세라" → 언제까지? 전체? 영원히 카운트?
이 문제를 해결하기 위해 Window가 필요하다 — 무한 스트림을 유한한 구간으로 잘라서 집계 가능하게 만드는 장치다.
장애 복구와 상태(State)
배치 잡이 실패하면? 재실행하면 된다. 입력 데이터가 고정되어 있으므로 동일한 결과를 보장한다.
스트리밍 잡이 실패하면?

스트리밍 엔진은 처리 중인 상태를 지속적으로 관리해야 하고, 장애 시 상태 + 오프셋을 일관되게 복구해야 한다. 이것이 Checkpoint/Savepoint 메커니즘이 필요한 이유다. 이 네 가지 문제 — 시간 의미론, 순서 보장, 무한 집계, 상태 복구 — 가 스트리밍을 어렵게 만드는 본질적인 이유다. 그리고 이 문제들을 설계 수준에서 해결한 엔진이 Apache Flink다.
3. Flink 소개
설계 철학: "스트리밍 퍼스트"
Flink의 핵심 설계 철학은 명확하다: "스트리밍이 기본이고, 배치는 스트리밍의 특수 케이스(bounded stream)다."
| 관점 | Spark Structured Streaming | Apache Flink |
| 기본 모델 | 배치 → 스트리밍 확장 | 스트리밍 → 배치 축소 |
| 내부 실행 | 마이크로배치 (기본) | 연속 처리 (continuous) |
| 레이턴시 하한 | 트리거 간격 + 스케줄링 오버헤드 | 네트워크 버퍼링 수준 (ms) |
| Event Time | 지원하지만 마이크로배치 경계에 제약 | 네이티브, 레코드 단위 Watermark |
| 상태 관리 | 외부 저장소 의존 (HDFS 체크포인트) | 내장 State Backend (RocksDB) |
Flink가 해결하는 핵심 문제들
낮은 레이턴시
- 이벤트 도착 → 처리 → 출력까지 밀리초 단위.
- 마이크로배치의 "배치를 만들고 제출하는" 오버헤드가 없다.
정확한 Event Time 처리
- Watermark 메커니즘으로 out-of-order 이벤트를 정확히 처리한다.
- 각 레코드의 Event Time을 기준으로 윈도우에 할당한다.
대규모 상태 관리
- RocksDB State Backend: 메모리를 넘어서는 대규모 상태를 로컬 디스크에 저장.
- 수 TB 규모의 상태도 단일 잡에서 관리 가능.
Exactly-once 보장
- Checkpoint 기반의 경량 스냅샷 (Chandy-Lamport 알고리즘 변형).
- Source(Kafka offset) → 처리 상태 → Sink(트랜잭션 커밋)까지 end-to-end exactly-once.
4. Flink 핵심 개념 심화 소개
Time & Watermark
Event Time 기반 처리가 중요한 이유
모바일 앱에서 주행 데이터를 전송하는 상황을 생각해보자:
사용자 A: 터널 진입 (3:00:00) → 터널 통과 (3:02:00) → 데이터 전송 (3:02:30)
사용자 B: 정상 주행 (3:00:00) → 데이터 즉시 전송 (3:00:01)
Processing Time 기준이라면 사용자 A의 3:00:00 이벤트는 3:02:30에 처리되어, "3시 윈도우"가 아닌 "3시 2분 윈도우"에 들어간다. 비즈니스 관점에서 이것은 오류다. Event Time 기반 처리는 이벤트가 실제로 발생한 시각을 기준으로 윈도우에 할당한다.
Watermark의 역할
Watermark는 스트리밍 엔진이 "이 시각 이전의 이벤트는 (거의) 모두 도착했다" 고 선언하는 메커니즘이다.

Watermark W(t)가 도착하면:
t이전 시간의 윈도우를 닫고 결과를 출력할 수 있다.W(t)이후에 도착하는t이전 이벤트는 late event로 분류된다.
// Flink Watermark 설정 예시
DataStream<Event> stream = env
.addSource(kafkaSource)
.assignTimestampsAndWatermarks(
WatermarkStrategy
.<Event>forBoundedOutOfOrderness(Duration.ofSeconds(5))
.withTimestampAssigner((event, timestamp) -> event.getEventTime())
);
forBoundedOutOfOrderness(5초) — "이벤트는 최대 5초까지 늦게 도착할 수 있다"는 가정. Watermark는 관찰된 최대 Event Time에서 5초를 뺀 값으로 생성된다.
Late Event 처리 전략
| 전략 | 설명 | Flink 지원 |
| Drop | 늦은 이벤트 무시 | 기본 동작 |
| Allowed Lateness | 윈도우를 일정 시간 더 유지 | .allowedLateness(Duration) |
| Side Output | 늦은 이벤트를 별도 스트림으로 분리 | .sideOutputLateData(tag) |
Window
Window는 무한 스트림을 유한한 구간으로 분할하여 집계를 가능하게 하는 핵심 추상화다.



| Window 타입 | 설명 | 유스케이스 |
| Tumbling | 고정 크기, 겹치지 않음 | 분당 요청 수, 시간별 매출 |
| Sliding | 고정 크기, 슬라이드 간격만큼 겹침 | 이동 평균, "최근 5분간" 집계 |
| Session | 이벤트 간 gap 기준으로 동적 생성 | 사용자 세션 분석, 주행 트립 구간 |
예시 코드
// Tumbling Window: 1분 단위 이벤트 수 집계
stream
.keyBy(Event::getUserId)
.window(TumblingEventTimeWindows.of(Duration.ofMinutes(1)))
.aggregate(new CountAggregator());
// Sliding Window: 5분 윈도우, 1분 슬라이드
stream
.keyBy(Event::getUserId)
.window(SlidingEventTimeWindows.of(Duration.ofMinutes(5), Duration.ofMinutes(1)))
.aggregate(new AvgSpeedAggregator());
// Session Window: 30초 gap
stream
.keyBy(Event::getUserId)
.window(EventTimeSessionWindows.withGap(Duration.ofSeconds(30)))
.process(new SessionAnalyzer());
Trigger와 Evictor
- Trigger: 윈도우 결과를 언제 출력할지 결정한다.
- 기본: Watermark가 윈도우 끝을 넘을 때 발화.
- 커스텀: 레코드 수 기반, Processing Time 기반 등.
- Evictor: 윈도우 함수 실행 전/후에 특정 요소를 제거한다.
- 예: 시간 기반 Evictor — 윈도우 내에서 너무 오래된 요소 제거.
State & Checkpoint
Keyed State vs Operator State
graph TB
subgraph "Flink Operator"
direction TB
subgraph "Keyed State (키별 분리)"
SA["State(A)"]
SB["State(B)"]
SC["State(C)"]
end
subgraph "Operator State (오퍼레이터 전체)"
OS["List / Broadcast State"]
end
end
A["key=A"] --> SA
B["key=B"] --> SB
C["key=C"] --> SC
| 구분 | Keyed State | Operator State |
| 범위 | 키(key)별로 독립 | 오퍼레이터 인스턴스 전체 |
| 용도 | 사용자별 집계, 키별 상태 | Kafka offset, 소스 분할 정보 |
| 타입 | ValueState, ListState, MapState 등 | ListState, BroadcastState |
| 스케일링 | 키 재분배로 자동 스케일링 | 수동 분배 로직 필요 |
// Keyed State 예시: 사용자별 누적 거리
public class DistanceTracker extends KeyedProcessFunction<String, DriveEvent, Result> {
private ValueState<Double> totalDistance;
@Override
public void open(Configuration parameters) {
totalDistance = getRuntimeContext().getState(
new ValueStateDescriptor<>("total-distance", Double.class, 0.0)
);
}
@Override
public void processElement(DriveEvent event, Context ctx, Collector<Result> out) throws Exception {
double current = totalDistance.value() + event.getDistance();
totalDistance.update(current);
out.collect(new Result(event.getUserId(), current));
}
}
Checkpoint 동작 원리
Flink의 Checkpoint는 Chandy-Lamport 분산 스냅샷 알고리즘을 기반으로 한다.
sequenceDiagram
participant JM as JobManager
participant S as Source
participant Op1 as Operator-1
participant Op2 as Operator-2
participant Store as State Backend (S3/HDFS)
JM->>S: Checkpoint Barrier 주입
S->>S: 현재 offset 스냅샷
S->>Op1: Barrier 전파 (데이터 스트림에 삽입)
Note over S,Op1: Barrier 이전 데이터 = 이번 체크포인트에 포함
Op1->>Op1: Barrier 수신 → State 스냅샷
Op1->>Op2: Barrier 전파
Op2->>Op2: Barrier 수신 → State 스냅샷
Op1->>Store: 비동기 State 저장
Op2->>Store: 비동기 State 저장
Store-->>JM: 스냅샷 완료 ACK
Note over JM: Checkpoint 완료 (모든 오퍼레이터 ACK)
핵심 포인트:
- Barrier가 데이터 스트림 안에 삽입되어 흐른다 — 처리를 멈추지 않는다.
- 각 오퍼레이터는 Barrier를 만나면 자신의 State를 스냅샷한다.
- 모든 오퍼레이터의 스냅샷이 완료되면 하나의 일관된 Checkpoint가 된다.
Savepoint와의 차이
| 구분 | Checkpoint | Savepoint |
| 목적 | 장애 복구 (자동) | 운영 작업 (수동) |
| 트리거 | 주기적 자동 실행 | 사용자 명시적 트리거 |
| 용도 | 잡 실패 시 자동 복구 | 잡 업그레이드, 스케일링, 마이그레이션 |
| 보존 | 설정에 따라 자동 삭제 | 명시적 삭제 전까지 유지 |
Exactly-once Semantics
End-to-end Exactly-once가 가능한 조건
"Exactly-once"는 Flink 내부만으로는 완성되지 않는다. Source → Flink → Sink 전 구간이 협력해야 한다.
┌──────────┐ ┌──────────────────┐ ┌──────────┐
│ Source │────▶│ Flink │────▶│ Sink │
│ (Kafka) │ │ (Checkpoint) │ │(Kafka/DB)│
└──────────┘ └──────────────────┘ └──────────┘
│ │ │
재생 가능한 상태 + 오프셋을 트랜잭션
소스 필요 원자적으로 스냅샷 커밋 지원 필요
| 구간 | 요구사항 | 메커니즘 |
| Source → Flink | 재생 가능(replayable) 소스 | Kafka: offset 기반 재생 |
| Flink 내부 | 상태 일관성 | Checkpoint (Barrier 기반 스냅샷) |
| Flink → Sink | 중복 쓰기 방지 | Two-phase commit 또는 멱등 쓰기 |
Two-phase Commit
Flink의 Kafka Sink는 Two-phase commit 프로토콜로 exactly-once를 구현한다:

- Checkpoint가 완료되기 전에는 Kafka 트랜잭션을 커밋하지 않는다.
- Checkpoint 실패 시 트랜잭션은 abort되고, 소스 오프셋이 롤백되어 재처리된다.
- 결과적으로 "처리 + 출력"이 원자적으로 동작한다.
5. 처리 모델 선택 가이드 — 그래서 무엇을 써야 하는가?
배치, 마이크로배치, 스트리밍은 진화의 단계가 아니라 트레이드오프가 다른 선택지다. 일별 정산 리포트에 Flink를 쓸 이유는 없고, 실시간 이상 탐지에 Spark 배치를 쓸 수도 없다. "우리 팀은 어떤 모델을 써야 하는가?"에 대한 판단 기준을 정리한다.

판단 기준 요약
| 기준 | Batch | Micro-batch | Kafka Streams | Flink |
| 레이턴시 허용 | 분~시간 | 수 초~수 분 | 수 ms~수 초 | 수 ms~수 초 |
| Event Time 정확성 | 불필요 | 제한적 | 지원 | 네이티브 |
| 상태 크기 | N/A | 제한적 | 중소규모 | 대규모 (TB) |
| 운영 복잡도 | 낮음 | 중간 | 낮음 (라이브러리) | 높음 (클러스터) |
| 팀 러닝커브 | 낮음 | 중간 (Spark 경험 시 낮음) | 중간 | 높음 |
스트리밍이 필요한 순간 — 밀리초 레이턴시, 정확한 Event Time 처리, 대규모 상태 관리, end-to-end exactly-once — 이 모든 것을 설계 수준에서 해결한 엔진이 Apache Flink다. 물론 Flink만이 유일한 선택지는 아니다. 스트리밍 처리 엔진으로는 Kafka Streams, Apache Storm(레거시), Amazon Kinesis Data Analytics, Google Dataflow (Apache Beam 런타임) 등이 존재한다. 다만 이들 각각은 트레이드오프가 다르다:
| 대안 | 특징 | Flink 대비 한계 |
| Kafka Streams | 라이브러리 형태, 별도 클러스터 불필요 | 대규모 상태 관리 제한, 복잡한 윈도우/CEP 미지원 |
| Google Dataflow | 완전 관리형, Beam API | 클라우드 종속, 세밀한 튜닝 제한 |
| Amazon KDA | AWS 관리형 Flink | AWS 종속, 커스터마이징 제약 |
Flink는 가장 강력하지만 운영 복잡도와 러닝커브도 가장 높다. "Flink가 필요한 이유가 명확할 때" 도입하는 것이 올바른 접근이다. Flink의 핵심 개념들 — Watermark, Window, State, Checkpoint — 은 각각 스트리밍의 본질적 문제에 대응한다. 이 문제들이 "본질적"인 이유는, 스트리밍 모델의 전제 조건 자체에서 불가피하게 발생하기 때문이다:
- 시간 의미론: 분산 환경에서 글로벌 클럭이 존재하지 않으므로, 이벤트 발생 시각과 처리 시각의 괴리는 제거할 수 없다. → Watermark
- 순서 보장 불가: 네트워크 파티션과 비동기 전송이 존재하는 한, 이벤트 도착 순서는 발생 순서와 다를 수밖에 없다. → Event Time + Watermark
- 무한 집계: unbounded stream에서 "전체"라는 개념이 정의되지 않으므로, 유한 구간으로의 분할이 필수다. → Window
- 상태 복구: long-running 프로세스에서 장애는 확률의 문제이지 가능성의 문제가 아니다. 상태를 잃지 않으면서 재시작하려면 일관된 스냅샷이 필요하다. → Checkpoint
이 개념들을 이해하면 Flink 사용법을 넘어, 스트리밍 파이프라인의 정확성(correctness)과 내결함성(fault tolerance)을 설계 단계에서 검증할 수 있다. 어떤 스트리밍 엔진을 선택하든, 이 네 가지 문제에 대한 해당 엔진의 답을 확인하는 것이 아키텍처 의사결정의 출발점이 된다.
6. Flink vs Spark Structured Streaming 비교
| 항목 | Apache Flink | Spark Structured Streaming |
| 처리 모델 | True streaming (record-at-a-time) | Micro-batch (기본), Continuous Processing (실험적) |
| 레이턴시 | 수 ms ~ 수십 ms | 수백 ms ~ 수 초 (micro-batch), ~1ms (continuous, 제한적) |
| Event Time | 네이티브 지원, 레코드 단위 Watermark | 지원하지만 마이크로배치 경계에 제약 |
| Watermark | 레코드 단위 생성/전파 | 마이크로배치 단위 |
| 상태 관리 | 내장 State Backend (Heap, RocksDB) | HDFS 기반 체크포인트 |
| 상태 크기 한계 | 수 TB (RocksDB) | 메모리 + 디스크 직렬화 (상대적 제한) |
| Exactly-once | Checkpoint + Two-phase commit | Micro-batch 트랜잭션 |
| Window 타입 | Tumbling, Sliding, Session, Global + Custom | Tumbling, Sliding (Session은 제한적) |
| CEP (복합 이벤트) | FlinkCEP 라이브러리 내장 | 직접 구현 필요 |
| 배치 처리 | DataSet API / Table API (bounded stream) | 네이티브 강점 |
| SQL 지원 | Flink SQL (Table API) | Spark SQL (성숙도 높음) |
| 운영 복잡도 | 전용 클러스터 (Standalone/YARN/K8s) | 기존 Spark 클러스터 활용 가능 |
| 커뮤니티/생태계 | 스트리밍 특화, 성장 중 | 대규모 생태계, ML/배치 통합 |
| 적합한 시나리오 | 저레이턴시 스트리밍, 대규모 상태, CEP | 배치+스트리밍 통합, 기존 Spark 인프라 활용 |
참고
- Apache Flink 공식 문서 — https://nightlies.apache.org/flink/flink-docs-stable/
- Event Time & Watermarks — https://nightlies.apache.org/flink/flink-docs-stable/docs/concepts/time/
- Windows — https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/datastream/operators/windows/
- State & Fault Tolerance — https://nightlies.apache.org/flink/flink-docs-stable/docs/concepts/stateful-stream-processing/
- Checkpointing — https://nightlies.apache.org/flink/flink-docs-stable/docs/ops/state/checkpoints/
- Exactly-once with Kafka — https://nightlies.apache.org/flink/flink-docs-stable/docs/connectors/datastream/kafka/#fault-tolerance
- Apache Spark Structured Streaming 공식 문서 — https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html
- Apache Kafka 공식 문서 — https://kafka.apache.org/documentation/
- Chandy-Lamport 알고리즘 원논문 (Flink Checkpoint의 이론적 기반) — https://www.microsoft.com/en-us/research/publication/distributed-snapshots-determining-global-states-distributed-system/
- Lightweight Asynchronous Snapshots for Distributed Dataflows (Flink 논문) — https://arxiv.org/abs/1506.08603
'Engineering > Database System' 카테고리의 다른 글
| Data Skew 진단과 해결 (0) | 2026.03.17 |
|---|---|
| MySQL 타임존 다루기 (0) | 2025.01.20 |
| [Database] MySQL ORDER BY 방식 비교와 성능 (0) | 2024.07.16 |
| [Database] 빅 데이터 (Big Data) 1장 - Big Data Storage System (0) | 2024.04.13 |
| [Database] 데이터 타입 비교 : char vs varchar (0) | 2024.01.17 |
댓글