학습 목표

버전 표기 읽는 법

Apache 아카이브의 4.3.1 디렉터리에는 배포 파일이 하나만 올라와 있습니다. kafka_2.13-4.3.1.tgz입니다. 이 한 줄에 버전 번호가 두 개 들어 있어서 오해가 끊이지 않습니다.

배포 파일명 분해
kafka_2.13-4.3.1.tgz
      ────  ─────
      Scala  Kafka
      2.13   4.3.1
Kafka 배포 파일명 분해 — kafka_2.13-4.3.1.tgz 의 2.13 은 Scala 버전 배포 파일명 kafka_2.13-4.3.1.tgz 를 두 부분으로 분해합니다. 밑줄 뒤의 2.13 은 브로커를 컴파일한 Scala 버전이며 Kafka 4.x 는 Scala 2.13 배포판만 제공합니다. Scala 2.12 지원은 4.0 에서 제거되었습니다. 하이픈 뒤의 4.3.1 이 Apache Kafka 버전으로 major 4, minor 3, patch 1 이며 설정 기본값과 CLI, API 는 이 번호를 기준으로 봅니다. 아래 경고 상자는 Kafka 2.13 이라는 버전이 존재하지 않는다는 점을 알려 줍니다. Kafka 의 minor 버전은 2.8 다음이 3.0 이므로 2.9 부터 2.13 까지는 아예 없습니다. 맨 아래에는 2.6, 2.7, 2.8, 3.0 을 지나 3.9, 4.0, 4.3 으로 이어지는 실제 버전 흐름이 표시되어 있습니다. Kafka 버전 표기 읽는 법 — 2.13 은 Kafka 버전이 아닙니다 kafka _2.13 -4.3.1 .tgz 2.13 = Scala 버전 브로커를 컴파일한 Scala 의 버전입니다. Kafka 4.x 는 Scala 2.13 배포판만 제공합니다 (2.12 지원은 4.0 에서 제거). 4.3.1 = Apache Kafka 버전 major 4 · minor 3 · patch 1. 설정 기본값 · CLI · API 는 모두 이 번호를 기준으로 봅니다. Kafka 2.13 이라는 버전은 존재하지 않습니다. Kafka 의 minor 버전은 2.8 다음이 3.0 입니다 — 2.9 부터 2.13 까지는 아예 없습니다. 실제 Kafka 버전의 흐름 2.6 2.7 2.8 3.0 3.9 4.0 4.3 2.8 다음이 3.0 — 여기서 minor 번호가 건너뜁니다. Scala 버전(2.13)과는 아무 관계가 없습니다. Scala 를 직접 쓰지 않는다면 _2.13 배포판을 그대로 고르면 됩니다. 브로커 실행에는 Java 만 필요합니다.
버전 표기 분해 — kafka_2.13-4.3.1.tgz의 각 부분이 Scala 버전과 Kafka 버전 중 무엇을 의미하는지 지시선으로 분해
배포 파일명에서 마주치는 표기들
표기의미
kafka_2.13Scala 2.13으로 컴파일된 배포판. 현행 Kafka가 제공하는 유일한 Scala 버전입니다
-4.3.1Apache Kafka 버전
_2.12Scala 2.12 빌드. 3.9까지 함께 배포되었고 Scala 2.12 지원은 Kafka 4.0에서 제거되었습니다(KIP-751)
_2.11더 오래된 배포판. 2.0에는 있었고 2.8 배포에서는 이미 사라졌습니다 (아카이브 확인)
kafka-4.3.1-src.tgz소스 배포판. Scala 접두어가 없습니다 — 접두어 유무로 바이너리/소스를 구분할 수 있습니다

무엇을 내려받아야 하는가

상황별 선택
하려는 일필요한 것
브로커·컨트롤러 운영, CLI 도구 사용kafka_2.13-4.3.1.tgz (바이너리 배포판). Java 17 이상이 필요합니다
Java/Kotlin 애플리케이션에서 produce·consumeMaven/Gradle 의존성 org.apache.kafka:kafka-clients:4.3.1. Scala 접두어가 없습니다
Kafka Streams 애플리케이션org.apache.kafka:kafka-streams:4.3.1. 테스트에는 kafka-streams-test-utils(10장)
Scala DSL로 Streams 작성org.apache.kafka:kafka-streams-scala_2.13 — 여기가 Scala 접두어가 필요한 드문 경우입니다. 4.3에서 deprecated
소스 빌드kafka-4.3.1-src.tgz

버전별 주요 변경 타임라인 (2.0 → 4.3)

