View
Kafka를 다뤄본 사람이라면 Apache Flink라는 이름을 한 번쯤 들어봤을 것이다. 다만 막상 "Flink가 무엇인가?"라고 물으면 제대로 답하는 사람이 별로 없다. 공식 docs는 영어로 깔끔하게 정리되어 있으나 입문자에게는 다소 불친절하다. 한국어 블로그 글들도 대부분 "스트리밍 프레임워크다"라는 한 줄로 끝내고 넘어간다.
각설하고 이 글에서는 Apache Flink가 실제로 무엇을 하는 도구인지, 왜 만들어졌는지, Spark와 어떻게 다른지, 언제 써야 하고 언제 쓰면 안 되는지 정리한다. 2~7년차 백엔드 개발자가 실시간 데이터 처리 요구사항을 받았을 때 "이것을 Flink로 가야 하는가"를 판단할 수 있는 수준까지 다룬다. 코드 예제도 있고 국내 기업 도입 사례도 함께 살펴본다.

출처: https://aeolabs.solutions/blog/flink/
Apache Flink란 대체 무엇인가
한 줄로 정리하면 분산 스트림 프로세싱 프레임워크다. 데이터가 끊임없이 들어오는 환경에서 실시간으로 처리하는 것이 주 목적이다. 배치 처리도 가능하지만 본질은 스트리밍이다.
어디서 시작되었는가
원래 독일 베를린공대(TU Berlin)에서 진행하던 Stratosphere라는 연구 프로젝트가 뿌리다. 2014년에 아파치 재단으로 이관되면서 이름이 Flink로 바뀌었다. 독일어로 "민첩한", "재빠른"이라는 뜻이다. 실제로 빠르다.
왜 만들어졌는가
Flink가 등장할 무렵 데이터 처리 세계는 Lambda 아키텍처가 대세였다. 배치는 Hadoop/Spark로 돌리고, 실시간은 Storm 같은 것으로 따로 돌리는 구조다. 다만 이는 비효율의 정점이다. 같은 로직을 두 번 작성해야 하고 두 시스템을 동시에 운영해야 한다.
그래서 등장한 것이 Kappa 아키텍처라는 개념이며, "전부 스트림으로 처리하면 되지 왜 두 개를 굴리는가"라는 발상이다. Flink가 이를 실제로 구현한 첫 프레임워크 중 하나다. 스트리밍이 본질이고 배치는 "유한한 스트림"으로 보는 관점이다.
지금은 어떤 상태인가
2025년 기준으로 Flink 2.0 시대가 열렸다. PyFlink가 많이 개선되어 파이썬 개발자도 쉽게 진입 가능해졌고, Unified Batch/Stream API도 한층 안정화되었다. 글로벌로 보면 우버, 알리바바, 넷플릭스가 대규모로 사용 중이고 국내에서도 카카오, 우아한형제들, 토스, 쿠팡 등이 사용한다.
Flink의 진짜 핵심 3가지
다른 스트리밍 프레임워크 대비 Flink가 자랑하는 차별점이 3가지 있다. 이를 이해하면 Flink의 80%는 이해한 것이다.
1. 스트리밍이 진짜 스트리밍이다
이것이 진짜 큰 차이다. Spark Streaming은 사실 마이크로배치다. 1초나 500ms 같은 짧은 간격으로 데이터를 모아서 미니 배치로 돌리는 방식이다. 스트리밍이라고 부르긴 하지만 본질은 배치다.
Flink는 이벤트 하나하나가 들어오는 즉시 처리한다. 그래서 레이턴시가 ms(밀리초) 단위로 떨어진다. Spark Streaming은 아무리 잘 튜닝해도 초 단위가 한계다. 금융 거래 이상탐지나 광고 실시간 입찰처럼 ms가 중요한 도메인에서는 Flink가 유리하다.
2. 상태(State)를 프레임워크가 관리해준다
스트림 처리에서 가장 골치 아픈 것이 상태 관리다. 예컨대 "최근 5분간 사용자별 클릭 수 집계" 같은 것을 하려면 어딘가에 카운트를 저장해두어야 한다. 보통은 Redis나 메모리에 직접 저장하는데, 이러면 장애가 났을 때 복구가 지옥이다.
Flink는 상태 저장(stateful)을 프레임워크 차원에서 지원한다. 내부적으로 RocksDB 기반 상태 저장소를 쓰고, 체크포인트(checkpoint)라는 메커니즘으로 주기적으로 스냅샷을 떠놓는다. 장애가 발생해도 마지막 체크포인트부터 자동으로 복구된다.
직접 Redis를 붙여 상태 관리를 해본 사람이라면 이것이 얼마나 편한지 바로 알 것이다. exactly-once 처리 보장도 이 체크포인트 메커니즘 덕분에 가능하다.
3. 이벤트 타임(Event Time)과 워터마크(Watermark)
이것이 Flink의 진짜 무기다. 다른 프레임워크들도 흉내는 내지만 Flink만큼 정교하게 다루는 도구는 별로 없다.
스트림을 처리할 때 시간 개념은 두 가지다:
- 처리 시간(Processing Time): Flink가 이벤트를 받은 시점
- 이벤트 시간(Event Time): 이벤트가 실제로 발생한 시점
네트워크 지연 때문에 이벤트가 늦게 도착하는 것은 일상적인 일이다. 모바일 앱 로그 같은 것은 사용자 핸드폰이 오프라인이었다가 한참 뒤에 한꺼번에 들어오기도 한다. 처리 시간 기준으로 집계하면 결과가 모두 어긋난다.
Flink는 워터마크라는 개념으로 "이 시점까지의 이벤트는 다 들어왔다고 보자"라는 기준을 잡는다. 늦게 도착한 데이터는 별도로 처리하거나(late event handling) 정해진 시간 안에 들어오면 윈도우에 다시 반영한다. 이것이 없으면 실시간 집계 결과는 결코 정확할 수 없다.
Spark Streaming과는 무엇이 다른가
가장 자주 받는 질문이다. 표로 정리하면 다음과 같다.
| 항목 | Apache Flink | Spark Streaming |
| 처리 방식 | 진짜 스트리밍 (이벤트 단위) | 마이크로배치 |
| 레이턴시 | 밀리초 단위 | 초 단위 |
| 상태 관리 | 네이티브 지원 (RocksDB) | 추가 설정 필요 |
| 이벤트 타임 처리 | 정교한 워터마크 메커니즘 | 기본 지원 약함 |
| 배치 처리 | DataStream + Table API | RDD + DataFrame |
| 러닝 커브 | 높음 | 중간 |
| 생태계 | 작지만 깊음 | 거대함 (MLlib, GraphX 등) |
| 한국어 자료 | 적음 | 많음 |
언제 Flink를 쓰고 언제 Spark를 쓰는가
솔직히 말하면 둘 다 사용 가능한 경우가 많다. 그래서 기술 스펙보다 팀 역량과 기존 인프라를 먼저 봐야 한다.
Flink가 유리한 경우:
- 레이턴시가 진짜 중요하다 (ms 단위)
- 복잡한 상태 관리가 필요하다
- 이벤트 시간 기반의 정확한 집계가 필요하다
- 이미 Kafka 위주 아키텍처다
Spark가 유리한 경우:
- 팀이 Spark에 이미 익숙하다
- 머신러닝 파이프라인과의 연동이 많다
- 배치가 메인이고 스트리밍은 부수적이다
- 한국어 자료가 많이 필요한 주니어 위주의 팀이다
Flink 구조 간단히 살펴보기
내부 구조를 몰라도 Flink를 사용할 수는 있으나, 알면 디버깅할 때 훨씬 편하다.
JobManager와 TaskManager
Flink 클러스터는 크게 두 종류의 노드로 구성된다.
- JobManager: 조율자다. 잡을 스케줄링하고, 체크포인트를 트리거하고, 장애 복구를 담당한다. 마스터 노드 역할이다.
- TaskManager: 실제 작업을 실행하는 워커 노드다. 데이터를 받고, 변환하고, 다음 단계로 넘기는 일을 한다. 보통 여러 대를 띄운다.
배포 환경은 standalone, YARN, Kubernetes 모두 가능하다. 요즘은 쿠버네티스로 띄우는 것이 대세다.
데이터 흐름 (Source → Transform → Sink)
Flink 잡은 결국 소스 → 변환 → 싱크 흐름이다. 흔한 프로덕션 파이프라인은 다음과 같은 모양이다:
Kafka(소스) → Flink(변환/집계) → Elasticsearch 또는 DB(싱크)
DataStream API로 작성하면 이런 식이다:
DataStream<String> source = env
.addSource(new FlinkKafkaConsumer<>("input-topic", schema, props));
DataStream<WordCount> result = source
.flatMap(new Tokenizer())
.keyBy(wc -> wc.word)
.window(TumblingEventTimeWindows.of(Time.minutes(1)))
.sum("count");
result.addSink(new FlinkKafkaProducer<>("output-topic", schema, props));
코드만 보면 Spark와 비슷해 보이지만, 내부적으로는 완전히 다르게 동작한다.
실제로 어떻게 쓰는가? Kafka 연동 예제
프로덕션에서 가장 흔한 조합이 Kafka + Flink다. 사실상 거의 표준 조합이라고 봐도 무방하다. 간단한 워드카운트 예제로 감을 잡아보자.
Java 버전
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
KafkaSource<String> source = KafkaSource.<String>builder()
.setBootstrapServers("localhost:9092")
.setTopics("text-input")
.setGroupId("flink-group")
.setValueOnlyDeserializer(new SimpleStringSchema())
.build();
DataStream<String> text = env.fromSource(
source,
WatermarkStrategy.noWatermarks(),
"Kafka Source"
);
DataStream<Tuple2<String, Integer>> counts = text
.flatMap((String line, Collector<Tuple2<String, Integer>> out) -> {
for (String word : line.split("\\s")) {
out.collect(new Tuple2<>(word, 1));
}
})
.returns(Types.TUPLE(Types.STRING, Types.INT))
.keyBy(value -> value.f0)
.window(TumblingProcessingTimeWindows.of(Time.seconds(10)))
.sum(1);
counts.print();
env.execute("Word Count");
10줄 남짓한 코드로 실시간 워드카운트가 동작한다. Kafka 토픽에서 텍스트를 받아 10초 단위로 집계해 출력한다.
PyFlink 버전
파이썬 개발자라면 PyFlink도 가능하다. 예전에는 다소 불안정했으나 2.0 이후로는 쓸 만해졌다.
from pyflink.datastream import StreamExecutionEnvironment
from pyflink.datastream.connectors.kafka import KafkaSource
from pyflink.common.serialization import SimpleStringSchema
from pyflink.common.watermark_strategy import WatermarkStrategy
env = StreamExecutionEnvironment.get_execution_environment()
source = KafkaSource.builder() \
.set_bootstrap_servers("localhost:9092") \
.set_topics("text-input") \
.set_group_id("flink-py-group") \
.set_value_only_deserializer(SimpleStringSchema()) \
.build()
stream = env.from_source(source, WatermarkStrategy.no_watermarks(), "Kafka Source")
stream.print()
env.execute("PyFlink Example")
문법은 다르지만 개념은 동일하다. 데이터 사이언스 팀이 스트리밍 처리에 진입할 때 PyFlink가 진입 장벽을 낮춰준다.
국내 기업 도입 사례
해외 사례는 많이 알려져 있으나(우버, 알리바바, 넷플릭스), 국내 사례가 더 와닿을 것이다.
카카오: 카카오톡 메시지 처리 일부와 추천 시스템 백엔드에서 Flink를 활용 중이다. 일평균 수십억 건의 이벤트를 실시간으로 처리하는 파이프라인이 동작한다.
우아한형제들(배달의민족): 실시간 주문 모니터링과 이상탐지에 Flink를 도입했다. 라이더 위치 추적, 배달 시간 예측 같은 데이터 흐름에 활용 중이다.
토스: 금융 거래 이상탐지에 Flink를 적극 활용한다. ms 단위 레이턴시가 진짜 중요한 도메인이라 Flink가 자연스러운 선택이었다.
쿠팡: 실시간 추천과 광고 입찰, 재고 관리 파이프라인에서 Flink를 쓴다. 대규모 클러스터 운영 노하우가 기술 블로그에 공유되어 있다.
공통점이 보이는데, 모두 이벤트 단위 즉시 처리가 핵심인 도메인이다. 그리고 다들 Kafka와 함께 쓴다. 사실상 한국 빅테크에서 실시간 처리를 한다고 하면 Kafka + Flink가 표준 조합이다.
다만 Flink가 만능은 아니다 - 언제 쓰면 안 되는가
장점만 늘어놓는 글은 의심해야 한다. Flink도 단점이 많다. 도입했다가 걷어내는 사례도 적지 않게 보았다.
운영 복잡도가 매우 높다
Flink 클러스터 운영은 쉽지 않다. 체크포인트 관리, 상태 백엔드 튜닝, 백프레셔(backpressure) 모니터링, 워터마크 설정 등 챙길 것이 많다. 전담 엔지니어가 한두 명은 있어야 굴러간다. 이것 없이 깔았다가 장애 한 번 나면 복구하지 못해 큰 혼란이 온다.
소규모 팀에는 오버킬이다
스타트업이 "우리도 실시간 처리가 필요하다"라며 Flink를 깔았다가 6개월 뒤에 걷어내는 경우가 꽤 있다. 처리량이 진짜 많지 않다면 그냥 Kafka Streams나 간단한 컨슈머로 충분하다. Flink는 클러스터 리소스도 꽤 많이 소비한다.
러닝 커브가 가파르다
Spark를 쓰던 사람도 Flink 적응에 시간이 걸린다. 이벤트 타임, 워터마크, 상태 백엔드 같은 개념이 처음에는 머리가 아프다. 한국어 자료도 Spark보다 적어 학습 비용이 더 높다.
배치 위주에는 의미가 없다
배치 처리만 한다면 Spark나 그냥 Airflow + 일반 작업이 더 단순하다. Flink의 진가는 스트리밍에서 나온다. 배치 잡을 돌리려고 Flink를 쓰는 것은 기술 자위에 가깝다.
솔직한 판단 기준
다음 3가지를 모두 만족하면 Flink를 고려해도 된다:
- 진짜 ms 단위 레이턴시가 필요하다
- 처리량이 충분히 크다 (초당 수만 건 이상)
- 운영할 수 있는 팀 역량이 있다
하나라도 맞지 않다면 Kafka Streams나 Spark Streaming부터 검토하는 것이 낫다.
시작하려면 무엇을 봐야 하는가
Flink를 한 번 다뤄보고 싶다면 Docker Compose가 가장 빠르다. 공식 이미지가 잘 갖추어져 있다.
추천 학습 순서
- DataStream API 기본 - 워드카운트부터 돌려보기
- Source/Sink 연동 - 파일이나 소켓으로 데이터 받기
- Kafka 연동 - 실전 환경 구성
- 윈도우 연산 - 텀블링, 슬라이딩, 세션 윈도우
- 상태 관리 - ValueState, ListState 사용해보기
- 체크포인트와 세이브포인트 - 장애 복구 시뮬레이션
- Table API / SQL API - 선언적으로 작성해보기
- PyFlink (필요한 경우)
추천 자료
- 공식 docs - 영어이지만 정확하다. 결국 여기로 와야 한다
- Flink GitHub - 예제 코드가 많다
- Confluent 블로그 - Kafka + Flink 조합 글이 많다
- 카카오, 토스, 우아한형제들 기술블로그 - 실전 사례
첫 프로젝트 아이디어
- 깃허브 이벤트 API를 받아 인기 레포 실시간 집계
- 트위터/X API로 키워드 트렌드 윈도우 집계
- 로컬 IoT 센서 데이터 이상치 탐지
- 게임 서버 로그로 실시간 유저 행동 분석
작게 시작하는 것이 진짜 중요하다. 처음부터 거대한 파이프라인을 짜려고 하면 시작도 못 하고 끝난다.
Apache Flink, 지금 배워둬야 하는 이유 정리
Apache Flink를 정리하면 다음과 같다:
- 본질: 진짜 스트리밍 + 상태 관리 + 이벤트 타임 처리에 강한 분산 프레임워크다
- 최고 강점: 레이턴시 ms 단위, exactly-once 보장, 정교한 워터마크 메커니즘
- 최대 약점: 운영 복잡도가 높고 러닝 커브가 가파르며, 소규모 팀에는 오버킬이다
실시간 데이터 처리 수요는 계속 커지는 중이다. 카카오, 토스, 쿠팡 같은 회사들이 Flink에 베팅하는 이유가 있다. Kafka를 쓰는 팀이라면 Flink는 알아둬야 한다. 당장 도입하지 않더라도 개념 자체는 다른 프레임워크에서도 통용되는 지식이다.
특히 이벤트 타임, 워터마크, 상태 관리 같은 개념은 Kafka Streams나 Spark Structured Streaming도 모두 흉내 내는 중이라 Flink로 익혀두면 어디 가서도 유용하다. 솔직히 한국 빅테크 백엔드/데이터 엔지니어 면접에서도 점점 더 자주 나오는 주제다.
처음에는 로컬에서 Docker Compose로 띄워놓고 워드카운트 한 번 돌려보는 것부터 시작하면 된다. 10분이면 충분하다. 그 다음에 Kafka 연동을 해보고, 윈도우 집계를 작성해보고, 상태 관리를 다뤄보면 어느새 실전 감각이 생긴다. Apache Flink가 어렵긴 하지만 한 번 익혀놓으면 실시간 데이터 처리에 대한 시야가 완전히 달라진다. 지금 시작해도 늦지 않다.
'DevOps' 카테고리의 다른 글
| RabbitMQ vs Kafka, 언제 무엇을 사용해야 하는지 정리한다 (0) | 2026.04.30 |
|---|---|
| 도커를 만든 사람을 알면 더 흥미롭다, 솔로몬 하익스 이야기 (0) | 2026.04.30 |
| CGI, WSGI, WAS의 차이 정리 — 웹서버 공부할 때 헷갈리는 개념 한 번에 끝내기 (0) | 2026.04.25 |
| 트래픽 Traffic 1000배가 터져도 죽지 않는 서버를 만드는 법 (1) | 2026.04.24 |
| 쿠버네티스(Kubernetes)는 누가 만들었는가? 개발자 3인방과 탄생 배경을 파헤치다 (1) | 2026.04.24 |
