Skip to main content

왜 실시간 처리가 필요한가요?

비즈니스 환경이 점점 빨라지면서, “어제의 데이터”가 아닌 “지금의 데이터”로 의사결정해야 하는 상황이 많아졌습니다.
사례필요한 응답 시간설명
신용카드 사기 감지밀리초결제 승인 전에 사기 여부를 판단해야 합니다
실시간 추천사용자의 최근 행동에 기반한 상품 추천입니다
IoT 설비 모니터링온도, 진동 이상 시 즉시 알림을 보내야 합니다
실시간 대시보드현재 매출, 트래픽을 실시간으로 표시합니다
로그 모니터링초~분서버 에러 급증 시 즉시 대응해야 합니다

실시간 처리의 핵심 구성 요소

실시간 데이터 처리 시스템은 일반적으로 세 가지 구성 요소로 이루어집니다.
구성 요소역할예시
Producer (데이터 생산자)이벤트를 발행합니다앱, 센서, 서버
Message Queue (메시지 큐)이벤트를 전달합니다Kafka, Kinesis
Consumer (데이터 소비자)이벤트를 처리합니다Spark, Flink
Storage (저장소)처리 결과를 저장합니다Delta Lake
구성 요소역할비유
Producer (생산자)이벤트/데이터를 생성하여 발행합니다편지를 보내는 사람
Message Queue (메시지 큐)이벤트를 임시 저장하고 순서대로 전달합니다우체국 (편지를 모아서 배달)
Consumer (소비자)이벤트를 받아서 처리합니다편지를 받아서 읽는 사람
Storage (저장소)처리된 결과를 영구 저장합니다파일 캐비닛

Apache Kafka

개념

💡 Apache Kafka 는 LinkedIn에서 개발한 분산 이벤트 스트리밍 플랫폼 입니다. 초당 수백만 건의 이벤트를 안정적으로 수집하고, 여러 소비자에게 전달할 수 있습니다. 현재 전 세계 Fortune 500 기업의 80% 이상이 사용하고 있습니다.

핵심 개념

Apache Kafka 구조
구성 요소역할설명
Topic: “orders”메시지 채널주문 관련 이벤트를 저장합니다
Partition 0병렬 처리 단위msg1, msg4, msg7…
Partition 1병렬 처리 단위msg2, msg5, msg8…
Partition 2병렬 처리 단위msg3, msg6, msg9…
Producer데이터 생산자주문 서비스, 모바일 앱 등이 Topic에 메시지를 전송합니다
Consumer Group데이터 소비자각 Partition을 분담하여 병렬로 메시지를 처리합니다
개념설명
Topic (토픽)이벤트가 발행되는 카테고리입니다. “orders”, “clicks”, “logs” 같은 이름을 가집니다
Partition (파티션)토픽을 물리적으로 나눈 단위입니다. 파티션이 여러 개이면 병렬로 처리할 수 있습니다
Producer (프로듀서)토픽에 이벤트를 발행하는 애플리케이션입니다
Consumer (컨슈머)토픽에서 이벤트를 읽어가는 애플리케이션입니다
Consumer Group같은 토픽을 읽는 컨슈머들의 그룹입니다. 파티션이 그룹 내 컨슈머에게 분배됩니다
Offset각 파티션에서 컨슈머가 어디까지 읽었는지를 나타내는 위치 정보입니다
BrokerKafka 서버 인스턴스입니다. 여러 Broker가 클러스터를 구성합니다

Kafka의 특징

특징설명
높은 처리량초당 수백만 건의 이벤트를 처리할 수 있습니다
내구성이벤트를 디스크에 저장하므로, 컨슈머가 느려도 데이터가 유실되지 않습니다
재처리 가능Offset을 되돌려서 과거 이벤트를 다시 읽을 수 있습니다
다중 소비하나의 이벤트를 여러 Consumer Group이 독립적으로 읽을 수 있습니다

관련 솔루션

솔루션설명
Confluent CloudKafka의 관리형 클라우드 서비스입니다
Amazon MSKAWS에서 관리형 Kafka를 제공합니다
Azure Event HubsKafka API와 호환되는 Azure의 스트리밍 서비스입니다
Amazon KinesisAWS의 자체 실시간 스트리밍 서비스입니다

