본문으로 건너뛰기
Kreath Archive
TechProjectsBooksAbout
TechProjectsBooksAbout

내비게이션

  • Tech
  • Projects
  • Books
  • About
  • Tags

카테고리

  • AI / ML
  • 웹 개발
  • 프로그래밍
  • 개발 도구

연결

  • GitHub
  • Email
  • RSS
© 2026 Kreath Archive. All rights reserved.Built with Next.js + MDX
홈TechProjectsBooksAbout
//
  1. 홈
  2. 테크
  3. 3장: Apache Kafka 심층 분석
2026년 2월 14일·데이터·

3장: Apache Kafka 심층 분석

Kafka의 핵심 아키텍처를 심층적으로 분석합니다. KRaft 모드, 브로커와 파티션 레플리케이션, 프로듀서 전송 보장, 컨슈머 그룹과 리밸런싱까지 Kafka의 내부를 이해합니다.

18분299자9개 섹션
streamingdata-engineering
공유
realtime-pipeline3 / 11
1234567891011
이전2장: 이벤트 스트리밍 아키텍처 기초다음4장: Kafka 프로듀서와 컨슈머 고급 패턴

학습 목표

  • Apache Kafka의 전체 아키텍처를 이해합니다.
  • KRaft 모드의 동작 원리와 ZooKeeper 대비 장점을 파악합니다.
  • 브로커, 파티션, 레플리카의 관계와 레플리케이션 메커니즘을 학습합니다.
  • 프로듀서의 전송 보장 수준(acks 설정)을 이해합니다.
  • **Consumer Group(컨슈머 그룹)**과 리밸런싱의 동작 방식을 파악합니다.

Kafka 아키텍처 개요

Apache Kafka는 분산 이벤트 스트리밍 플랫폼입니다. LinkedIn에서 2011년 오픈소스로 공개된 이후, 사실상 이벤트 스트리밍의 표준으로 자리잡았습니다.

Kafka의 핵심 설계 철학은 다음과 같습니다.

  • 높은 처리량: 순차 I/O와 제로카피(zero-copy) 전송으로 초당 수백만 건 처리
  • 내구성: 디스크 기반 저장 + 레플리케이션으로 데이터 유실 방지
  • 수평 확장: 브로커와 파티션 추가로 선형적 확장
  • 다중 소비: 이벤트 로그 기반으로 여러 컨슈머가 독립적으로 소비

KRaft 모드 — ZooKeeper의 퇴장

ZooKeeper 시대의 문제

Kafka는 오랫동안 Apache ZooKeeper에 의존하여 클러스터 메타데이터를 관리했습니다. 브로커 등록, 파티션 리더 선출, 토픽 설정 등을 ZooKeeper가 담당했습니다.

그러나 이 구조에는 여러 문제가 있었습니다.

  • 운영 복잡도: Kafka와 ZooKeeper 두 시스템을 별도로 관리해야 함
  • 확장 한계: ZooKeeper의 메타데이터 처리 성능이 병목 (수십만 파티션에서 한계)
  • 장애 전파: ZooKeeper 장애가 Kafka 전체에 영향
  • 리더 선출 지연: 대규모 클러스터에서 컨트롤러 장애 복구 시간이 수 분 소요

KRaft 모드의 동작

**KRaft(Kafka Raft)**는 Kafka 자체에 Raft 기반 합의 프로토콜을 내장하여, ZooKeeper 없이 메타데이터를 관리하는 모드입니다.

KRaft 모드의 핵심 개념은 메타데이터를 이벤트 로그로 관리한다는 것입니다. 토픽 생성, 파티션 재배치, 설정 변경 등 모든 메타데이터 변경이 __cluster_metadata라는 내부 토픽에 이벤트로 기록됩니다. Kafka가 자기 자신의 원리를 메타데이터 관리에도 적용한 셈입니다.

KRaft의 장점

항목ZooKeeper 모드KRaft 모드
운영 대상Kafka + ZooKeeperKafka만
파티션 상한약 20만수백만
컨트롤러 장애 복구수 분수 초
메타데이터 전파비동기, 비일관 가능로그 기반, 일관성 보장
Info

