🧭 서론
최근 스트리밍 시스템을 공부하면서 '진짜'스트리밍 처리, 실시간 처리, 이벤트 도착하자마자 처리 라는 개념을 이해하기 위해 리서치한 내용을 바탕으로 글을 작성한다.
"Flink는 진짜 스트리밍 처리 시스템이다"
이 말, 도대체 어떤 의미일까.
Flink는 어떻게 동작하길래 '진짜 스트리밍'이라는 수식어가 붙는걸까?
마이크로배치로 동작하는 스파크랑 비교하면서 알아봤다.
📌 본론
✅ 마이크로배치란?
Spark Structured Streaming은 사실 이름과 다르게 완전한 실시간(streaming) 시스템이 아니다.
데이터를 아주 짧은 시간 단위(예: 1초, 500ms)로 '모아서' 한 번에 처리하는 방식
이것을 마이크로배치(Micro-Batch) 라고 부른다.
즉, Spark는 실시간처럼 보일 뿐, 내부적으로는 작은 배치들의 연속 실행.
✅ 네이티브 스트리밍이란?
Flink와 Kafka Streams처럼 이벤트가 들어오자마자 바로 연산을 수행하는 방식을 '네이티브 스트리밍(Native Streaming)'라고 부른다.
- 데이터를 기다리지 않고
- 이벤트가 들어오는 즉시
- 연산자(map, filter 등)를 실행하고
- 필요한 경우 바로 Sink 로 전송
즉, 진짜로 실시간 반응이 가능한 구조.
✅ 동작 방식 비교
항목 | Spark Structured Streaming | Apache Flink |
처리 단위 | 배치 단위 (micro-batch) | 이벤트 단위 (record-at-a-time) |
처리 시작 시점 | 트리거 발생 시 | 이벤트 도착 시 즉시 |
Sink 전송 방식 | 전체 처리 후 한번에 전송 | 처리 후 바로 Sink로 전송 가능 |
✅ 처리 흐름은 어떻게 다를까?
▶ Spark
Kafka → (Trigger 주기마다 수집)
→ DataFrame 생성
→ 연산 (map/filter/window 등)
→ 전체 결과 Sink로 write
▶ Flink
Kafka → poll() → record 1
→ map → filter → window → sink
Kafka → record 2
→ map → filter → window → sink
(이벤트가 들어오자마자 흐름 시작)
✅ Flink가 ‘진짜 실시간’ 이라고 부르는 이유
- 이벤트가 도착하는 즉시 처리 로직을 실행
- 데이터를 모아두지 않고 바로 연산자 체인으로 전달
- 연산 후 바로 Sink로 내보낼 수 있음
- 처리 흐름 전체가 event-driven 구조
즉, 마이크로배치의 경우 100개의 데이터가 들어오면 100개를 한 번에 처리하고 마지막에 write 하는 방식이라면,
스트리밍 처리는 이벤트 하나하나를 개별로 완료처리 한다는 것.
그럼 여기서 궁금한 게 생긴다.
✅ 이벤트를 어떻게 감지하지?
사실 이건 source connect 마다 다르다.
많이 사용하는 Kafka 를 메시지 브로커로 사용한다면 카프카의 경우 pull 기반이다.
즉, Flink 내부에서 계속 poll() 하여 추가된 데이터가 있는지 체크하는 방식이지
카프카부터 이벤트가 들어온 걸 실시간으로 감지하지 않는다.
카프카를 예시로 들어보면,
100ms 마다 poll() 하여 추가된 이벤트들을 가져와 Flink 내부 큐에 쌓아두고 하나씩 처리하는 방식이다.
이벤트가 발생한 걸 플링크가 요술처럼 바로 감지해서 '진짜' 실시간으로 '넘겨주는' 게 아니다.
단지, 소스에서 이벤트를 가져온 후부터 연산자에 바로바로 넘겨주는 걸 '네이티브 스트리밍' 이라고 부른다.
데이터 생성 즉시 이벤트 단위로 처리
즉 ! 이벤트를 전달하는 주체(Source)와 / 이벤트를 처리하는 주체(Flink)를 구분할 필요가 있다.
플링크나 카프카 스트림즈에서 부르는 실시간 스트리밍이란 건, 내부 처리에 대한 걸 얘기하는 것.
비교를 많이하는 스파크의 마이크로배치는 레코드 별 처리가 아닌 결국 하나의 배치처리 (모아서 한 번에).
✅ 마이크로 배치든 스트리밍이든 kafka poll을 100ms 로 하면 동일한 것 아닌가?
차이점이 분명히 있다.
예시를 보겠다.200ms 동안 2번 poll 했다고 가정을 해보자.첫 번째 poll 때 500개를 가져왔고, 두 번째 poll 때 100개를 가져온다.
마이크로배치의 경우
첫 번째 poll -> 500개를 한 번에 처리 -> write -> 두 번째 poll
스트리밍의 경우
첫 번째 poll -> 레코드 1 처리 -> 레코드 2 처리 -> ... -> 두 번째 poll -> 레코드 456 처리
즉,
마이크로배치는 500개를 다 처리할 때 동안 다음 poll 을 하지 않는다. (트리거 방식)스트리밍의 경우 500개 처리가 다 되는 것과 관계 없이 100ms가 지나면 다음 poll을 진행한다.(물론, 내부 부하를 방지하기 위해 백프레셔 같은 동작도 존재)
🫡 결론
구분 | Spark Structured Streaming | Apache Flink |
처리 철학 | 마이크로배치 | 네이티브 스트리밍 |
실행 시점 | 트리거 주기마다 | 이벤트 도착 즉시 |
Sink 전송 | 배치 처리 후 한번에 | 처리 직후 개별 전송 가능 |
실시간성 | 유사 실시간 | 진짜 실시간 |
공부하면서 헷갈렸던 부분은,
메시지 브로커에 이벤트 생긴 걸 어떻게 실시간으로 알 수 있지?
마이크로배치랑 뭐가 다르길래 실시간 스트리밍이란거지? 였는데 이번 기회에 정리해본다.