kafka 제대로 된 동작원리나 개념을 모르는 것 같아 살펴보기로 한다.
Kafka를 검색하면 나오는 설명으로 크게 두 가지가 있는 것 같다.
카프카의 기술적 구조에 초점:
분산 시스템: 데이터를 여러 노드에 분산해 처리하므로 확장성과 고가용성을 제공함.
메시지 스트리밍: 메시지가 계속해서 들어오고, 실시간으로 데이터를 전달할 수 있는 스트리밍 처리 지원.
이 정의는 카프카가 기존 메시지 큐(Message Queue) 시스템에서 출발했다는 배경에 맞춰 설명하는 방식.
카프카의 주요 역할
데이터 스트리밍:
실시간으로 데이터를 수집하고 처리하기 위해 데이터를 브로커(broker)에 저장하고 배포
메시지 브로커:
서로 다른 시스템 간에 데이터를 안전하게 전달
데이터 파이프라인:
다양한 데이터 소스에서 데이터를 수집하고 분석 시스템으로 전달하는 데이터 파이프라인을 구성
왜 카프카가 필요했나?
기존 메시지 브로커(MQ)나 데이터 파이프라인 도구들은 다음과 같은 문제를 가지고 있었음
대용량 처리 한계: 데이터의 양이 폭발적으로 증가하면서 기존 시스템은 확장성이 부족
실시간 데이터 부족: 기존 시스템은 배치(batch) 방식으로 데이터를 처리해 실시간 데이터 분석의 어려움
다양한 데이터 통합 문제: 여러 데이터 소스에서 들어오는 데이터를 안정적으로 관리하고 통합의 복잡성
카프카는 이러한 문제를 해결하며 실시간 데이터 스트리밍과 높은 확장성을 제공했습니다.
카프카의 핵심 개념인 이벤트에 더 초점을 맞춘 설명:
이벤트(Event): 시스템에서 발생한 상태 변화나 중요한 데이터.
예) "유저가 결제를 완료했다", "센서가 온도 데이터를 보냈다"
스트리밍(Streaming): 이벤트가 발생하자마자 지속적으로 처리하고 소비자에게 전달.
이 정의는 오늘날 카프카가 주로 사용되는 데이터 처리 패러다임을 반영해 설명하는 방식으로, 특히 실시간 데이터 처리가 강조되는 환경에서는 "이벤트 스트리밍 플랫폼"이 더 적절한 표현이다.
공식 문서에서 "이벤트 스트리밍 플랫폼"이라고 설명하고 잇는데 오늘날 kafka가 단순한 메시지 큐 역할을 넘어서 실시간 이벤트 중심 데이터 처리를 주요 목적으로 하기 때문인 것 같다.
카프카가 이벤트 스트리밍 플랫폼에 더 가깝다고 설명했는데 그러면 이벤트 스트리밍이란 무엇일까?
기술적으로 말해서 이벤트 스트리밍은 데이터베이스, 센서, 모바일 기기, 클라우드 서비스, 소프트웨어 애플리케이션과 같은 이벤트 소스에서 이벤트 스트림 형태로 실시간으로 데이터를 캡처하는 것을 말한다. 이러한 이벤트 스트림을 나중에 검색할 수 있도록 내구성 있게 저장하고 실시간 및 사후 분석을 통해 조작, 처리 및 반응한다. 또한 필요에 따라 이벤트 스트림을 다른 시스템 또는 기술로 전달한다.
결과적으로 이벤트 스트리밍은 적절한 정보가 적시에 적합한 장소에 전달되도록 데이터의 지속적인 흐름과 해석을 보장한다.
다른 시스템에서 데이터를 지속적으로 가져오고 내보내는 것을 포함하여 이벤트 스트림을 게시(쓰기)하고 구독(읽기)합니다.
카프카는 발신자(Producer)가 데이터를 토픽(Topic)에 게시하고, 수신자(Consumer)가 해당 토픽을 구독하여 데이터를 읽는 구조!
게시(쓰기): 다양한 시스템(예: IoT 센서, 애플리케이션 로그)에서 발생하는 데이터를 실시간으로 카프카에 보냄.
구독(읽기): 다른 서비스나 데이터 파이프라인이 이 데이터를 구독해 실시간 또는 배치(batch)로 처리.
카프카의 장점은 메시지를 손실 없이 고성능으로 처리하는 분산 구조 덕분에 대량의 데이터 스트림을 다룰 수 있다는 점이다.
원하는 기간 동안 이벤트 스트림을 지속적이고 안정적으로 저장합니다.
카프카는 단순히 이벤트를 전달하는 것만 하지 않고 내구성 있게 저장할 수 있다.
이벤트는 카프카 브로커의 디스크에 저장되며, 설정에 따라 며칠, 몇 주 또는 무기한 저장 가능.
이를 통해 실시간뿐만 아니라 과거 데이터 재처리도 가능!
전통적인 메시지 큐(MQ)는 데이터가 소비되면 삭제되는 반면, 카프카는 데이터의 스토리지 시스템 역할도 수행한다.
실시간 및 사후 이벤트 스트림 처리
카프카는 데이터가 발생하는 즉시 실시간 처리와 필요에 따라 회고적(batch) 처리도 지원!
실시간 처리: Kafka Streams, Flink, Spark와 같은 스트리밍 프레임워크를 통해 실시간 데이터 분석.
사후 처리: 특정 시점에 발생한 이벤트 데이터를 다시 읽어 재처리.
실시간과 배치 처리를 모두 지원하기 때문에 데이터 손실 최소화 및 유연한 분석이 가능하다.
카프카의 아키텍처를 알려면 먼저 Pub/Sub 구조를 알아야 한다.
카프카의 탄생 배경을 먼저 알면 좋은데, 링크드인에서 대규모 데이터 처리 문제를 겪고 있었고 이를 해결하기 위해 카프카를 만들었다.
실시간 로그 수집: 사용자 활동 데이터, 서버 로그 등이 대량으로 발생
데이터 전달 지연: 기존 시스템은 대량 데이터를 여러 시스템으로 효율적으로 전달하기 어려움
데이터 손실: 장애가 발생하면 메시지가 손실되거나 순서가 뒤바뀌는 문제