2026년 현재, Kafka의 새 배포에서는 KRaft 모드가 기본입니다. 기존 ZooKeeper 모드에서의 마이그레이션 도구도 제공되므로, 아직 ZooKeeper를 사용하고 있다면 마이그레이션을 계획해야 합니다.


브로커, 파티션, 레플리카

Broker (브로커)

**Broker(브로커)**는 Kafka 클러스터를 구성하는 개별 서버입니다. 각 브로커는 여러 파티션의 데이터를 저장하고, 프로듀서의 쓰기 요청과 컨슈머의 읽기 요청을 처리합니다.

레플리케이션

Kafka는 데이터 내구성을 위해 각 파티션을 여러 브로커에 **Replica(레플리카)**로 복제합니다.

  • Leader Replica(리더 레플리카): 모든 읽기/쓰기 요청을 처리하는 주 레플리카
  • Follower Replica(팔로워 레플리카): 리더의 데이터를 복제하여 동기화 유지
replication-example
text
토픽: orders (파티션 3개, 레플리카 팩터 3)
 
         브로커 1      브로커 2      브로커 3
P0:      Leader        Follower     Follower
P1:      Follower      Leader       Follower
P2:      Follower      Follower     Leader

리더가 분산 배치되어 부하가 균등하게 분배됩니다.

ISR (In-Sync Replicas)

**ISR(In-Sync Replicas)**은 리더와 동기화가 완료된 레플리카의 집합입니다. 팔로워가 리더의 데이터를 일정 시간 내에 복제하지 못하면 ISR에서 제외됩니다.

ISR은 데이터 안전성과 직결됩니다. 리더가 장애를 겪으면 ISR에 속한 팔로워 중 하나가 새 리더로 승격됩니다. ISR에 속하지 않은 팔로워는 데이터가 불완전할 수 있으므로, 기본 설정에서는 리더 후보에서 제외됩니다.

isr-example
text
파티션 0의 상태:
  리더(브로커 1): offset 0~100 (최신)
  팔로워(브로커 2): offset 0~100 (ISR - 동기화 완료)
  팔로워(브로커 3): offset 0~95  (ISR에서 제외 - 5개 뒤처짐)
Warning

unclean.leader.election.enable 설정은 ISR이 비어있을 때 동기화되지 않은 레플리카를 리더로 승격할지 결정합니다. 활성화하면 가용성이 높아지지만 데이터 유실 위험이 있습니다. 데이터 정확성이 중요한 시스템에서는 반드시 비활성화(기본값)로 유지해야 합니다.


프로듀서와 전송 보장

acks 설정

프로듀서의 acks 설정은 "메시지가 성공적으로 기록되었다"의 기준을 결정합니다.

acks=0: 프로듀서가 브로커의 응답을 기다리지 않습니다. 전송 즉시 성공으로 간주합니다. 가장 빠르지만 데이터 유실 가능성이 높습니다.

ProducerAcks0.java
java
Properties props = new Properties();
props.put("acks", "0");
// 브로커 응답을 기다리지 않음 — 최대 처리량, 유실 가능

acks=1: 리더 레플리카에 기록되면 성공으로 응답합니다. 리더 장애 시 팔로워에 아직 복제되지 않은 데이터가 유실될 수 있습니다.

acks=all (또는 -1): 모든 ISR 레플리카에 복제가 완료되면 성공으로 응답합니다. 가장 안전하지만 지연 시간이 늘어납니다.

ProducerAcksAll.java
java
Properties props = new Properties();
props.put("acks", "all");
props.put("min.insync.replicas", "2");
// ISR 중 최소 2개 레플리카에 기록되어야 성공
// 레플리카 팩터 3 + min.insync.replicas 2 → 1대 장애 허용

acks와 min.insync.replicas의 조합

acksmin.insync.replicas의미
0-응답 안 기다림, 최대 속도
1-리더만 확인, 리더 장애 시 유실 가능
all1리더만 있어도 성공 (acks=1과 동일)
all2리더 + 1개 팔로워 확인, 1대 장애 허용
all33개 모두 확인, 가장 안전하지만 느림
Tip

