회사에서 Confluent 기반 Poc를 진행중에 마침 Confluent에서 Flink 워크샵이 열려 참석했다. 실습 위주의 워크샵으로 Flink를 처음 다뤄보는 입장에서 도움이 되었다. 아래는 실습과 개념을 정리한 후기이다.
Shift Left
기존 데이터 파이프라인
flowchart LR A[Database] --> B[배치 ETL/ELT] B --> C[Data Warehouse] C --> D[데이터 제공]
Mermaid
복사
•
전통적인 파이프라인은 shift-right 구조
→ 오류 발견 시점이 늦어 품질 이슈가 발생하기 쉽다
•
데이터의 지연으로 로그 분석까지 시간이 오래 걸려 비효율적
실시간 파이프라인
•
Shift left → 데이터가 유입되는 Upstream 시점에서 바로 처리해 오염된 데이터 전파를 막는 개념
•
Flink 기반 스트리밍 처리로 이벤트 들어오는 즉시 정제, 집계, 검증 가능
배치 vs 스트리밍
구분 | 배치 처리 (Batch) | 스트리밍 처리 (Streaming) |
처리 시점 | 일정 주기 | 이벤트 발생 즉시 |
지연 시간 | 수 분 ~ 수 시간 | 수 초 이내 |
상태 관리 | 파일·DB 기반 | 체크포인트·스냅샷(State) |
처리 모델 | 일괄 처리 | 연속 처리(하나씩/마이크로 배치) |
사용 사례 | 일일 리포트 | 실시간 모니터링, 알림, 사기 탐지 |
Apache Flink란?
Flink는 고성능 스트리밍 및 배치 처리용 분산 처리 프레임워크
대규모 이벤트 데이터를 정확하고 빠르게 처리할 수 있어 실시간 데이터 인프라에 적합하다
주요 아키텍처 구성
•
JobManager / TaskManager 구조
◦
JobManager: 전체 작업의 스케줄링 및 상태 관리를 담당하는 마스터 노드
▪
DAG 형태의 실행 플랜 생성
▪
장애 복구 시 체크포인트 복원 처리
◦
TaskManager: 실제 데이터를 처리하는 워커 노드
▪
각 TaskManager는 여러 개의 Task Slot 보유
▪
병렬 실행을 통해 고속 처리 가능
•
상태(Stateful) 기반 처리
◦
Flink는 집계/조인/패턴 인식과 같은 복잡한 연산에서 내부 상태(State) 를 유지
◦
상태는 메모리에 유지되며, 로컬 RocksDB나 Heap 상태 백엔드로 구성 가능
◦
이 상태 때문에 TTL 전략이 중요함
•
Checkpoint & Savepoint
◦
Checkpoint: 일정 주기마다 전체 상태를 백업하여 장애 발생 시 자동 복구 가능
▪
Exactly-once 보장을 위해 사용
▪
Kafka Offset과 연동 가능
◦
Savepoint: 수동 트리거로 생성하는 영속 상태 스냅샷
시간 개념
•
Event Time(이벤트 시간)
◦
데이터가 실제 발생한 시간
◦
정확한 시간 기반 분석이 가능
•
Processing Time(처리 시간)
◦
해당 작업을 실행하는 기계의 시스템 시간
◦
지연 고려하지 않고 가장 빠르게 처리할 때 사용
◦
레코드가 시스템에 도착하는 속도나 네트워크 중단 등의 영향을 받기 때문에 윈도우 연산시 레코드가 다른 윈도우에 할당 될 수 있음
•
Ingestion Time(수집 시간)
◦
Source에서 Flink로 유입된 시간
◦
Processing Time과 Event Time의 중간의 개념
◦
소스에서 한번 할당되는 안정적인 타임스탬프로 윈도우 연산에 동일한 기준 제공
워터마크 Watermark
•
이벤트 타임 기반 처리에서, 지연된 이벤트 허용 범위를 정의
•
Flink는 Watermark를 기준으로 이 윈도우는 이제 완료(종료)되었다고 판단함
워터마크가 필요한 이유
•
스트리밍 환경에서는 이벤트가 항상 제시간에 도착하지 않음
◦
유저가 9:59에 행동했지만 네트워크 지연으로 10:01에 도착할 수 있음
•
이때 단순히 processing time 기준으로 처리하면 지연된 이벤트가 집계에서 누락
•
그래서 event time 기준으로 윈도우 종료를 결정하기 위해 워터마크를 사용
예시
•
10:00까지 도착할 이벤트를 30초 지연까지 허용하고 싶다면 watermark = 10:00 - 30초
•
1분짜리 윈도우 사용한다고 가정
이벤트 시간 실제 도착 시간
09:59:50 (10:00:05 도착)
10:00:10 (10:00:12 도착)
10:00:25 (10:00:26 도착)
10:00:30 (10:00:45 도착)
Plain Text
복사
•
가장 최신 값 10:00:30 으로 워터마크 갱신 → 10:00:30 - 30 = 10:00:00
•
이후 더 늦은 이벤트들이 들어오고 워터마크가 10:01:00 넘어가는 순간 10:00:00 ~ 10:01:00 윈도우 마감
Kafka 와의 관계
Kafka는 이벤트 저장소(저장 계층) 역할
Flink는 Kafka로부터 메시지를 읽어와 실시간 처리(컴퓨팅 계층) 역할
•
Kafka → Flink → Redis / S3 / PostgreSQL 등 다양한 싱크로 연동
•
Kafka의 Topic은 Flink에선 Source Topic으로, Sink는 S3, JDBC, Redis 등 유연하게 설정 가능
Flink, Kafka Streams, ksqlDB 주요 차이점
Kafka Streams와 ksqlDB는 Kafka 환경에서만 가능하지만, Flink는 Kafka 외에도 다양한 소스/싱크를 지원하고 범용성이 뛰어남
속성 | CP Flink(오픈소스) | CC Flink | Kafka Streams | ksqlDB |
특징 | 독립 실행형 | Confluent Cloud의 관리형 | Java 라이브러리 | SQL기반 |
처리 모드 | 스트림+배치 | 스트림+배치 | 스트림 전용 | 스트림 전용 |
장애 복구 | 체크포인트/스냅샷 | 체크포인트/스냅샷 | 메시지 재생 | 메시지 재생 |
배포 모델 | 자체 관리 | Serverless | 애플리케이션 내장 | 별도 배포 |
언어 유연성 | SQL, Table API, DataStream, ProcessFunction | ANSI SQL, Java UDF | Java API | SQL |
실습
Confluent Marketplace에서 제공하는 실시간 프로듀싱 토픽을 이용한 실습으로 간단히 Lab1만 정리, 이후는 직접 Poc 진행하면서 더 상세히 정리할 예정
기본적으로 kafka 토픽이 곧 Flink에서는 테이블이라고 생각하고 SQL을 작성하면 된다
테이블 조회
•
SHOW TABLES
•
SHOW CREATE TABLE <table>
•
DESCRIBE <table>
기본 조회(SELECT)
•
SELECT * FROM products;
•
SELECT * FROM customers WHERE name LIKE 'B%';
•
DESCRIBE EXTENDED orders;
•
SELECT order_id, product_id, customer_id, $rowtime FROM orders WHERE customer_id=3001 LIMIT 2;
중복 제거
•
중복 확인: SELECT order_id, COUNT(*) FROM orders GROUP BY order_id;
•
첫 이벤트만 남기기 (ROW_NUMBER 윈도우 함수)
•
결과를 unique_orders 테이블로 생성
CREATE TABLE unique_orders AS
SELECT order_id, product_id, customer_id, price
FROM (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY order_id
ORDER BY `$rowtime` ASC
) AS rownum
FROM orders
)
WHERE rownum = 1;
SQL
복사
실행 계획 확인 (EXPLAIN)
•
EXPLAIN CREATE TABLE unique_orders AS …
•
물리 플랜, State 크기, Upsert 키 확인
집계 (Aggregations)
•
브랜드별 모델 수, 벤더 수:
SELECT brand,
COUNT(DISTINCT name),
COUNT(DISTINCT vendor)
FROM products
GROUP BY brand;
SQL
복사
•
페이지 뷰 분석:
SELECT url,
COUNT(click_id),
COUNT(DISTINCT user_id),
AVG(view_time),
MAX(view_time)
FROM clicks
GROUP BY url
HAVING COUNT(click_id) > 2;
SQL
복사
타임 윈도우 (Time Windows)
$rowtime 값은 시스템 자체 컬럼
•
Tumbling (1분)
SELECT window_time,
COUNT(DISTINCT order_id)
FROM TABLE(
TUMBLE(
TABLE unique_orders,
DESCRIPTOR(`$rowtime`),
INTERVAL '1' MINUTES
)
)
GROUP BY window_start, window_end, window_time;
SQL
복사
•
Hopping (10분, 슬라이드 5분)
SELECT window_start, window_end, window_time,
COUNT(DISTINCT order_id)
FROM TABLE(
HOP(
TABLE unique_orders,
DESCRIPTOR(`$rowtime`),
INTERVAL '5' MINUTES,
INTERVAL '10' MINUTES
)
)
GROUP BY window_start, window_end, window_time;
SQL
복사

