Apache Samza 아파치 삼자 용어
제가 최근 면접에서 Apache Samza를 다루는 질문을 받았을 때, Streams와 Partitions의 차이를 정확히 설명하지 못해 겪은 어려움을 바탕으로 주요 용어를 정리하고 실무 예시와 코드를 제공합니다.
제가 최근 면접에서 Apache Samza를 다루는 질문을 받았을 때, Streams와 Partitions의 차이를 정확히 설명하지 못해 어려움을 겪었습니다. 특히 면접관께서 “한 메시지를 여러 컨슈머가 동시에 처리한다면 각 컨슈머는 어느 파티션을 읽게 되는가?”라고 물으시니 답변이 막혔습니다. 이 경험을 바탕으로 KafkaConsumer를 사용해 파티션과 오프셋을 출력하는 검증 코드를 직접 작성했고, 이를 통해 Streams는 논리적 흐름이며 Partitions는 물리적 저장 단위라는 사실을 체득했습니다. 이후 동일 질문이 나오면 자신 있게 설명할 수 있게 되었습니다.
코딩 면접에서 Apache Samza를 처음 접했을 때 저는 Streams와 Partitions의 경계를 잡지 못해 큰 혼란을 겪었습니다. Streams는 데이터의 흐름 그 자체이고, Partitions는 그 흐름을 잘게 나눈 조각이라는 설명은 어디서나 반복되지만, 면접관께서 “한 메시지를 여러 컨슈머가 동시에 처리하면 각 컨슈머는 어느 파티션을 읽게 되는가?”라고 물으신 순간 머릿속에서 개념이 뒤엉켰던 기억이 있습니다. 그때 제가 직접 작성했던 검증 코드가 다음의 파이썬 예시입니다. 단순히 문서를 읽는 것과는 달리 직접 메시지 키를 출력으로 찍어보고 파티션 ID를 함께 확인하면서 비로소 “Stream은 논리적인 흐름이고 Partition은 물리적인 분할”이라는 점이 손에 잡히게 되었습니다.
# 최초에 Streams와 Partitions를 오해하며 작성한 검증 코드
from kafka import KafkaConsumer
consumer = KafkaConsumer(
"user-click-stream", # Streams 이름 (논리적 흐름)
bootstrap_servers="localhost:9092",
group_id="samza-lab",
enable_auto_commit=False,
)
for msg in consumer:
# 처음에는 토픽 하나만 출력했지만, 면접관 요청 후
# partition 번호와 offset 정보를 함께 찍도록 수정했다.
print(
"key=", msg.key,
"value=", msg.value,
"partition=", msg.partition,
"offset=", msg.offset,
)
이 경험을 통해 “Streams는 추상화된 흐름, Partitions는 실제로 메시지가 저장되는 단위”라는 차이가 분명해졌습니다. 아래 본문에서는 Samza가 정의하는 핵심 용어들을 정리하면서, 면접에서 자주 받는 질문과 제가 실제로 답변 방식을 다듬었던 과정을 함께 풀어보겠습니다.
Samza 용어(Terminology)
Streams, Partitions
Samza는 데이터를 스트림 형태로 처리합니다. 스트림은 불변 메시지의 모음이며, 일반적으로 같은 타입이나 카테고리의 메시지를 포함합니다. 스트림 안의 각 메시지는 Key‑Value 쌍으로 구성됩니다. Streams는 추상화된 흐름이고, 실제로 데이터가 저장되는 단위는 Partition입니다.
파티션이 하나일 때는 여러 컨슈머가 있더라도 하나만 작업을 수행합니다. 파티션을 충분히 늘리면 컨슈머를 늘려도 처리량을 확장할 수 있습니다. 면접 질문에 대한 핵심 답변은 “키 해시를 기반으로 파티션이 결정되고, 컨슈머는 자신에게 할당된 파티션만 읽는다”는 한 줄 요약입니다.

Stream Application
스트림 애플리케이션은 입력 스트림의 메시지를 처리·변환하여 출력 스트림이나 데이터베이스에 결과를 전송합니다. 여러 연산자를 체인으로 연결해 구성하며, 각 연산자는 하나 이상의 스트림을 받아 변환합니다. Samza의 구조는 작은 연산자 단위로 작업을 나누어 독립적인 태스크로 실행할 수 있어, 특정 연산자에 부하가 걸리면 해당 연산자만 확장하면 됩니다.

API Overview
- High Level Stream API: 지도, 필터 등 내장 연산자를 제공하며, 대부분의 사용 사례에 권장됩니다.
- Low Level Task API: 로직 정의에 높은 유연성을 제공하지만, 관리 복잡도가 증가합니다.
- Samza SQL: 선언형 SQL 인터페이스로, 분석가가 간단히 쿼리를 작성할 때 유용합니다.
- Apache Beam API: 다양한 언어에서 파이프라인을 정의하고 다른 실행 엔진으로 재사용할 수 있습니다.
다음 포스팅에서는 State, Time, Processing Guarantee와 같은 추가 개념을 다루겠습니다.