기존 메시지 큐의 한계
당시 주로 사용되던 메시지 큐(Message Queue) 시스템들은 포인트-투-포인트(Point-to-Point) 구조가 일반적이었다.
카프카는 이런 문제를 해결하기 위해 Pub/Sub(발행/구독) 구조를 채택하고, Pub/Sub구조는 아래와 같은 장점이 있다.
느슨한 결합(Decoupling)
발신자(Producer)와 수신자(Consumer)가 직접 연결되지 않아도 됨.
여러 Consumer가 동시에 동일한 메시지를 수신 가능.
데이터 재사용
Consumer가 메시지를 읽더라도 메시지는 카프카 브로커에 내구성 있게 저장됨.
필요할 때 과거 데이터를 다시 읽을 수 있어 데이터 분석에 유리.
확장성
분산 브로커 아키텍처 덕분에 수평적으로 확장 가능.
수천 개의 Producer와 Consumer가 동시에 연결되어도 안정적으로 작동.
대용량 실시간 처리
Pub/Sub 구조 덕분에 실시간으로 이벤트 스트리밍을 처리할 수 있어 대규모 트래픽 대응이 가능.

Pub/Sub(발행/구독) 모델은 데이터를 발행자(Producer)가 보내면 구독자(Consumer)가 해당 데이터를 받아보는 방식으로 중간에 브로커(Broker)가 있어서 발행과 구독을 관리한다.
(카프카에서는 Publisher의 역할을 Producer가 하고 Subscriber의 역할을 Consumer가 행함)
발행자(Producer): 메시지를 생성하고 브로커에 보냄
예) 뉴스 기사가 작성되면 서버에 업로드
브로커(Broker): 메시지를 받아서 원하는 구독자에게 전달
예) 카프카가 여기서 브로커 역할
구독자(Consumer): 브로커에서 메시지를 구독하여 처리
예) 뉴스 앱에서 특정 주제 뉴스를 받아보기
발행자는 자신이 보내는 메시지를 특정 주제(Topic)에 게시함.
구독자는 그 주제를 구독해 필요한 데이터만 받아봄.