스트림 처리 엔진

메시지 큐에서 이벤트를 받아 실시간으로 처리하는 엔진들을 살펴보겠습니다.

Apache Spark Structured Streaming

💡 Spark Structured Streaming 은 Apache Spark의 스트리밍 모듈로, 마이크로 배치(Micro-Batch) 방식으로 스트리밍 데이터를 처리합니다. 배치 코드와 동일한 DataFrame API를 사용할 수 있어서, 배치→스트리밍 전환이 매우 쉽습니다.
# Kafka에서 주문 이벤트를 실시간으로 읽어서 Delta 테이블에 저장
df = (spark.readStream
    .format("kafka")
    .option("kafka.bootstrap.servers", "broker:9092")
    .option("subscribe", "orders")
    .load()
)

# JSON 파싱 및 변환
from pyspark.sql.functions import from_json, col
schema = "order_id LONG, customer_id LONG, amount DOUBLE, ts TIMESTAMP"

orders = (df
    .select(from_json(col("value").cast("string"), schema).alias("data"))
    .select("data.*")
)

# Delta Lake에 스트리밍으로 저장
(orders.writeStream
    .format("delta")
    .outputMode("append")
    .option("checkpointLocation", "/checkpoints/orders")
    .toTable("catalog.schema.streaming_orders")
)
💡 Apache Flink 는 진정한 이벤트 단위(Event-at-a-time) 스트리밍 처리 엔진입니다. 이벤트가 도착하는 즉시 하나씩 처리하므로, Spark의 마이크로 배치보다 더 낮은 지연 시간(밀리초 수준)을 달성할 수 있습니다.
비교 항목Spark Structured StreamingApache Flink
처리 모델마이크로 배치 (기본)이벤트 단위 (True Streaming)
지연 시간수백 밀리초 ~ 초밀리초 ~ 수십 밀리초
배치/스트리밍 통합동일 API (DataFrame)별도 API (DataStream vs Table)
상태 관리체크포인트 기반Savepoint + 체크포인트
생태계Spark 생태계 (MLlib, SQL 등)독자 생태계
Databricks 지원✅ 네이티브 지원❌ 별도 운영 필요
💡 체크포인트(Checkpoint)란? 스트리밍 처리의 현재 진행 상태(어디까지 읽었고, 어떤 집계 값을 가지고 있는지)를 주기적으로 저장하는 것입니다. 장애가 발생하면 마지막 체크포인트부터 재시작하여 데이터 유실 없이 처리를 이어갈 수 있습니다.

이벤트 드리븐 아키텍처 (EDA)

개념

💡 이벤트 드리븐 아키텍처(Event-Driven Architecture, EDA) 란 시스템의 구성 요소들이 이벤트 를 중심으로 통신하는 아키텍처 패턴입니다. A 서비스에서 발생한 이벤트를 Kafka 같은 메시지 큐에 발행하면, 관심 있는 다른 서비스들이 이를 구독하여 처리합니다.
이벤트 드리븐 아키텍처 (마이크로서비스)
서비스역할Kafka 연동
주문 서비스주문 생성 이벤트 발행Producer
Kafka (이벤트 버스)이벤트를 중앙에서 관리메시지 브로커
결제 서비스주문 이벤트 구독 → 결제 처리Consumer
재고 서비스주문 이벤트 구독 → 재고 차감Consumer
알림 서비스주문 이벤트 구독 → 알림 발송Consumer
분석 서비스주문 이벤트 구독 → 데이터 분석Consumer

EDA의 장점

장점설명
느슨한 결합서비스 간 직접 호출 없이 이벤트로 통신하므로, 서비스를 독립적으로 변경할 수 있습니다
확장성이벤트를 처리하는 서비스(Consumer)를 쉽게 추가할 수 있습니다
실시간 반응이벤트 발생 즉시 관련 서비스가 반응합니다
이력 보존Kafka에 이벤트가 보존되므로, 나중에 새로운 서비스가 과거 이벤트를 재처리할 수 있습니다

Databricks에서의 실시간 처리

