[Kafka] Apache Kafka 개요 및 구성요소
카프카는 고성능 분산 이벤트 스트리밍 플랫폼으로, 지연 시간이 짧고 처리량이 높아서 대량의 데이터를 실시간으로 처리하고 전송하기 위해 사용됩니다. 단순히 메시지를 전달하는 시스템을 넘어, 대규모 데이터 스트림을 안정적으로 처리하고 여러 시스템 간의 결합도를 낮추는 핵심 인프라로 자리 잡고 있습니다. 기존의 Message Queue는 주로 단일 애플리케이션과 백엔드 시스템 간의 비동기 통신을 지원하는 데 초점을 맞추어왔습니다. 반면 카프카는 단순 메시징을 넘어 로그 저장소, 이벤트 스트리밍 플랫폼, 데이터 파이프라인 허브의 역할까지 수행할 수 있다는 점에서 큰 차이가 있습니다.
탄생 배경
기존의 Source 시스템에서 Target 시스템으로 직접 데이터를 전송하는 경우에 시스템이 커질수록 데이터 전송 파이프라인이 복잡해질 수 있습니다. 이는 장애 발생 시 대응을 힘들게 하고 시스템 간 높은 결합도로 Target 시스템에 문제 발생 시 Source 시스템에도 영향을 줍니다.

그래서 링크드인은 사내에서 발생하는 모든 이벤트/데이터의 흐름을 중앙에서 관리하는 카프카를 개발했습니다. 이로서 서비스 아키텍처를 깔끔하게 관리할 수 있고 시스템 간 결합도를 낮출 수 있었습니다.

Broker
브로커(Broker)는 카프카가 설치된 서버 단위를 의미하며, 안정성을 위해 보통 3개 이상의 브로커로 클러스터를 구성하는 것이 권장됩니다. 각 브로커는 특정 파티션의 리더(Leader) 역할을 맡거나 다른 브로커의 파티션 데이터를 팔로워(Follower) 형태로 복제합니다. 이를 통해 장애가 발생했을 때도 고가용성을 유지할 수 있습니다.
브로커는 메시지를 디스크 기반으로 저장하여 영속성을 보장하고 리더, 팔로워 파티션을 관리해서 데이터의 복제나 자동 장애 복구를 지원합니다. 또한 부하 분산을 위한 파티션의 균등한 메시지 분배나 클러스터 내 리더 선출과 관리를 담당합니다.
Topic
카프카에서 토픽(Topic)은 파일시스템의 폴더나 데이터베이스의 테이블과 유사한 개념으로, 데이터를 논리적으로 구분하는 단위입니다. 프로듀서는 특정 토픽에 이벤트를 발행하며, 하나의 토픽은 여러 개의 파티션(Partition)으로 구성됩니다. 파티션은 큐처럼 레코드를 순차적으로 저장하지만, 전통적인 메시지 큐와 달리 데이터를 즉시 삭제하지 않고 설정된 보존 정책에 따라 관리한다는 차이가 있습니다.
파티션 수를 늘리면 컨슈머를 병렬로 확장하여 데이터 처리량을 높일 수 있습니다. 하지만 파티션은 늘릴 수는 있어도 줄이는 방법은 제공하지 않기 때문에 초기 설계 단계에서 적절한 파티션 수를 신중히 결정하셔야 합니다. 또한 파티션은 메시지 키(key)를 기준으로 데이터를 할당할 수 있는데 키가 null일 경우 라운드 로빈(Round Robin) 방식으로 분배됩니다.
파티션 내부의 데이터는 최대 보존 시간(log.retention.ms)과 최대 보존 크기(log.retention.bytes) 옵션에 따라 관리되며, 이를 초과하면 오래된 데이터부터 삭제됩니다. 중요한 점은, 컨슈머가 이벤트를 읽더라도 데이터 자체는 삭제되지 않으며, 컨슈머는 각자의 오프셋(offset)을 기준으로 데이터를 관리한다는 것입니다. 덕분에 여러 컨슈머 그룹이 동일한 데이터를 독립적으로 처리할 수 있습니다.
Partitioner

