백엔드(BackEnd)/Kafka

[Kafka] Apache Kafka 개요

마달랭 2025. 5. 26. 13:30

개요

Apache Kafka는 대용량 실시간 데이터 스트리밍을 위한 분산 플랫폼이다. LinkedIn에서 개발되어 2011년 Apache 재단에 오픈소스로 기증 되었다.

 

Kafka는 고성능 메시지 처리가 가능하여 초당 수백만 개의 메시지를 처리할 수 있는 높은 처리량을 제공한다. 메시지를 디스크에 순차적으로 저장하여 빠른 읽기/쓰기 성능을 보장한다.

여러 서버에 걸쳐 데이터를 분산 저장하므로 단일 장애점이 없고, 수평적 확장이 가능하여 분산 아키텍처에 어울린다.

메시지를 디스크에 영구 저장하고 복제본을 유지하여 데이터 손실을 방지하여 내구성과 신뢰성이 있다.

 

위와 같은 특성으로 인해 실시간 로그 수집, 이벤트 스트리밍, 마이크로서비스 간 비동기 통신, 데이터 파이프라인 구축, 실시간 분석을 위한 데이터 스트리밍 등에 널리 사용된다.

Kafka는 높은 처리량과 낮은 지연시간이 필요한 대규모 데이터 처리 환경에서 핵심적인 역할을 하는 인프라 컴포넌트다.

 

 

구성요소

  • Topic: 메시지가 저장되는 논리적 채널로, 카테고리나 피드 이름과 같은 역할을 한다.
  • Partition: 토픽을 물리적으로 분할한 단위로, 병렬 처리와 확장성을 제공한다.
  • Producer: 토픽에 메시지를 발행하는 클라이언트 애플리케이션이다.
  • Consumer: 토픽에서 메시지를 구독하고 처리하는 클라이언트 애플리케이션이다.
  • Broker: Kafka 서버로, 메시지를 저장하고 전달하는 역할을 한다.

Kafka 서버가 곧 브로커이며 최소 구성으로는 Kafka브로커 + ZooKeeper를 통해 Kafka시스템을 구현할 수 있다, 단 최근엔 KRaft 모드를 사용할 경우 ZooKeeper를 사용하지 않고도 시스템을 구현할 수 있다고 한다.

 

 

아키텍처

보통은 다음과 같은 아키텍처 개요를 따른다.

클라이언트 → API 게이트웨이 → Kafka → 처리 서비스 → 데이터베이스

 

  1. 생산자(Producer) 측: API 게이트웨이
  2. 소비자(Consumer) 측: 처리 서비스

 

메시지 순서 보장

토픽: "orders"
- 파티션 0: 메시지 A → B → C (이 순서는 보장됨)
- 파티션 1: 메시지 D → E → F (이 순서는 보장됨)

그러나 파티션 0과 1의 메시지들 간에는 순서 보장 없음
(예: 메시지 D가 메시지 A보다 먼저 처리될 수 있음)

 

만약 단일 파티션을 사용한다면 완전한 순서 보장이 가능하나, 병렬 처리가 불가능하므로 처리량이 제한되게 된다. 위와 같은 아키텍처를 구현할 때 고려해야 할 사항으로 순서가 중요한 경우, 같은 파티션에 메시지가 가도록 파티션 키를 설정해야한다. 웹 서버 기준으로 JWT토큰 검증 후 X-User-ID를 헤더로 사용할 때 이 값을 활용해 유저별 파티션을 구분하여 각 유저가 항상 동일한 파티션에 배정되게끔 하여 메시지 순서를 보장할 수 있다.

 

파티션의 개수는 사용자가 지정할 수 있다. Kafka의 파티션 개수는 토픽을 생성할 때 설정할 수 있으며, 이미 생성된 토픽의 파티션 수는 나중에 증가시킬 수는 있지만 줄일 수는 없다. 하나의 파티션은 하나의 Consumer에 의해서만 처리된다. 따라서 Consumer 인스턴스를 늘려 처리량을 높이려면 파티션도 충분히 많아야 한다. 하지만 너무 많은 파티션은 순서 관리를 복잡하게 만들 수 있다.

 

많은 파티션을 보유하면 더 높은 병렬 처리가 가능하지만 각 파티션은 브로커에서 파일 핸들과 메모리를 사용하므로 너무 많은 파티션은 브로커 리소스 부담 증가로 이어진다. 이는 당연하게도 요청 지연 시간 증가로 이어지게 된다. 일반적으로 브로커당 최대 2,000~4,000개 파티션이 권장된다.

필요 파티션 수 = max(목표 처리량 ÷ 단일 파티션 처리량, Consumer 인스턴스 수)

 

 

볼륨 데이터

위에서 kafka는 메시지를 디스크에 순차적으로 저장하여 빠른 읽기/쓰기 성능을 보장한다고 언급하였다. 따라서 메시지를 저장하기 위한 볼륨 설정이 필요하다. 기본적으로 Kafka는 호스트의 로컬 스토리지를 사용하여 메시지 데이터를 저장한다. 이는 다른 분산 시스템과 차별화되는 Kafka의 중요한 설계 결정 중 하나이다.

 

각 토픽 파티션은 로그 세그먼트 파일 집합으로 저장되며, 파일 명명 규칙은 [토픽명]-[파티션번호]/00000000000000000000.log과 같은 형태가 된다.

 

 

Kafka가 로컬 스토리지를 사용하는 이유는 로컬 디스크 I/O는 일반적으로 네트워크 스토리지보다 빠르며, 순차적 읽기/쓰기에 최적화된 설계되어있기 때문이다. 또한 각 브로커가 자체 디스크 리소스를 가지고, 다른 브로커의 I/O 부하에 영향 받지 않는다. 브로커가 추가된다면 저장 용량만 추가되므로 확장이 간단하다.

 

네트워크 스토리지를 이론상 사용할 수도 있지만 성능 저하 가능성이 있기 때문에 이는 Kafka를 사용하는 주된 이유가 되지 못한다. Docker나 Kubernetes 환경에서는 볼륨 마운트로 컨테이너 재시작 시에도 데이터 유지가 되어 컨테이너 볼륨을 통해 관리하기도 쉽다. 로컬 스토리지를 사용하므로 HDD대신 SSD를 사용하는게 권장된다.

728x90