Databricks는 Spark Structured Streaming 을 기반으로 실시간 처리를 지원하며, 이를 Medallion 아키텍처와 결합하여 사용합니다.
계층구성 요소역할
소스Kafka / Kinesis스트리밍 데이터를 수집합니다
BronzeStreaming Table원본 데이터를 수집합니다
SilverStreaming Table실시간 변환을 수행합니다
GoldMaterialized View집계 결과를 제공합니다
출력실시간 대시보드Gold 데이터를 시각화합니다
Databricks 기능역할
Auto Loader클라우드 스토리지의 새 파일을 실시간으로 감지하여 수집합니다
Structured StreamingKafka, Kinesis 등에서 이벤트를 실시간으로 읽고 처리합니다
Streaming Tables (SDP)선언적으로 스트리밍 파이프라인을 정의합니다
Materialized Views (SDP)스트리밍 데이터를 실시간으로 집계합니다
Delta Lake스트리밍으로 적재된 데이터에 ACID 트랜잭션을 보장합니다

Kafka를 직접 운영해본 경험 — ZooKeeper의 고통

Kafka를 Confluent Cloud나 Amazon MSK 같은 관리형 서비스로 사용하면 편리하지만, 직접 운영한다면 이야기가 완전히 달라집니다.

ZooKeeper 관리의 고통

Kafka는 오랫동안 ZooKeeper 라는 분산 코디네이션 서비스에 의존해왔습니다. ZooKeeper가 죽으면 Kafka도 죽습니다.
문제현실
ZooKeeper 클러스터 유지최소 3대(홀수)를 운영해야 합니다. 하나가 죽으면 즉시 복구해야 합니다
세션 타임아웃ZooKeeper와 Kafka Broker 간 세션이 끊기면, Broker가 클러스터에서 제외됩니다. 네트워크 순간 장애에도 민감합니다
디스크 공간ZooKeeper의 트랜잭션 로그가 디스크를 가득 채우면 전체 Kafka 클러스터가 멈춥니다. 새벽 3시에 호출받는 대표적인 원인입니다
버전 업그레이드Kafka와 ZooKeeper 버전 호환성을 맞춰야 합니다. Rolling Upgrade 절차를 잘못하면 서비스 중단이 발생합니다
🆕 KRaft 모드 (2024~): Kafka 3.3 이후부터 ZooKeeper 없이도 동작하는 KRaft(Kafka Raft) 모드가 도입되었습니다. Kafka 4.0부터는 ZooKeeper가 완전히 제거될 예정입니다. 새로 구축하는 경우 KRaft를 사용하시는 것을 권장합니다.

파티션 리밸런싱의 악몽

Kafka Broker를 추가하거나 제거할 때, 파티션을 재분배해야 합니다. 이 과정에서 대량의 데이터가 네트워크를 통해 복사되며, 클러스터 전체의 성능이 저하됩니다.
상황영향
Broker 1대 추가기존 파티션의 일부를 새 Broker로 이동. 데이터 크기에 따라 수 시간~수일 소요
Broker 1대 장애해당 Broker의 파티션 리더십이 다른 Broker로 넘어감. ISR(In-Sync Replica)이 부족하면 데이터 유실 가능
토픽 파티션 증가한 번 늘린 파티션은 줄일 수 없습니다. 초기 설계가 매우 중요합니다
💡 현업에서는 이렇게 합니다: 파티션 수는 “현재 필요한 수의 23배”로 넉넉하게 설정합니다. 나중에 늘리는 것은 가능하지만, 줄이는 것은 토픽을 재생성해야 하므로 매우 번거롭습니다. 일반적으로 토픽당 파티션 612개로 시작하고, Consumer 수에 맞춰 조정합니다.

Kafka 비용의 현실

