Spark Structured Streaming을 활용하여 실시간 데이터 파이프라인을 만들다 보면 종종 스트리밍 데이터(streaming DataFrame) 와 정적 테이블(static DataFrame) 을 결합해야 하는 상황이 발생합니다.
예를 들어:
- 실시간 이벤트(streamingDF)에 사용자 정보(static user lookup)를 매칭
- IoT 센서 이벤트에 센서 메타데이터 조인
- 로그 데이터에 저장된 reference table을 매핑
이처럼 stream-static join은 실제 데이터 엔지니어링에서 굉장히 흔합니다. 하지만 Structured Streaming에서는 모든 조인이 허용되는 것이 아닙니다. 일부 조인은 기술적으로 불가능하거나, Spark 엔진의 일관성을 위해 금지되어 있습니다.
이번 글에서는:
- Stream-Static Join이 무엇인지
- 어떤 조인이 가능하고
- 어떤 조인이 불가능한지
- 왜 그런 제한이 존재하는지
를 명확하고 쉽게 정리해보겠습니다.
✔ Stream-Static Join이란?
Stream-static join은 말 그대로:
스트리밍 DataFrame(계속 들어오는 데이터)
+
정적(Static) DataFrame(변하지 않는 데이터)
를 조인하는 작업
예시 코드:
streamingDF.join(staticDF, "user_id", "inner")
여기서 중요한 특징은:
- streamingDF는 계속 증가 (infinite input)
- staticDF는 고정된 스냅샷 (finite input)
즉, 스트리밍 조인은 각 microbatch에서 새로 들어온 데이터를 static 데이터와 결합하여 처리합니다.
✔ Stream-Static Join이 필요한 이유
일반적인 사용 사례:
1) 메타데이터 Lookup
스트리밍 이벤트에는 user_id만 있고, 유저의 이름/상태는 lookup table에 있을 때
2) Dimension 테이블 조회
Fact(Event) + Dimension(join)
3) 실시간 enrichment
incoming stream에 추가 정보 enrich
이처럼 stream-static join은 실시간 조인 기반 데이터 풍부화(enrichment)에서 핵심 역할을 합니다.
✔ Stream-Static Join – 허용되는 조인 유형
Spark Structured Streaming에서는 다음의 join 타입만 허용됩니다:
| 조인 유형 | 허용 여부 | 설명 |
| inner join | ✔ 허용 | 가장 일반적인 stream-static join |
| left outer join | ✔ 허용 | streamDF 왼쪽, staticDF 오른쪽일 때 사용 |
| left semi join | ✔ 허용 | streaming 쪽 key 존재 여부 판단 |
| left anti join | ✔ 허용 | streaming에서 static key가 없는 행만 선택 |
여기서 패턴을 보면:
✔ 스트리밍 DataFrame은 항상 Left Side이어야 한다.
즉, 다음 형태만 가능:
streamingDF.join(staticDF, ...)
또는
streamingDF.join(staticDF, ..., "left")
❌ Stream-Static Join – 허용되지 않는 조인 유형
Spark는 다음 조인 유형은 stream-static에서 허용하지 않습니다:
| 조인 유형 | 허용 여부 | 이유 |
| full outer join | ❌ 불가 | 양쪽이 동기화되기 위해 infinite input과 finite input 결합 불가능 |
| right outer join | ❌ 불가 | static이 left side에 올 수 없음 |
| staticDF.join(streamingDF) | ❌ 불가 | stream은 반드시 left DF |
즉, 아래와 같은 코드들은 모두 오류를 발생시킴:
# full outer join → 불가능
streamingDF.join(staticDF, "id", "outer")
# right join → 불가능
streamingDF.join(staticDF, "id", "right")
# staticDF를 왼쪽에 두는 join → 불가능
staticDF.join(streamingDF, "id")
✔ 왜 이런 제한이 있을까?
Structured Streaming의 핵심 개념 때문입니다:
- streamingDF는 끝없이 증가
- staticDF는 유한
- staticDF에 새로운 값이 “추가되지 않음”
✔ 1) FULL OUTER JOIN이 불가능한 이유
FULL OUTER JOIN은 다음을 보장해야 함:
- 왼쪽 또는 오른쪽에서 조인되지 않은 값도 출력
하지만 streaming은 무한 데이터이므로 “조인되지 않은 값”을 완전히 판별할 수 없음.
(언제 새로운 스트림 레코드가 들어올지 모르기 때문)
→ 그래서 FULL OUTER JOIN은 stream-static 조인에서 금지됨.
✔ 2) RIGHT OUTER JOIN이 불가능한 이유
Streaming DF는 반드시 left side여야 한다.
즉, 다음 조건을 강제:
(streamingDF LEFT JOIN staticDF)
staticDF를 왼쪽에 두는 right join은 구조적으로 스트리밍 엔진 모델과 맞지 않음.
✔ 요약 정리
✔ 허용되는 stream-static join
- inner join
- left outer join
- left semi
- left anti
❌ 허용되지 않는 join
- full outer join
- right outer join
- static.join(streaming)
✔ 마무리
Stream-static join은 실시간 데이터 파이프라인에서 필수적인 기능이지만, Spark Structured Streaming의 특성 때문에 허용되는 조인과 허용되지 않는 조인이 존재합니다.
핵심은:
스트림은 항상 “왼쪽(left)”에 있어야 하고
full/right join은 사용할 수 없다.
#Spark #Databricks #DeltaLake #스트리밍조인 #StreamStaticJoin #StructuredStreaming #실시간데이터 #데이터엔지니어링 #빅데이터 #데이터파이프라인 #SparkStreaming
'빅데이터 > Spark' 카테고리의 다른 글
| [Deep Dive] Spark Internals: spark-submit부터 Task 실행까지의 여정 (1) | 2026.01.08 |
|---|---|
| Spark Structured Streaming에서 체크포인트가 중요한 이유와 Auto Loader에서 필수인 이유 (0) | 2025.11.16 |
| 왜 모두가 Spark를 쓰는가? 분산 데이터 처리의 정석 (7) | 2025.07.30 |