Kafka 버전 타임라인 — 2.4 부터 4.3 까지의 주요 변경 가로 타임라인을 세 시대로 나눕니다. 2.4 부터 3.0 까지는 ZooKeeper 시대, 3.3 부터 3.9 까지는 KRaft 와 ZooKeeper 공존기, 4.0 부터는 KRaft 전용입니다. 2.4 에서 기본 파티셔너가 sticky 방식으로 바뀌고 증분 협력적 리밸런스와 CooperativeStickyAssignor 가 도입되었습니다. 2.8 에서 KRaft 가 early access 로 처음 등장했습니다. 3.0 에서 acks 기본값이 1 에서 all 로, enable.idempotence 가 true 로 바뀌고 session.timeout.ms 가 10초에서 45초로 늘었습니다. 3.3 에서 KRaft 가 신규 클러스터에 대해 production ready 가 되었고 4.x 로 올리려면 최소 이 버전을 거쳐야 합니다. 3.6 에서 Tiered Storage 가 early access 로 들어오고 3.9 에서 production ready 가 되었으며 3.9 가 ZooKeeper 에서 KRaft 로 가는 마지막 브리지 릴리스입니다. 4.0 에서 ZooKeeper 모드가 제거되고 KIP-848 이 GA 되었으며 linger.ms 기본값이 0 에서 5 로 바뀌고 Scala 2.12 와 Java 8 지원이 사라졌습니다. 4.2 에서 share groups 와 Streams 리밸런스 프로토콜이 production-ready 가 되었고 4.3 이 이 사이트의 기준 버전입니다. Kafka 버전 타임라인 — 시험과 운영에 실제로 영향을 준 변경만 ZooKeeper 시대 KRaft·ZK 공존기 KRaft 전용 2.4 2.8 3.0 3.3 3.6 3.9 4.0 4.2 4.3 2.4 DefaultPartitioner 가 sticky 파티셔닝으로 바뀌고, 증분 협력적 리밸런스와 CooperativeStickyAssignor 가 도입되었습니다 (KIP-429). 2.8 KRaft 모드가 early access 로 처음 등장했습니다 (KIP-500). 운영에는 쓸 수 없는 단계였습니다. 3.0 acks 기본값이 1 에서 all 로, enable.idempotence 가 true 로 바뀌었습니다. session.timeout.ms 는 10초에서 45초로 늘었습니다. 3.3 KRaft 가 신규 클러스터에 대해 production ready 가 되었습니다 (3.3.1). 4.x 로 올리려면 최소 이 버전을 거쳐야 합니다. 3.6 Tiered Storage 가 early access 로 들어왔습니다 (KIP-405). 3.9 Tiered Storage 가 production ready 가 되었고, 이 버전이 ZooKeeper→KRaft 마이그레이션을 위한 마지막 브리지 릴리스입니다. 4.0 ZooKeeper 모드가 제거되고 KIP-848 컨슈머 리밸런스 프로토콜이 GA 되었습니다. linger.ms 기본값이 0 에서 5 로 바뀌고 Scala 2.12 배포와 Java 8 지원이 사라졌습니다. 4.2 Queues for Kafka(share groups, KIP-932)가 production-ready 가 되었고 Streams 리밸런스 프로토콜(KIP-1071)도 production-ready 가 되었습니다. 4.3 이 사이트의 기준 버전입니다. 업그레이드는 3.3.x 이상에서만 가능하고 KRaft 가 필수입니다. 각 항목은 Apache Kafka 4.3.1 · 3.9.0 공식 문서(site-docs)로 확인했습니다. 2.8 의 KRaft early access 만 웹 검색으로 확인했습니다.
버전 타임라인 — 2.0부터 4.3까지 KRaft 성숙, 프로듀서 기본값 변경, 리밸런스 프로토콜 세대 교체, Tiered Storage, Share Groups가 어느 버전에 놓이는지 가로 타임라인
주요 변경 타임라인. 4.x 항목은 Apache Kafka 4.3 업그레이드 문서에서 직접 확인했고, 3.x 이하는 공식 릴리스 발표와 KIP으로 교차 확인했습니다.
버전 시기 이 버전에서 바뀐 것
2.0 2018-07 이 표의 출발점. SASL/OAUTHBEARER 지원이 이 버전에서 시작됩니다. ZooKeeper가 필수인 시대입니다
2.4 2019-12 증분 협력적 리밸런스(KIP-429)와 CooperativeStickyAssignor 도입. 다만 기본값은 여전히 eager 프로토콜이라, 쓰려면 명시해야 했습니다. sticky 파티셔너(KIP-480)도 이 버전입니다 — 키 없는 메시지의 분배 방식이 여기서 바뀝니다(4장)
2.8 2021-04 KRaft early access (KIP-500). ZooKeeper 없이 돌려 볼 수 있게 되었지만 구현이 미완이라 프로덕션 금지였습니다. Kafka Streams는 이 버전부터 스트림 스레드를 동적으로 추가·제거할 수 있습니다
3.0 2021-09 프로듀서 기본값이 가장 강한 보장으로 바뀝니다(KIP-679)acks=1all, enable.idempotence=falsetrue. 컨슈머 partition.assignment.strategy 기본값도 RangeAssignor[RangeAssignor, CooperativeStickyAssignor]로 바뀝니다(KIP-726). 관리 도구에서 --zookeeper 플래그가 제거됩니다(KIP-604). Kafka Streams의 1세대 exactly_once가 deprecated됩니다
3.3 2022-09 KRaft가 신규 클러스터에 대해 production-ready (KIP-833). 4.3 업그레이드 문서가 "KRaft 모드가 production ready로 판정된 첫 버전"이라고 3.3.x를 지목하며, 그래서 4.x 업그레이드의 메타데이터 하한선이 됩니다. Kafka Connect의 source 커넥터 exactly-once도 이 버전부터입니다(9장)
3.5 2023-06 ZooKeeper → KRaft 마이그레이션의 bridge release. ZooKeeper 모드가 deprecated로 표시됩니다. Connect에 stop API가 추가됩니다(9장)
3.6 2023-10 Tiered Storage early access (KIP-405) — 프로덕션 권장은 아니었습니다. Connect의 plugin.discovery가 설정 가능해지고 기본값이 hybrid_warn이 됩니다
3.9 2024-11 ZooKeeper 모드를 지원하는 마지막 릴리스. Tiered Storage가 production-ready가 되고, 동적 KRaft 쿼럼(KIP-853)이 들어옵니다. 4.x로 가는 모든 레거시 클러스터의 경유지입니다 — 4.3 업그레이드 문서가 3.3.x보다 오래된 KRaft 클러스터에 대해 "3.9.x로 먼저 올릴 것을 권장"합니다
4.0 2025-03 ZooKeeper 모드 완전 제거. KRaft만 지원합니다. KIP-848 새 컨슈머 리밸런스 프로토콜 GA(서버 쪽은 4.0 확정 시 자동 활성, 클라이언트 group.protocol 기본값은 여전히 classic). 새 그룹 코디네이터 구현, KIP-890 트랜잭션 서버 사이드 방어, Eligible Leader Replicas(KIP-966 part 1). linger.ms 기본값 05. Scala 2.12 지원 제거(KIP-751), Java 8 제거 — clients·streams는 Java 11+, 브로커·Connect·tools는 Java 17+(KIP-750·KIP-1013). Log4j → Log4j2 전환. DefaultPartitioner·UniformStickyPartitioner 제거. segment.bytes 최소값 14바이트 → 1MB, num.recovery.threads.per.data.dir 1 → 2, message.timestamp.after.max.ms Long.MAX1시간(KIP-1030)
4.1 2025-09 Queues for Kafka (KIP-932) preview. kafka-features.shshare.version=1을 명시해야 켰습니다. Streams Rebalance Protocol(KIP-1071) Early Access — 기본 비활성, 프로덕션 금지. ELR이 신규 클러스터에서 기본 활성. log.cleaner.enable deprecated. 프로듀서 flush()가 콜백 안에서의 호출을 금지하고 데드락을 감지합니다
4.2 2026-02 Queues for Kafka (KIP-932) production-ready. RENEW ack 타입이 추가됩니다(11장). Streams Rebalance Protocol(KIP-1071)도 핵심 기능 집합이 production-ready — 단 4.2.0의 오프라인 마이그레이션 버그(KAFKA-20254) 때문에 마이그레이션은 4.2.1에서 해야 합니다. Connect의 connector.client.config.override.policyAllowlist가 추가되고 권장 설정이 됩니다. controller.quorum.auto.join.enable 추가(KIP-853). KafkaPrincipalBuilderKafkaPrincipalSerde를 상속하도록 변경(KIP-1157)
4.3 2026-05 현행 기준 버전. kafka-streams-scala deprecated(5.0에서 제거 예정). Kafka Streams에 headers-aware 상태 저장소(dsl.store.format, KIP-1285). 로그 디렉터리 cordoning(KIP-1066). group.coordinator.rebalance.protocols deprecated — 5.0부터 feature version(group.version·streams.version·share.version)으로만 제어(KIP-1237). share group 설정 3종 추가(KIP-1240). remote.log.metadata.topic.min.isr 신설(기본 2, KIP-1235). tiered storage 팔로워 부트스트랩 최적화 follower.fetch.last.tiered.offset.enable(기본 false, KIP-1023). 동적 쿼럼 컨트롤러의 동적 설정 변경 지원