방식월 비용 (대략)운영 부담
자체 운영 (EC2)500 500~2,000+ (3 Broker + 3 ZooKeeper)높음 — 모니터링, 패치, 장애 대응 필요
Amazon MSK1,000 1,000~3,000+중간 — 브로커 관리는 AWS가 담당
Confluent Cloud500 500~5,000+ (사용량 기반)낮음 — 완전 관리형
💡 이것을 안 하면…: Kafka 모니터링을 설정하지 않으면, Consumer Lag(소비 지연)이 쌓이고 있는지 알 수 없습니다. 어느 날 갑자기 “실시간 대시보드가 3시간 전 데이터를 보여주고 있다”는 보고를 받게 됩니다. 최소한 Consumer Lag, Broker Disk Usage, ISR Shrink 이 세 가지는 반드시 모니터링하세요.

”실시간이 필요하다고 생각했는데, 마이크로배치로 충분했던 경우”

현업에서 “실시간 처리가 필요합니다”라는 요구사항을 받으면, 먼저 정말 실시간이 필요한지 를 따져봐야 합니다.

진짜 실시간(밀리초) vs 니어 실시간(초분) vs 마이크로배치(분시간)

요구사항실제 필요한 수준권장 솔루션
”신용카드 사기 감지”진짜 실시간(밀리초)Flink, 또는 별도의 실시간 서빙 레이어
”실시간 대시보드”니어 실시간(1~5분 지연 허용)Spark Structured Streaming (마이크로배치)
“주문 현황 모니터링”니어 실시간(5~15분 지연 허용)Spark Structured Streaming 또는 Auto Loader
”일별 리포트를 오전 9시에”배치(시간 단위)스케줄된 배치 잡
”데이터가 들어오면 바로 분석”대부분 마이크로배치 로 충분Auto Loader + SDP
💡 현업에서는 이렇게 합니다: 고객이 “실시간”이라고 말할 때, 실제로 의미하는 것은 대부분 “1시간 전 데이터가 아니라 5분 전 데이터를 보고 싶다”입니다. 이 정도의 요구사항은 Spark Structured Streaming의 마이크로배치(수 초~수 분 간격)로 충분히 충족됩니다. 진짜 밀리초 수준의 실시간이 필요한 경우는 전체 워크로드의 5% 미만입니다.

Databricks Structured Streaming과의 연결

Databricks에서 실시간 처리를 구현하는 가장 일반적인 패턴은 다음과 같습니다.
Kafka → Spark Structured Streaming → Delta Lake (Bronze → Silver → Gold)

                              SQL Warehouse → AI/BI Dashboard
# Databricks에서 Kafka → Delta Lake 실시간 파이프라인 (간단 버전)
(spark.readStream
    .format("kafka")
    .option("kafka.bootstrap.servers", "broker:9092")
    .option("subscribe", "orders")
    .option("startingOffsets", "latest")
    .load()
    .selectExpr("CAST(value AS STRING) as json_str")
    .writeStream
    .format("delta")
    .option("checkpointLocation", "/checkpoints/orders_bronze")
    .outputMode("append")
    .toTable("catalog.schema.orders_bronze")
)
SDP(Spark Declarative Pipelines)를 사용하면 더 간단해집니다:
-- SDP에서는 SQL만으로 스트리밍 테이블을 정의할 수 있습니다
CREATE STREAMING TABLE orders_bronze
AS SELECT * FROM STREAM read_kafka(
    bootstrapServers => 'broker:9092',
    subscribe => 'orders'
);

CREATE STREAMING TABLE orders_silver
AS SELECT
    from_json(value, 'order_id LONG, customer_id LONG, amount DOUBLE') AS parsed
FROM STREAM orders_bronze;
💡 현업에서의 판단 기준: “마이크로배치로 충분한 워크로드에 Flink를 도입하면, 시스템 복잡성만 증가하고 ROI가 나오지 않습니다.” Databricks를 이미 사용 중이라면, Structured Streaming부터 시작하고, 정말 밀리초 수준의 지연이 필요한 워크로드만 Flink로 분리하는 것이 현실적입니다.

실시간 처리 아키텍처 패턴

Lambda 아키텍처

💡 Lambda 아키텍처배치 레이어스피드 레이어(실시간)를 분리하여, 각각의 장점을 활용하는 아키텍처입니다. 배치는 정확성을, 스피드는 속도를 담당합니다.
단점: 같은 로직을 배치용과 스트리밍용으로 두 번 구현해야 하는 유지보수 부담이 있습니다.