프로덕션 환경에서의 권장 설정은 레플리카 팩터 3, acks=all, min.insync.replicas=2입니다. 이 조합은 1대의 브로커 장애를 허용하면서도 데이터 유실을 방지합니다.


컨슈머 그룹

컨슈머 그룹의 개념

**Consumer Group(컨슈머 그룹)**은 하나의 토픽을 협력하여 소비하는 컨슈머들의 논리적 그룹입니다. 토픽의 각 파티션은 그룹 내 정확히 하나의 컨슈머에게 할당됩니다.

consumer-group-assignment
text
토픽: orders (6개 파티션)
컨슈머 그룹: order-processor (3개 컨슈머)
 
  컨슈머 1 ← P0, P1
  컨슈머 2 ← P2, P3
  컨슈머 3 ← P4, P5

컨슈머 수가 파티션 수보다 많으면 초과 컨슈머는 유휴 상태가 됩니다. 따라서 컨슈머 수는 파티션 수 이하로 유지하는 것이 효율적입니다.

서로 다른 컨슈머 그룹은 같은 토픽을 독립적으로 소비합니다. 주문 이벤트를 분석 시스템(그룹 A)과 알림 시스템(그룹 B)이 각각 독립적으로 처리하는 것이 가능합니다.

리밸런싱

컨슈머가 그룹에 합류하거나 떠나면, 파티션 할당이 재조정됩니다. 이를 **Rebalancing(리밸런싱)**이라고 합니다.

리밸런싱이 발생하는 상황은 다음과 같습니다.

  • 새 컨슈머가 그룹에 합류
  • 기존 컨슈머가 그룹에서 이탈 (장애 또는 정상 종료)
  • 토픽에 파티션이 추가됨
  • 컨슈머의 구독 토픽이 변경됨

Cooperative Rebalancing (협력적 리밸런싱)

전통적인 **Eager Rebalancing(즉시 리밸런싱)**에서는 리밸런싱이 시작되면 모든 컨슈머가 모든 파티션을 반납하고 새로 할당받습니다. 이 동안 전체 소비가 중단됩니다.

**Cooperative Rebalancing(협력적 리밸런싱)**은 이 문제를 해결합니다. 변경이 필요한 파티션만 재할당하고, 나머지 파티션은 계속 소비합니다.

cooperative-rebalancing
text
[Eager 방식]
1단계: 모든 컨슈머가 모든 파티션 반납 (전체 중단)
2단계: 새로운 할당 계산
3단계: 모든 파티션 재할당 (소비 재개)
 
[Cooperative 방식]
1단계: 이동이 필요한 파티션만 해당 컨슈머가 반납 (나머지는 계속 소비)
2단계: 반납된 파티션을 새 컨슈머에게 할당
→ 중단 시간 최소화
CooperativeRebalancing.java
java
Properties props = new Properties();
props.put("partition.assignment.strategy",
    "org.apache.kafka.clients.consumer.CooperativeStickyAssignor");
// 협력적 리밸런싱 + 기존 할당 유지 선호
Tip

프로덕션 환경에서는 CooperativeStickyAssignor를 사용하는 것을 권장합니다. 리밸런싱 중 소비 중단을 최소화하고, 기존 파티션 할당을 최대한 유지하여 캐시 효율도 높입니다.


Kafka의 성능 특성

Kafka가 높은 처리량을 달성하는 핵심 기술을 간략히 살펴보겠습니다.

순차 I/O

Kafka는 데이터를 디스크에 순차적으로 기록합니다. 순차 디스크 I/O는 랜덤 I/O보다 수십~수백 배 빠르며, 경우에 따라 메모리 접근 속도에 근접합니다.

Zero-Copy 전송

프로듀서가 보낸 데이터를 컨슈머에게 전달할 때, 커널 영역에서 사용자 영역으로의 불필요한 복사를 건너뛰는 sendfile() 시스템 콜을 사용합니다. 이를 통해 CPU 사용량과 메모리 복사 비용을 줄입니다.

페이지 캐시 활용