1) 고가용성 (High Availability)
하나의 Kafka Broker가 고장나도 나머지 Broker들이 데이터 처리를 이어갈 수 있다.
클러스터가 아니었다면 브로커 하나가 다운될 때 서비스 전체가 멈출 위험이 있다.
2) 확장성 (Scalability)
데이터 처리량이 증가할 때 새로운 Broker를 추가해서 더 많은 데이터를 분산 처리할 수 있다.
단일 브로커로는 대량의 데이터를 처리하는 데 한계가 있다.
3) 데이터 복제 (Replication)
동일한 데이터를 여러 Broker에 복제해서 데이터 손실을 방지한다!
예를 들어, 하나의 브로커가 고장나도 복제된 데이터가 다른 브로커에 남아 있음.
간단하게 말하자면 Kafka Cluster는 여러 대의 트럭으로 구성된 배송 네트워크! 한 트럭이 고장나도 나머지 트럭이 계속 배송할 수 있다.

예를 들어 위에 그림에 "Topic A"가 partition 0, partition 1, partition 2로 나뉘어져 있는데 이 파티션들이 Broker 1, Broker 2, Broker 3에 존재한다.
partition에 보면 Leader와 Follower로 구성되어 있는데 이는 복제와 관련되어 있다.
예를 들어 Broker 1에 partition 0을 보자. Broker 1에 partition 0에는 Leader라고 되어 있는데 이는 처음에 데이터가 들어왔을 때 저장되는 partition을 의미한다. 이 후에 Leader 파티션에 저장이 된 후에 Broker2, 3에 존재하는 Follower partition 0들에 데이터가 복제된다.
이를 자세히 알아보기 위해 카프카에서의 병렬 처리와 복제(Replication)을 알아보자.
병렬 처리란 Kafka 클러스터 내에서 파티션들이 각각 다른 브로커에서 독립적으로 리더 역할을 수행하며 동시에 메시지를 처리하는 것을 의미한다.
| Partition | Leader Broker | 메시지 처리 |
|---|---|---|
| Partition 0 | Broker 1 | 동시에 메시지 저장 |
| Partition 1 | Broker 2 | 동시에 메시지 저장 |
| Partition 2 | Broker 3 | 동시에 메시지 저장 |
복제(Replication):
Kafka에서는 데이터 안정성과 고가용성을 위해 파티션을 여러 브로커에 복제한다. 복제본 개수는 토픽 설정에서 Replication Factor로 지정된다. 예를 들어, Replication Factor = 3이라면 각 파티션이 3개의 브로커에 복제된다.
리더(Leader)와 팔로워(Follower):
| Partition | Broker 1 | Broker 2 | Broker 3 |
|---|---|---|---|
| Partition 0 | Leader | Follower | Follower |
| Partition 1 | Follower | Leader | Follower |
| Partition 2 | Follower | Follower | Leader |
리더 파티션에 메시지가 저장된 직후
프로듀서가 리더(Leader) 파티션에 메시지를 성공적으로 쓰면, Kafka는 즉시 팔로워(Follower)들에게 해당 데이터를 복제.
즉, Broker 1의 Partition 0 (Leader)에 데이터가 저장되면 Broker 2나 Broker 3의 Partition 0 (Follower)로 복제가 이루어진다.
비동기(Asynchronous) 복제
복제는 비동기 방식으로 이루어진다. 즉, 리더에 데이터가 먼저 쓰인 후 팔로워들이 이를 복사한다.
팔로워 파티션들은 복제된 데이터만 저장하며 데이터 읽기나 쓰기 요청을 처리하지 않는다고 한다. 만약 리더가 장애가 발생하면 Kafka가 리더 선출(Leader Election)을 통해 팔로워 중 하나를 새로운 리더로 승격한다.
카프카의 구독은 컨슈머가 특정 토픽에 발행된 메시지를 읽어오는 프로세스를 의미한다. 여기서 중요한 개념은 컨슈머 그룹이다.
구독과 메시지 소비
컨슈머 그룹
메시지 읽기 시점
poll()을 사용해 새로운 메시지가 있는지 주기적으로 확인하면서 메시지를 읽는다.컨슈머가 구독을 시작한다
Consumer1은 chat-room-1 토픽을 구독한다고 설정되었다면, 이 컨슈머는 해당 토픽의 메시지를 읽을 준비가 된다.메시지가 발행된다
chat-room-1 토픽에 발행된다. 이제 이 메시지는 발행된 상태가 된다.컨슈머가 poll() 메서드로 메시지를 확인한다
Consumer1은 poll() 메서드를 호출해 주기적으로 카프카로부터 메시지를 받아온다. 메시지가 없으면 아무것도 받지 않고 대기하게 된다.컨슈머가 메시지를 처리한다
Consumer1은 카프카에서 받은 메시지를 처리하고, 필요한 작업(예: 메시지 화면에 출력)을 한다.메시지 오프셋
Zookeeper는 분산 시스템의 코디네이션 서비스로, 여러 서버들 간의 상태 정보, 구성 정보, 동기화 등을 관리하는 역할을 한다. 쉽게 말하면, 여러 서버들 간에 협력하고 데이터를 일관되게 유지하려면 Zookeeper가 그들 간의 조정자 역할을 한다.
카프카는 처음에 분산 시스템을 구성하기 위해 Zookeeper를 사용하여 클러스터의 상태를 관리하고 파티션의 리더와 팔로워를 관리하는데 사용했다. 예를 들어, Zookeeper는 카프카의 브로커가 리더/팔로워 상태를 변경할 때 이 정보를 서로 공유하고 관리하는 역할을 한다.
카프카는 설정 파일에서 Zookeeper의 주소를 지정해야 했다. 예를 들어, 카프카 설정에서 다음과 같이 Zookeeper 주소를 설정할 수 있다.
# 카프카 서버 설정 (server.properties)
zookeeper.connect=localhost:2181 # Zookeeper 서버의 주소
카프카 클러스터를 구성할 때 Zookeeper가 필수였고, 카프카는 내부적으로 Zookeeper를 통해 브로커와 파티션 리더 관리를 했다.
KRaft 모드는 카프카가 Zookeeper 없이 자체적으로 Raft 프로토콜을 사용하여 리더 선출과 메타데이터 관리를 하는 모드!
Raft 프로토콜은 분산 시스템에서 일관성을 유지하면서 리더를 선출하고, 파티션을 관리하는 알고리즘이다.
KRaft 모드는 Zookeeper의 필요성을 없애고 카프카 자체로 리더 선출과 메타데이터 관리를 하여 운영의 복잡성을 크게 줄일 수 있다.
KRaft 모드를 사용하려면, 카프카 설정에서 Zookeeper 관련 항목을 제거하고, 대신 KRaft 모드 설정을 활성화해야 한다.
# 카프카 KRaft 모드 설정 (server.properties)
# Zookeeper 설정을 비활성화
zookeeper.connect= # 비워두거나 제거
# KRaft 모드 활성화
process.roles=broker,controller
# 카프카가 브로커 역할과 컨트롤러 역할을 동시에 할 수 있도록 설정
https://kafka.apache.org/intro#intro_platform
https://velog.io/@hahnwoong/%EC%B9%B4%ED%94%84%EC%B9%B4-%EC%B9%B4%ED%94%84%EC%B9%B4-%EC%B9%B4%ED%94%84%EC%B9%B4-%EC%B9%B4%ED%94%84%EC%B9%B4.-%EC%96%B4-%EC%96%B4%ED%97%88-%EC%96%B4%EB%A0%A4%EC%9B%8C
https://velog.io/@djc06048/%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC-Kafka-Redis-RabbitMQ%EB%9E%80
https://velog.io/@hyeondev/Apache-Kafka-%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90