Kafka 2.x / 3.x를 아직 쓰는 조직을 위한 안내

ZooKeeper 앙상블 구성

ZooKeeper는 과반수 기반 합의를 쓰므로 앙상블 크기를 홀수로 두는 것이 관례였습니다. 3대면 1대 장애, 5대면 2대 장애를 견딥니다. 운영 관점의 핵심은 Kafka 브로커와 ZooKeeper 노드를 같은 머신에 두지 않는 것ZooKeeper의 트랜잭션 로그를 별도 디스크에 두는 것이었습니다 — ZooKeeper는 쓰기마다 fsync를 하므로 디스크 지연에 매우 민감했습니다.

"두 개의 분산 시스템을 함께 운영해야 한다"는 부담이 KIP-500(ZooKeeper 제거)의 출발점이었습니다. Kafka를 운영하려면 Kafka와 ZooKeeper 양쪽의 튜닝·모니터링·보안·업그레이드를 모두 알아야 했습니다.

ZooKeeper에 저장되던 것들

ZooKeeper 시대에 ZooKeeper가 보관했던 상태와, 4.x에서 그것이 어디로 갔는지
저장 대상ZooKeeper 시대4.x (KRaft)
브로커 등록·생존 브로커가 ZooKeeper에 ephemeral 노드로 자신을 등록. 세션이 끊기면 노드가 사라져 이탈로 판정 브로커가 컨트롤러에 주기적 하트비트를 보냅니다. broker.session.timeout.ms 안에 도착하지 않으면 오프라인 처리
브로커 ID 생성 broker.id.generation.enable·reserved.broker.max.id로 ZooKeeper가 자동 생성 제거됨. node.id로 서버를 식별합니다
컨트롤러 선출 ZooKeeper 노드 생성 경쟁으로 컨트롤러 한 대를 뽑음. 컨트롤러 페일오버 시 메타데이터 전체를 ZooKeeper에서 다시 읽어야 했고 클러스터가 클수록 오래 걸렸습니다 컨트롤러 쿼럼이 Raft로 합의합니다. 메타데이터가 __cluster_metadata 로그에 있어 페일오버가 빠릅니다(3장)
토픽 메타데이터·토픽 설정 ZooKeeper znode 메타데이터 로그
ACL ZooKeeper znode (AclAuthorizer) 클러스터 메타데이터 로그 (StandardAuthorizer, 11장)
동적 브로커 설정 ZooKeeper znode. 민감 값은 password.encoder.* 설정으로 암호화해 저장 메타데이터 레코드. password.encoder.* 설정 6개는 제거되었고, KRaft는 민감 데이터를 레코드에 암호화하지 않고 저장합니다
쿼터·SCRAM 자격증명 ZooKeeper znode 메타데이터 레코드 (kafka-configs.sh로 동일하게 관리)
컨슈머 오프셋 0.9 이전에는 ZooKeeper, 이후 __consumer_offsets 토픽 __consumer_offsets 토픽 (변화 없음)