Kafka는 자체 캐시를 구현하지 않고 OS의 **Page Cache(페이지 캐시)**에 의존합니다. 최신 데이터는 대부분 페이지 캐시에 존재하므로, 컨슈머가 최신 데이터를 읽을 때 디스크 I/O 없이 메모리에서 직접 전송합니다.

배치 처리

프로듀서는 여러 메시지를 하나의 배치로 묶어 전송하고, 컨슈머도 여러 메시지를 한 번에 가져옵니다. 네트워크 라운드트립과 I/O 횟수를 줄여 처리량을 높입니다.

압축

배치 단위로 gzip, snappy, lz4, zstd 등의 압축을 적용하여 네트워크 대역폭과 디스크 사용량을 줄입니다.


정리

이번 장에서는 Apache Kafka의 핵심 아키텍처를 심층적으로 살펴보았습니다.

  • KRaft 모드: ZooKeeper를 제거하고 Raft 기반 메타데이터 관리로 운영 복잡도를 줄였습니다.
  • 레플리케이션: 리더-팔로워 구조와 ISR로 내구성과 가용성을 보장합니다.
  • 프로듀서 acks: 0/1/all 설정으로 속도와 안전성의 트레이드오프를 조절합니다.
  • 컨슈머 그룹: 파티션 기반 병렬 소비와 Cooperative 리밸런싱으로 효율적 확장이 가능합니다.
  • 성능 특성: 순차 I/O, 제로카피, 페이지 캐시, 배치 처리의 조합으로 높은 처리량을 달성합니다.

다음 장 미리보기

4장에서는 Kafka 프로듀서와 컨슈머의 고급 패턴을 다룹니다. Idempotent 프로듀서와 트랜잭셔널 프로듀서를 통한 Exactly-once 시맨틱스, 수동 오프셋 관리, 배치 크기와 압축 최적화, Dead Letter Queue 패턴까지 프로덕션 수준의 Kafka 활용법을 학습합니다.

이 글이 도움이 되셨나요?

관련 주제 더 보기

#streaming#data-engineering

관련 글

데이터

4장: Kafka 프로듀서와 컨슈머 고급 패턴

Idempotent 프로듀서, 트랜잭셔널 프로듀서, Exactly-once 시맨틱스, 수동 오프셋 관리, 배치 최적화, Dead Letter Queue 등 프로덕션 수준의 Kafka 활용 패턴을 학습합니다.

2026년 2월 16일·18분
데이터

2장: 이벤트 스트리밍 아키텍처 기초

이벤트 로그, 토픽과 파티션, 오프셋 관리, 이벤트 시간과 처리 시간의 차이, 워터마크, 윈도우 연산 등 스트림 처리의 핵심 개념을 체계적으로 학습합니다.

2026년 2월 12일·20분
데이터

5장: Kafka Connect와 데이터 통합

Kafka Connect의 Source/Sink 아키텍처, 주요 커넥터 활용, 분산 모드 운영, SMT를 통한 데이터 변환, 커스텀 커넥터 개발까지 Kafka 기반 데이터 통합 전략을 학습합니다.

2026년 2월 18일·14분
이전 글2장: 이벤트 스트리밍 아키텍처 기초
다음 글4장: Kafka 프로듀서와 컨슈머 고급 패턴

댓글

목차

약 18분 남음
  • 학습 목표
  • Kafka 아키텍처 개요
  • KRaft 모드 — ZooKeeper의 퇴장
    • ZooKeeper 시대의 문제
    • KRaft 모드의 동작
    • KRaft의 장점
  • 브로커, 파티션, 레플리카
    • Broker (브로커)
    • 레플리케이션
    • ISR (In-Sync Replicas)
  • 프로듀서와 전송 보장
    • acks 설정
    • acks와 min.insync.replicas의 조합
  • 컨슈머 그룹
    • 컨슈머 그룹의 개념
    • 리밸런싱
    • Cooperative Rebalancing (협력적 리밸런싱)
  • Kafka의 성능 특성
    • 순차 I/O
    • Zero-Copy 전송
    • 페이지 캐시 활용
    • 배치 처리
    • 압축
  • 정리
  • 다음 장 미리보기