← 학습 카테고리

Learn

Kafka

42개 모듈 · 현재 37번째

Kafka 모듈 37/42 kafka-learn-37

Kafka Streams와 확장 생태계 — KStream/KTable, 윈도우, Connect, ksqlDB

90+ Kafka Interview Questions and Answers (blog) kafka_ref_01(Q68-80), kafk_ref_03(Section 8 Kafka Streams vs Spark Streaming), kafka_ref_04(KTable, 스트림 조인, ksqlDB 관련 문항), kafka_ref_05(Q8,Q13) 종합.

이 모듈을 다 읽으면

  • KStream과 KTable의 개념적 차이와 각각이 적합한 사용 사례를 구분할 수 있다
  • Kafka Streams의 네 가지 윈도우 연산 방식을 구분해 설명할 수 있다
  • Kafka Streams가 별도 클러스터 없이 exactly-once를 어떻게 달성하는지 설명할 수 있다
  • Kafka Connect, ksqlDB, MirrorMaker가 Kafka 생태계에서 각각 어떤 역할을 하는지 구분할 수 있다

Kafka Streams의 핵심 추상화(KStream/KTable, 상태 저장소, 윈도우 연산)와, 이를 둘러싼 Kafka Connect·ksqlDB·MirrorMaker 같은 확장 생태계 컴포넌트들의 역할을 정리한다.

Kafka Streams — 별도 클러스터 없는 스트림 처리 라이브러리

Kafka Streams는 표준 Java(또는 Scala) 애플리케이션 안에 임베드되는 클라이언트 라이브러리로, Spark Streaming이나 Flink처럼 별도의 처리 클러스터를 두지 않고 Kafka 클라이언트만으로 스트림 처리를 수행한다. 이 점이 운영 복잡도를 크게 낮추는 대신, 클러스터 단위의 자원 스케줄링이나 이기종 소스/싱크 통합 같은 범용 분산 처리 엔진의 유연성은 상대적으로 제한적이다.

고수준 DSL(필터, 맵, 조인, 집계, 윈도우)을 제공해 처리 로직을 선언적으로 표현할 수 있고, 저수준 Processor API를 쓰면 토폴로지를 더 세밀하게 제어할 수 있다. Kafka Streams는 상태가 없는(stateless) 연산(필터링, 매핑)과 상태가 있는(stateful) 연산(집계, 조인, 윈도우) 모두를 지원하며, 상태는 기본적으로 로컬 RocksDB(또는 인메모리 저장소)에 유지되고 동시에 체인지로그 토픽에 백업되어, 애플리케이션 인스턴스가 죽고 다른 곳에서 재시작되어도 상태를 복원할 수 있다.

핵심 포인트

  • Kafka Streams는 별도 클러스터 없이 애플리케이션 안에 임베드되는 클라이언트 라이브러리다
  • DSL은 필터/맵/조인/집계/윈도우를 선언적으로 표현하는 고수준 API다
  • 상태는 로컬 RocksDB에 유지되면서 체인지로그 토픽으로 백업되어 장애 시 복원 가능하다

KStream과 KTable — 이벤트 로그와 최신 상태 뷰

KStream은 경계가 없는(unbounded) 연속 레코드 스트림으로, 모든 레코드가 독립적인 새 이벤트로 취급된다(예: "주문 생성" 이벤트 하나하나). KTable은 체인지로그 형태의 테이블 뷰로, 같은 키에 대한 새 레코드가 이전 값을 덮어쓰는 방식으로 동작한다(개념적으로 로그 컴팩션과 유사) — 예를 들어 "현재 계좌 잔액"처럼 특정 키의 "지금 상태"를 표현하는 데 적합하다.

실무에서 자주 쓰이는 패턴은 원시 이벤트는 KStream으로 흘려보내고, 그 이벤트들을 집계한 파생 상태는 KTable로 유지하는 것이다("거래 발생" 이벤트 스트림으로부터 "계좌 잔액" 테이블을 만드는 식). KStream과 KTable, 또는 KTable끼리도 조인이 가능하며, 조인 시에는 데이터가 적절히 키잉되어 있어야 하고(같은 키가 같은 파티션에 있어야 함), KStream-KStream 조인처럼 두 스트림 사이의 조인에는 시간 윈도우가 필요하다.

핵심 포인트

  • KStream은 독립적인 이벤트들의 연속 스트림, KTable은 키별 최신 값을 유지하는 체인지로그 뷰다
  • 원시 이벤트는 KStream으로, 파생된 집계 상태는 KTable로 표현하는 패턴이 일반적이다
  • 조인이 성립하려면 데이터가 같은 키로 같은 파티션에 정렬되어 있어야 한다