--zookeeper CLI의 시대

2.x 자료를 보면 아래와 같은 명령이 흔히 나옵니다. 이 명령들은 현행 Kafka에서 동작하지 않습니다. 관리 도구의 --zookeeper 플래그는 KIP-555로 deprecated되고 Kafka 3.0에서 제거되었습니다(KIP-604).

Kafka 2.x 시절 — ZooKeeper에 직접 접속해 메타데이터를 고쳤습니다. 클라이언트가 브로커를 거치지 않으므로 ACL·인증을 우회하는 문제도 있었습니다.

2.x 명령 (현행에서는 동작하지 않습니다)
bin/kafka-topics.sh --zookeeper localhost:2181 \
  --create --topic orders --partitions 6 --replication-factor 3

bin/kafka-topics.sh --zookeeper localhost:2181 --list

bin/kafka-configs.sh --zookeeper localhost:2181 \
  --entity-type topics --entity-name orders --describe

bin/kafka-acls.sh \
  --authorizer-properties zookeeper.connect=localhost:2181 --list

Kafka 4.x — 모든 관리 요청이 브로커(또는 컨트롤러)를 거칩니다. 인증·인가가 일관되게 적용되고, 클라이언트가 알아야 할 엔드포인트가 하나로 줄었습니다.

4.x 명령
bin/kafka-topics.sh --bootstrap-server localhost:9092 \
  --create --topic orders --partitions 6 --replication-factor 3

bin/kafka-topics.sh --bootstrap-server localhost:9092 --list

bin/kafka-configs.sh --bootstrap-server localhost:9092 \
  --entity-type topics --entity-name orders --describe

bin/kafka-acls.sh --bootstrap-server localhost:9092 --list

4.0에서는 남아 있던 ZooKeeper 흔적까지 정리되었습니다 — kafka-acls--authorizer·--authorizer-properties·--zk-tls-config-file 옵션이 제거되고 --bootstrap-server 또는 --bootstrap-controller를 쓰게 되었으며, kafka.admin.ZkSecurityMigrator 도구도 제거되었습니다. 또한 KRaft 모드용 설정 파일이 별도의 config/kraft 디렉터리에 있던 관행도 끝나 모든 설정 파일이 config 디렉터리로 통합되었습니다.