Kappa 아키텍처

💡 Kappa 아키텍처 는 모든 데이터를 스트리밍으로만 처리 하는 아키텍처입니다. 배치 처리가 필요하면, 과거 이벤트를 Kafka에서 다시 읽어서(재처리) 스트리밍 파이프라인으로 처리합니다.

Delta 아키텍처 (Databricks 권장)

Databricks는 Delta Lake의 배치/스트리밍 통합 능력 을 활용하여, 하나의 코드로 배치와 스트리밍을 모두 처리하는 방식을 권장합니다. Lambda나 Kappa의 장점을 모두 취하면서 복잡성을 줄입니다.

아키텍처 선택 가이드

아키텍처적합한 경우주의사항
Lambda레거시 시스템이 이미 배치로 구축되어 있고, 일부만 실시간이 필요한 경우동일 로직을 두 번 구현하는 유지보수 부담이 큽니다
Kappa모든 데이터가 이벤트 형태이고, Kafka에 충분한 보존 기간이 설정된 경우대규모 재처리 시 Kafka에서 읽는 비용이 큽니다
DeltaDatabricks를 사용하는 경우 (가장 권장)하나의 Delta 테이블에 배치/스트리밍 모두 쓸 수 있어 가장 단순합니다
💡 현업에서는 이렇게 합니다: “어떤 아키텍처를 선택할지” 고민하기보다, “Databricks + Delta Lake를 쓴다면 Delta 아키텍처가 자동으로 따라온다”고 생각하시면 됩니다. Structured Streaming으로 실시간 데이터를 Delta에 쓰고, 같은 테이블을 배치 잡으로도 읽고 쓸 수 있으므로, 별도의 아키텍처 설계가 크게 필요하지 않습니다.

실시간 처리 도입 시 체크리스트

실시간 처리를 도입하기 전에 아래 항목들을 점검하세요.
항목질문설명
비즈니스 요구정말 실시간이 필요한가?“5분 지연 허용”이면 마이크로배치로 충분합니다
데이터 소스소스가 이벤트를 발행할 수 있는가?CDC, API Webhook, Kafka 연동 가능 여부를 확인합니다
데이터 양초당 이벤트 수는?초당 1,000건 이하면 가벼운 솔루션으로 충분합니다
Late data늦게 도착하는 데이터를 어떻게 처리할 것인가?Watermark 설정이 필수입니다
정확성Exactly-once가 필요한가?결제, 주문 등은 중복 처리가 허용되지 않습니다
모니터링Consumer Lag, 처리 지연을 어떻게 모니터링할 것인가?알림 체계가 없으면 장애를 감지할 수 없습니다
비용24/7 실행 비용을 감당할 수 있는가?스트리밍 클러스터는 항상 실행되므로 비용이 지속적입니다
💡 현업에서는 이렇게 합니다: 실시간 처리를 처음 도입할 때는, 전체 파이프라인을 한 번에 실시간으로 전환하지 마세요. 가장 비즈니스 임팩트가 큰 하나의 파이프라인을 먼저 실시간으로 전환하고, 안정화된 후에 점진적으로 확대하는 것이 현실적입니다.

정리

핵심 개념설명
Apache Kafka분산 이벤트 스트리밍 플랫폼. 이벤트를 안정적으로 수집하고 전달합니다
Structured StreamingSpark의 스트리밍 엔진. 마이크로 배치 방식으로 동작합니다
Apache Flink이벤트 단위 스트리밍 엔진. 밀리초 수준의 낮은 지연 시간을 제공합니다
EDA이벤트를 중심으로 서비스가 통신하는 아키텍처 패턴입니다
CDC데이터베이스 변경 사항을 실시간으로 감지하여 전달하는 기술입니다
체크포인트스트리밍 처리 상태를 저장하여 장애 시 복구를 보장합니다
마이크로배치대부분의 “실시간” 요구사항에 충분한, 수 초~수 분 간격의 처리 방식입니다
이것으로 선행 지식 섹션을 마치겠습니다. 이제 01. 데이터 기초로 진행하시면, Databricks 중심의 본격적인 학습을 시작하실 수 있습니다.

참고 링크