네 가지 윈도우 연산과 exactly-once

시간 범위로 이벤트를 묶어 집계·조인해야 할 때 Kafka Streams는 네 가지 윈도우 타입을 제공한다. 텀블링(tumbling) 윈도우는 고정 크기이고 겹치지 않아 각 이벤트가 정확히 하나의 윈도우에만 속한다(예: 매 시간 정각 기준 집계). 호핑(hopping) 윈도우는 고정 크기이지만 윈도우 크기보다 짧은 간격으로 슬라이딩하며 겹치므로 한 이벤트가 여러 윈도우에 속할 수 있다(예: 1분 윈도우를 10초마다 갱신하는 이동 평균). 슬라이딩(sliding) 윈도우는 고정된 시계 격자가 아니라 각 이벤트를 기준으로 동적으로 형성되며, 주로 조인 연산에 쓰인다. 세션(session) 윈도우는 크기가 고정되어 있지 않고, 설정된 비활성 간격(inactivity gap)으로 구분되는 활동 구간에 따라 동적으로 형성된다(예: 사용자의 클릭들을 하나의 "세션"으로 묶기).

exactly-once semantics는 Kafka Streams에서도 Kafka의 트랜잭션 API를 그대로 이용해 달성된다 — 즉 입력 오프셋 커밋과 출력 쓰기(그리고 상태 저장소 변경분의 체인지로그 반영)를 하나의 트랜잭션으로 묶어, 애플리케이션 인스턴스가 중간에 죽었다 재시작해도 각 입력 레코드가 결과에 정확히 한 번만 반영되게 한다.

핵심 포인트

  • 텀블링은 겹치지 않는 고정 윈도우, 호핑은 겹치는 고정 윈도우, 슬라이딩은 이벤트 기준 동적 윈도우, 세션은 비활성 간격 기준 동적 윈도우다
  • Kafka Streams의 exactly-once는 Kafka 트랜잭션 API를 그대로 활용해 입력 오프셋/출력 쓰기/상태 변경을 하나의 트랜잭션으로 묶는 방식이다

Kafka Connect, ksqlDB, MirrorMaker — 생태계 컴포넌트의 역할 구분

Kafka Connect는 커스텀 프로듀서/컨슈머 코드를 작성하지 않고도 Kafka와 외부 시스템(데이터베이스, 검색엔진, 파일시스템, 클라우드 스토리지 등) 사이에서 데이터를 스트리밍하기 위한 프레임워크다. 소스 커넥터는 외부 시스템에서 Kafka 토픽으로 데이터를 끌어오고(예: JDBC 소스 커넥터로 RDB 변경분을 스트리밍), 싱크 커넥터는 Kafka 토픽의 데이터를 외부 시스템으로 내보낸다(예: S3나 Elasticsearch 싱크). 커넥터는 standalone 모드(단일 워커, 로컬/단순 환경)나 distributed 모드(다수 워커, 프로덕션의 장애 허용·확장 가능 실행)로 돌릴 수 있다.

ksqlDB는 Kafka Streams 위에 얹힌 SQL 기반 스트림 처리 엔진으로, Java/Scala 코드를 작성하는 대신 SQL과 유사한 쿼리로 필터링·집계·조인·윈도우를 표현할 수 있으며, 임베디드 라이브러리가 아니라 독립 서버로 동작한다는 점이 Kafka Streams와의 실질적 차이다. MirrorMaker(2.0 기준 Kafka Connect 기반으로 재작성됨)는 한 Kafka 클러스터의 데이터를 다른 클러스터로 복제하는 도구로, 재해 복구, 여러 리전 데이터를 중앙 클러스터로 집계, 클러스터 마이그레이션 등에 쓰인다 — 다만 Kafka 자체에는 별도의 네이티브 백업 기능이 없으므로, 장기 보관이나 백업 목적으로는 MirrorMaker나 서드파티 도구로 HDFS/S3 등 외부 저장소에 내보내는 방식이 흔히 쓰인다.

핵심 포인트

  • Kafka Connect는 소스/싱크 커넥터로 커스텀 코드 없이 Kafka와 외부 시스템을 연결하는 프레임워크다
  • ksqlDB는 Kafka Streams 위에 얹힌 SQL 기반 스트림 처리 엔진으로 독립 서버로 동작한다
  • MirrorMaker는 클러스터 간 데이터 복제 도구로 재해 복구와 마이그레이션에 쓰인다
  • Kafka 자체에는 네이티브 백업 기능이 없어 백업은 MirrorMaker나 외부 저장소 내보내기로 별도 구현해야 한다