ZooKeeper 시대의 흔한 장애

어떤 장애가 잦았는지는 Kafka가 그 시절 어떤 메트릭을 노출했는지를 보면 드러납니다. 아래 메트릭들은 모두 4.x에서 제거되었지만, 그 이름이 곧 당시의 걱정거리 목록입니다.

ZooKeeper 시대의 장애 유형과 그것을 감시했던 메트릭 (모두 4.x에서 제거됨)
장애무슨 일이 일어나는가당시의 메트릭
ZooKeeper 세션 만료 GC 정지, 네트워크 순단, ZooKeeper 과부하로 브로커의 ZooKeeper 세션이 만료됩니다. 브로커는 살아 있는데 클러스터에서 이탈한 것으로 처리되어 리더 선출과 ISR 축소가 연쇄로 일어납니다. zookeeper.session.timeout.ms가 너무 짧으면 이 현상이 잦아졌습니다 SessionExpireListener.ZooKeeperExpiresPerSec, SessionExpireListener.SessionState
ZooKeeper 연결 끊김 세션 만료까지 가지 않아도 재연결이 반복되면 메타데이터 갱신이 지연되고 컨트롤러 동작이 불안정해졌습니다 SessionExpireListener.ZooKeeperDisconnectsPerSec, SessionExpireListener.ZooKeeperSyncConnectsPerSec
ZooKeeper 디스크 압박 ZooKeeper는 쓰기마다 트랜잭션 로그를 디스크에 sync합니다. 스냅샷·로그 정리(autopurge)가 안 되어 디스크가 차거나 디스크가 느리면 ZooKeeper 응답 지연 → 브로커 세션 위험으로 이어졌습니다 ZooKeeperClientMetrics.ZooKeeperRequestLatencyMs
인증 실패 ZooKeeper에 SASL 인증을 켠 환경에서 자격증명 문제로 브로커가 ZooKeeper에 붙지 못했습니다 SessionExpireListener.ZooKeeperAuthFailuresPerSec
컨트롤러 이슈 · split-brain 우려 컨트롤러 페일오버 시 메타데이터 전체를 ZooKeeper에서 다시 읽어야 했으므로 파티션이 많은 클러스터에서 페일오버가 오래 걸렸고, 그 사이 파티션이 오프라인으로 남았습니다. 옛 컨트롤러가 자신이 여전히 컨트롤러라고 믿는 상황(zombie controller)을 컨트롤러 epoch로 걸러 내야 했습니다 ControllerStats.ControllerChangeRateAndTimeMs, ControllerStats.ControllerShutdownRateAndTimeMs, KafkaController.ControllerState
마이그레이션 상태 추적 ZooKeeper → KRaft 마이그레이션 중에는 브로커가 어느 단계에 있는지 확인해야 했습니다 KafkaController.ZkMigrationState, KafkaController.MigratingZkBrokerCount

업그레이드 경로 — 2.x → 3.9 → 4.x