파티셔너(Partitioner)는 프로듀서가 전송하는 메시지를 어떤 파티션에 저장할지를 결정하는 역할을 합니다. 기본적으로 UniformStickyPartitioner가 사용되며, 메시지에 키가 포함되어 있으면 키 값을 해시(hash)로 변환하여 파티션 번호를 계산하고, 동일 키는 항상 동일한 파티션에 할당됩니다. 이렇게 하면 파티션 내 순서가 유지되므로 같은 키를 가진 메시지의 처리 순서를 보장할 수 있습니다.
만약 메시지 키가 없다면 라운드 로빈 방식으로 균등하게 분배됩니다. 다만 효율성을 위해 개별 메시지가 아니라 일정량의 메시지를 배치(batch) 단위로 모아 파티셔너에 전달하는 특징이 있습니다. 필요하다면 애플리케이션 특성에 맞게 커스텀 파티셔너를 구현하여 특정 파티션 분배 전략을 적용할 수도 있습니다.
Producer
카프카에서 프로듀서(Producer)는 데이터를 생성하여 특정 토픽으로 전송하는 역할을 합니다. 애플리케이션에서 발생한 이벤트(예: 주문 생성, 결제 완료)를 프로듀서가 메시지로 만들어 카프카 클러스터에 발행하면, 이 메시지가 토픽의 파티션에 저장됩니다.
프로듀서는 메시지를 보낼 때 키(key)를 함께 지정할 수 있는데, 이 키를 기준으로 어느 파티션에 메시지가 들어갈지 결정됩니다. 키를 지정하지 않으면 라운드 로빈 방식으로 균등 분배됩니다. 또한, 프로듀서는 acks 옵션을 통해 전송 안정성을 조절할 수 있습니다. “안전성과 속도 중 무엇을 우선할지”에 따라서 설정값은 달라집니다.
ack = 0- 데이터를 전송하고 응답은 받지 않습니다.
- 가장 빠르지만 데이터 유실 가능성이 있습니다.
ack = 1- 리더 파티션에 데이터 전송 성공 시 응답을 받습니다.
- 리더 파티션까지는 기록을 보장하지만, 복제 전에 장애가 발생하면 유실될 수 있습니다.
ack = all- 모든 팔로워 복제까지 완료된 후 응답을 받습니다.
- 가장 안전하지만 속도는 느려집니다.
Consumer
카프카에서 컨슈머(Consumer)는 토픽에 저장된 메시지를 읽어가는 주체입니다.
컨슈머는 하나 이상의 토픽을 구독(subscribe)하여 메시지를 가져오며, 동일한 그룹 ID를 가진 컨슈머들은 컨슈머 그룹으로 묶여 토픽 내의 파티션을 분담해서 처리합니다. 이때 컨슈머와 파티션의 관계는 1:n 입니다.
컨슈머가 메시지를 읽더라도 토픽에 저장된 원본 데이터는 삭제되지 않고, 컨슈머마다 오프셋(offset)을 관리하면서 어디까지 읽었는지를 추적합니다. 이 덕분에 같은 데이터를 여러 컨슈머 그룹이 독립적으로 소비할 수도 있고, 필요하다면 과거 데이터를 다시 읽어 재처리할 수도 있습니다.
운영 환경에서는 Consumer Lag(생산 속도와 소비 속도의 차이)을 모니터링하는 것이 중요합니다. Lag이 커지면 메시지가 적체되고, 실시간성이 떨어진다는 신호가 되기 때문입니다.
Consumer Lag

프로듀서가 데이터를 기록하는 속도와 컨슈머가 데이터를 소비하는 속도 사이에 차이가 발생하면 오프셋 간격이 벌어지는데, 이를 Consumer Lag이라고 합니다. Lag은 컨슈머가 제때 데이터를 처리하지 못하고 있다는 신호이므로, 실시간성을 요구하는 시스템에서는 중요한 모니터링 지표가 됩니다. 여러 파티션이 있을 경우 가장 큰 Lag을 records-lag-max로 정의하여 관리합니다.
컨슈머 애플리케이션 내부에서 Lag을 확인할 수도 있지만, 이는 컨슈머 로직에 의존하기 때문에 운영 환경에서는 신뢰하기 어렵습니다. 따라서 보통 LinkedIn이 공개한 오픈소스 툴인 Burrow 같은 모니터링 시스템을 통해 외부에서 Lag을 추적하고 알람을 설정합니다. 실무에서는 Prometheus, Grafana 같은 모니터링 스택과 연계해 대시보드로 시각화하는 방식도 많이 활용됩니다.
메시징 플랫폼 비교
메시징 플랫폼은 크게 메시지 브로커와 이벤트 브로커로 나눌 수 있습니다. 메시지 브로커는 생산자가 메시지를 큐에 넣으면 컨슈머가 이를 소비하면서 큐에서 삭제하는 방식으로 동작합니다. 따라서 동일한 이벤트에 대해 다른 작업을 수행하는 컨슈머마다 별도의 큐를 두어야 하며, 데이터는 일회성 소비에 초점이 맞춰져 있습니다. 대표적인 예로 RabbitMQ나 AWS SQS가 있습니다.
반면 이벤트 브로커인 카프카는 데이터를 소비하더라도 원본 데이터가 삭제되지 않습니다. 모든 이벤트는 분산 로그에 저장되고, 각 컨슈머는 자신만의 오프셋을 유지하며 데이터를 읽습니다. 이 덕분에 여러 컨슈머 그룹이 같은 이벤트를 독립적으로 처리할 수 있고, 필요하다면 과거 데이터를 다시 재처리할 수도 있습니다. 즉, 카프카는 단순 메시지 큐를 넘어 이벤트 저장소이자 스트리밍 플랫폼의 성격을 동시에 갖추고 있으며, 이 점이 메시지 브로커와의 가장 큰 차별점입니다.
[ Reference ]
Confluence Apache Kafka
Conducktor kafkademy
데브원영 - 아파치 카프카
Contributor9 블로그
댓글남기기