💡 이 문서는: Flink에서 여러 연산자를 하나의 태스크로 묶어 실행하는 Operator Chaining 최적화 기법을 다룹니다. Flink에선 기본적으로 큰 작업이나 IO 관련된 부분에서 체인을 끊는 방식으로 제공하고 있고 최적화가 잘 되어 있어 공식문서나 커뮤니티에서도 기본 설정으로 사용하는 것을 추천하지만, 알면 내 마음대로 할 수 있고 모르면 Flink 맘대로 하는 것이기 때문에 조사한 내용을 정리한다.


기본 개념

정의

Operator Chaining은 여러 연산자를 하나의 태스크로 묶어 실행하는 최적화 기법입니다.

동작 방식

체이닝 전
┌────────┐   ┌─────────┐   ┌─────────┐   ┌──────┐
│ Source │ → │ Filter1 │ → │ Filter2 │ → │ Map  │
└────────┘   └─────────┘   └─────────┘   └──────┘
    ↓            ↓             ↓            ↓
4개의 독립 태스크, 3번의 네트워크 전송

체이닝 후
┌──────────────────────────────────────┐
│  Source → Filter1 → Filter2 → Map    │
└──────────────────────────────────────┘
              ↓
1개의 태스크, 0번의 네트워크 전송

동작 원리

항목 설명 효과
메모리 참조 전달 객체를 직렬화하지 않고 포인터만 전달 직렬화 비용 제거
단일 스레드 실행 같은 스레드에서 연속 실행 Context Switch 제거
L1 Cache 활용 같은 CPU 코어에서 실행 Cache Hit Rate 95%+

체이닝 조건

필수 조건

연산자가 체이닝되려면 모든 조건을 만족해야 합니다:

조건 설명 확인 방법
같은 병렬도 setParallelism()이 동일 Flink Web UI → Job Graph
같은 슬롯 그룹 slotSharingGroup()이 동일 코드 검토
체이닝 활성화 disableChaining() 미호출 코드 검토
재분배 없음 keyBy(), rebalance() 등 없음 데이터 흐름 분석
Forward 전략 1:1 데이터 전달 파티션 전략 확인

체이닝 불가능한 경우

❌ 병렬도가 다른 경우

source.setParallelism(4)    .filter(...).setParallelism(2)  // 체이닝 불가

❌ 재분배가 발생하는 경우

source.filter(...)    .keyBy(...)  // 체이닝 경계 (재분배 발생)