4.3 업그레이드 경로 — 이미 KRaft, 낮은 KRaft, ZooKeeper 모드의 세 가지 경우 경로 A 는 이미 KRaft 이고 버전이 3.3.x 에서 4.2.x 사이인 경우로, 브로커를 한 대씩 롤링 재시작해 소프트웨어를 올린 뒤 동작과 성능을 확인하고 마지막에 kafka-features.sh upgrade --release-version 4.3 으로 메타데이터 버전을 올립니다. 4.3 은 메타데이터 변경이 있어 이 단계 뒤에는 다운그레이드가 불가능합니다. 경로 B 는 KRaft 이지만 3.3.x 보다 낮은 경우로 공식 문서는 3.9.x 를 먼저 거치도록 권합니다. 소프트웨어뿐 아니라 메타데이터 버전도 최소 3.3 이어야 합니다. 경로 C 는 아직 ZooKeeper 모드인 경우로 3.9 로 올린 뒤 KRaft 컨트롤러 쿼럼을 띄우고 zookeeper.metadata.migration.enable 을 true 로 두어 마이그레이션을 완료해야 합니다. 3.9 가 마지막 브리지 릴리스이므로 여기서 끝내야 하며 4.0 이상에는 ZooKeeper 경로가 없습니다. 공통 원칙으로 클라이언트를 브로커보다 먼저 올리지 않으며 4.0 이후 브로커는 2.1 이상 클라이언트만 지원합니다. 4.3 으로 가는 업그레이드 경로 — 지금 상태에 따라 셋 중 하나입니다 A. 이미 KRaft · 3.3.x ~ 4.2.x 현재 클러스터 브로커 롤링 재시작 동작·성능 확인 kafka-features.sh upgrade 소프트웨어를 한 대씩 올린 뒤 마지막에 메타데이터 버전을 올립니다. bin/kafka-features.sh --bootstrap-server :9092 upgrade --release-version 4.3 4.3 은 메타데이터 변경이 있어 이 단계 뒤에는 다운그레이드가 불가능합니다. B. KRaft 이지만 3.3.x 보다 낮음 현재 클러스터 3.9.x 로 먼저 4.3 롤링 업그레이드 kafka-features.sh upgrade 공식 문서는 3.3.x 미만 KRaft 클러스터는 3.9.x 를 경유하도록 권합니다. 메타데이터 버전도 최소 3.3 이어야 합니다 — 소프트웨어만 올려서는 부족합니다. C. 아직 ZooKeeper 모드 ZK 모드 클러스터 3.9 로 업그레이드 KRaft 마이그레이션 4.3 롤링 업그레이드 3.9 가 마지막 브리지 릴리스이므로 여기서 마이그레이션을 끝내야 합니다. KRaft 컨트롤러 쿼럼을 먼저 띄우고 zookeeper.metadata.migration.enable=true 로 시작합니다 마이그레이션이 끝난 뒤에야 4.x 로 올릴 수 있습니다. 4.0 이상에는 ZooKeeper 경로가 없습니다. 공통 원칙: 클라이언트는 브로커보다 먼저 올리지 않습니다. 4.0 이후 브로커는 2.1 이상 클라이언트만 지원합니다. 메타데이터 버전을 올리는 마지막 단계는 되돌릴 수 없는 경우가 많습니다 — 충분히 관찰한 뒤 실행합니다.
업그레이드 경로 — 2.x에서 4.x까지 3.9를 경유하는 흐름과, ZooKeeper 모드 클러스터가 KRaft로 마이그레이션되는 지점

왜 3.9를 경유해야 하는가

4.3 업그레이드 문서의 서술을 정리하면 이유가 세 겹입니다.

  1. 4.x는 KRaft만 지원합니다. 문서는 "ZooKeeper 모드 클러스터는 4.3.x로 업그레이드하기 전에 반드시 KRaft로 마이그레이션되어야 한다"고 명시합니다. 그리고 ZooKeeper → KRaft 마이그레이션 기능이 있는 마지막 버전이 3.9입니다. 4.0 이후에는 마이그레이션 경로 자체가 없습니다.
  2. 4.x 브로커 업그레이드는 소프트웨어·메타데이터 버전이 최소 3.3.x여야 합니다. 문서는 이를 "KRaft 모드가 production ready로 판정된 첫 버전"이라는 이유로 설명합니다. 3.3.x보다 오래된 KRaft 클러스터에는 3.9.x로 먼저 올리는 것을 권장합니다.
  3. 클라이언트는 4.0 이전에 2.1 이상이어야 합니다. 4.0에서 오래된 프로토콜 API 버전이 제거되었기 때문입니다(KIP-896). Connect와 Kafka Streams도 내부적으로 클라이언트를 쓰므로 함께 해당됩니다.

단계별 절차

레거시 클러스터를 4.3으로 올리는 큰 흐름
단계무엇을 하는가확인 사항
① 클라이언트 정비 모든 프로듀서·컨슈머·Connect·Streams 클라이언트를 최소 2.1 이상으로 올립니다. 가능하면 더 최신으로 4.0에서 제거된 API를 쓰고 있지 않은지. Apache Kafka 외부의 서드파티 클라이언트도 KIP-896을 확인해야 합니다
② 3.9로 롤링 업그레이드 (ZooKeeper 모드 유지) 브로커를 하나씩 3.9로 교체합니다. 아직 ZooKeeper 모드입니다 ZooKeeper 모드에서는 inter.broker.protocol.version단계적으로 상향합니다 — 먼저 모든 브로커의 바이너리를 교체하고, 전부 정상 동작을 확인한 뒤 이 값을 올려 다시 롤링합니다
③ ZooKeeper → KRaft 마이그레이션 (3.9에서) KRaft 컨트롤러 쿼럼을 구성하고 브로커를 마이그레이션 모드로 전환한 뒤, 메타데이터를 KRaft로 옮기고 ZooKeeper 의존을 끊습니다 3.9의 공식 마이그레이션 문서를 그대로 따르세요. 컨트롤러 수는 3 또는 5(3장). KafkaController.ZkMigrationState 메트릭으로 진행을 확인합니다
④ 4.x로 롤링 업그레이드 브로커를 하나씩 정지 → 코드 교체 → 재시작합니다. 이 시점에는 이미 KRaft 모드입니다 UnderReplicatedPartitions가 0으로 돌아온 뒤 다음 브로커로 넘어가세요(11장)
⑤ 업그레이드 확정 bin/kafka-features.sh --bootstrap-server localhost:9092 upgrade --release-version 4.3 되돌릴 수 없습니다. 클러스터 동작·성능을 먼저 충분히 검증하세요
⑥ 설정·기본값 정리 제거된 ZooKeeper 관련 설정을 지우고, 바뀐 기본값이 의도와 맞는지 확인합니다 linger.ms 5, acks all, enable.idempotence true, num.recovery.threads.per.data.dir 2, message.timestamp.after.max.ms 1시간, segment.bytes 최소 1MB
⑦ 신기능 선택 적용 KIP-848 컨슈머 프로토콜, Share Groups, Streams Rebalance Protocol을 필요에 따라 켭니다 모두 클라이언트 쪽 기본값이 아닙니다. group.protocol=consumer(5장), share.version=1·group.protocol=streams(11장·10장)
4.x 롤링 업그레이드 — 공식 문서의 3단계
# 1. 브로커를 하나씩: 정지 → 코드 교체 → 재시작
#    전부 끝나면 클러스터 동작과 성능이 기대와 맞는지 검증합니다.

