빅데이터/Spark

Spark Structured Streaming: Stream-Static Join 완벽 정리 (허용되는 조인 vs 허용되지 않는 조인)

네야_IT 2025. 11. 18. 20:00
반응형

Spark Structured Streaming을 활용하여 실시간 데이터 파이프라인을 만들다 보면 종종 스트리밍 데이터(streaming DataFrame)정적 테이블(static DataFrame) 을 결합해야 하는 상황이 발생합니다.

예를 들어:

  • 실시간 이벤트(streamingDF)에 사용자 정보(static user lookup)를 매칭
  • IoT 센서 이벤트에 센서 메타데이터 조인
  • 로그 데이터에 저장된 reference table을 매핑

이처럼 stream-static join은 실제 데이터 엔지니어링에서 굉장히 흔합니다. 하지만 Structured Streaming에서는 모든 조인이 허용되는 것이 아닙니다. 일부 조인은 기술적으로 불가능하거나, Spark 엔진의 일관성을 위해 금지되어 있습니다.

이번 글에서는:

  1. Stream-Static Join이 무엇인지
  2. 어떤 조인이 가능하고
  3. 어떤 조인이 불가능한지
  4. 왜 그런 제한이 존재하는지

를 명확하고 쉽게 정리해보겠습니다.

 

 

✔ 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

반응형