# 2. 검증이 끝나면 업그레이드를 확정합니다 (되돌릴 수 없습니다)
bin/kafka-features.sh --bootstrap-server localhost:9092 \
  upgrade --release-version 4.3

# 3. 현재 feature 레벨 확인
bin/kafka-features.sh --bootstrap-server localhost:9092 describe

# (참고) 4.x 에서는 inter.broker.protocol.version 이 아니라
#        metadata.version 을 feature 로 관리합니다.

레거시 → 현행 대응표

옛 자료나 사내 위키에서 아래 왼쪽 항목을 만나면 오른쪽으로 옮겨 읽으세요.

명령·설정·개념의 대응 관계
레거시 (2.x / 3.x)현행 (4.3)비고
--zookeeper localhost:2181 --bootstrap-server localhost:9092 관리 도구에서 3.0에 제거(KIP-604). 컨트롤러를 직접 겨냥해야 하면 --bootstrap-controller
zookeeper.connect=… controller.quorum.bootstrap.servers (또는 정적 쿼럼이면 controller.quorum.voters) 브로커가 컨트롤러를 찾는 방법입니다(3장)
broker.id 자동 생성 node.id 명시 broker.id.generation.enable·reserved.broker.max.id가 제거되었습니다
inter.broker.protocol.version 단계적 상향 bin/kafka-features.sh upgrade --release-version X.Y KRaft에서는 metadata.version이 클러스터 기능 레벨을 제어합니다
log.message.format.version / message.format.version (없음) 4.0에서 제거되었습니다
control.plane.listener.name controller.listener.names + listeners + listener.security.protocol.map KRaft에서는 컨트롤 플레인이 Kafka 자체에 통합되었습니다(11장)
kafka.security.authorizer.AclAuthorizer org.apache.kafka.metadata.authorizer.StandardAuthorizer ACL이 ZooKeeper가 아니라 메타데이터 로그에 저장됩니다
kafka-acls.sh --authorizer-properties zookeeper.connect=… kafka-acls.sh --bootstrap-server … --authorizer·--authorizer-properties·--zk-tls-config-file4.0에서 제거
kafka.admin.ZkSecurityMigrator (없음) 4.0에서 제거
config/kraft/server.properties config/server.properties ZooKeeper 제거로 설정 파일이 config로 통합되었습니다
password.encoder.* (없음) KRaft는 민감 데이터를 레코드로 저장하며 암호화하지 않습니다
DefaultPartitioner / UniformStickyPartitioner (클래스 제거 — 기본 파티셔너 동작이 내장) 4.0에서 제거. 커스텀 파티셔너는 Partitioner 구현으로(4장)
Partitioner.onNewBatch() (없음) 4.0에서 제거
NotLeaderForPartitionException NotLeaderOrFollowerException 4.0에서 클래스 제거. 재시도 가능한 예외입니다(4장)
consumer.poll(long) consumer.poll(Duration) 4.0에서 제거. 동작이 다릅니다 — poll(Duration)은 파티션 배정을 기다리며 타임아웃을 넘기지 않습니다
Admin.alterConfigs() Admin.incrementalAlterConfigs() 4.0에서 제거. kafka-configs.sh도 내부적으로 후자를 씁니다
MirrorMaker 1 (kafka-mirror-maker.sh) MirrorMaker 2 (Connect 기반) 4.0에서 MM1과 관련 클래스가 제거되었습니다
--whitelist / --blacklist 계열 옵션 --include / --exclude 계열 예: kafka-console-consumer--whitelist--include. MirrorMaker의 topics.blacklisttopics.exclude
Log4j 1 설정 (log4j.properties) Log4j2 설정 (log4j2.yaml) 4.0에서 Log4j2로 전환. KafkaLog4jAppender도 제거되었습니다
브로커 로그 레벨을 재시작으로 변경 kafka-configs.sh --entity-type broker-loggers --alter --add-config … 컨트롤러 대상이면 --bootstrap-controller를 쓰고, --entity-type은 그래도 broker-loggers입니다
ControlPlaneNetworkProcessorAvgIdlePercent NetworkProcessorAvgIdlePercent ZooKeeper 시대의 control plane 전용 메트릭이 제거되었습니다(11장)
Admin.listConsumerGroups() Admin.listGroups(ListGroupsOptions.forConsumerGroups()) 4.1에서 deprecated. share group·streams group이 생겨 그룹 종류가 늘었기 때문입니다
ConsumerGroupState GroupState 4.0에서 deprecated. 모든 그룹 종류에 적용됩니다

버전 병기 항목 — 트랙별 값

본문에서 .note--version으로 병기하는 항목들을 한 표에 모았습니다. 기억에 의존해 3.x 기준으로 답하면 틀리는 항목들입니다.

버전 트랙별 값 비교. 4.x 열은 Apache Kafka 4.3 문서·소스에서 직접 확인했습니다.
항목 2.x (2.0~2.8) 3.x (3.0~3.9) 4.x (4.3 현행)
메타데이터 저장소 ZooKeeper (필수) ZooKeeper / KRaft 공존. 3.3부터 KRaft production-ready, 3.9가 마지막 ZooKeeper 지원 KRaft 전용
enable.idempotence 기본값 false 3.0부터 true (단 3.0.0·3.1.0은 버그로 미적용, 3.0.1·3.1.1·3.2.0에서 수정) true
acks 기본값 1 3.0부터 all all
linger.ms 기본값 0 0 5 (4.0에서 변경)
컨슈머 리밸런스 프로토콜 eager 중심. 2.4에 cooperative 도입(KIP-429)이나 기본값은 아님 cooperative 확산 KIP-848 GA (4.0). 단 클라이언트 group.protocol 기본값은 여전히 classic
파티션 할당 기본 전략
(partition.assignment.strategy)
RangeAssignor 3.0부터 [RangeAssignor, CooperativeStickyAssignor] (KIP-726) [RangeAssignor, CooperativeStickyAssignor]
--zookeeper CLI 옵션 사용. 후반에 deprecated (KIP-555) 3.0에서 관리 도구에서 제거 (KIP-604) 존재하지 않습니다. kafka-acls의 ZooKeeper 잔여 옵션과 ZkSecurityMigrator도 4.0에서 제거
Queues / Share Groups (KIP-932) 없음 없음 4.1 preview → 4.2 production-ready
Streams Rebalance Protocol (KIP-1071) 없음 없음 4.1 Early Access → 4.2 production-ready (신규 4.2+ 클러스터는 브로커 쪽 기본 활성, 클라이언트 기본값은 classic)
Tiered Storage (KIP-405) 없음 3.6 early access → 3.9 production-ready 지원
Java 최소·지원 버전 8 8 / 11 Java 17 · 21 · 25 완전 지원. Java 11은 clients·streams 등 일부 모듈만. Java 8은 4.0에서 제거되었고 브로커·Connect·tools는 17 이상
Scala 배포판 2.0은 2.11 / 2.12. 2.4에 2.13이 추가되고(2.11/2.12/2.13 셋), 2.8에서 2.11이 사라져 2.12/2.13 2.12 / 2.13 (3.0~3.9 전부) kafka_2.13-4.3.1.tgz 단일. Scala 2.12 지원은 4.0에서 제거(KIP-751)
Kafka Streams EOS 설정값 exactly_once 2.6에 exactly_once_v2(KIP-447), 3.0에서 exactly_once deprecated at_least_once(기본) 또는 exactly_once_v2
Connect exactly-once sink만 (0.11.0부터) 3.3.0부터 source도 지원 (distributed 모드 전용) 동일. exactly.once.source.support 기본값은 disabled
Connect 리밸런스 프로토콜 2.3.0부터 증분 협력적이 기본 (그 이전은 전량 재배치) 동일 connect.protocol 기본값 sessioned. eager로 옛 동작 복귀 가능

확인 문제

버전 표기와 타임라인을 확인하는 문항입니다. 실무 이관에서 자주 걸리는 지점이자, 시험에서도 버전 차이를 직접 묻는 문항이 나옵니다.

공식 문서 출처

타임라인의 각 항목은 아래에서 확인했습니다. 4.x 항목은 Apache Kafka 4.3 업그레이드 문서에 직접 기재된 내용이고, 3.x 이하는 공식 릴리스 발표와 KIP으로 교차 확인했습니다.