개발이군고구마

[Kafka/Redis] Kafka 개념 본문

SERVER/Kafka

[Kafka/Redis] Kafka 개념

김구황 2026. 2. 3. 08:09
728x90
1주차 - Kafka 개념
2주차 - Kafka 설치
3주차 - Kafka와 Spring
4주차 - Kafka 메트릭
5주차 - Redis 개념
6주차 - Kafka/Redis를 활용한 실시간 트랜잭션 집계 서비스 

 

1) Kafka는 무엇을 해결하려고 만들어졌나

Kafka는 “이벤트(사실/변화/로그)”가 계속 발생하는 시스템에서, 그 이벤트를

- 지속적으로 저장하고

- 여러 소비자가 각자 필요한 방식으로 읽어 가게 해주는

- 분산 이벤트 스트리밍 플랫폼이다.

카프카의 주요 기능

즉, 단순 메시지 큐를 넘어서

  • (1) 오래 보관되는 로그 
  • (2) 여러 소비자가 독립적으로 읽는 구조 
  • (3) 높은 처리량/확장성 을 목표로 한다.

Kafka의 토픽(topic)은 “테이블”이라기보다 **끝없이 append 되는 로그(신문 연재/거래 원장)**에 가깝다.

소비자는 “마지막으로 읽은 지점(오프셋)”만 기억하면 된다.

 

 

2) Kafka의 데이터 모델: Topic → Partition → Log(세그먼트) → Offset

2-1. Topic: 이벤트가 모이는 논리적 통로

  • Topic: 이벤트를 분류하는 논리 단위(주문, 결제, 클릭로그 등).
  • 한 Topic은 보통 여러 Partition으로 나뉜다(확장/병렬 처리 목적).

2-2. Partition: Kafka 확장성의 핵심(병렬 처리 단위)

  • Partition은 “append-only 로그”다. 메시지는 뒤에만 계속 붙고(append), 중간 수정은 없다.
  • Topic의 처리량은 결국 Partition 수로 스케일된다(프로듀서/컨슈머 병렬화).

 

2-3. Offset: “파티션 안에서의 메시지 주소”

  • Offset: 파티션 로그에서 메시지의 위치(0,1,2… 증가).
  • “전체 토픽의 전역 순서”는 보장되지 않는다. 대신 파티션 내부에서는 순서가 보장된다(같은 파티션에 들어간 것들끼리).
    → 그래서 “순서가 중요한 이벤트”는 **같은 키(key)**로 같은 파티션에 들어가게 설계하는 경우가 많다.
orders-topic, partition 0:

offset 0: {"order_id": "A", "user": "김철수", "amount": 10000}
offset 1: {"order_id": "B", "user": "이영희", "amount": 20000}
offset 2: {"order_id": "C", "user": "박민수", "amount": 15000}
offset 3: {"order_id": "D", "user": "최지은", "amount": 30000}
offset 4: {"order_id": "E", "user": "정우성", "amount": 25000}

 

2-4. Segment(Log Segment): 파티션 로그의 “물리 파일 묶음”

파티션 로그는 내부적으로 하나의 거대한 파일이 아니라, 일정 크기/시간 단위로 잘린 세그먼트 파일들의 집합이다.

#file
$ls /data/kafka/kafka-log-a/test_topic-0
000000123453.index
000000123453.timeindex
000000123453.log
000007735204.index
000007735204.timeindex
000007735204.log
leader-epoch-checkpoint
  • 실제 메시지: *.log
  • 빠른 탐색용 인덱스: *.index, *.timeindex
  • 세그먼트는 시간이 지나면 “roll(새 파일로 교체)”되고, 보관 정책(retention/compaction)에 따라 삭제/정리된다.

 

 

3) Producer: 어떻게 파티션을 고르고, 왜 배치가 중요한가

3-1. Record(메시지) 구조

프로듀서가 보내는 단위는 보통 이렇게 생각하면 된다.

  • key(선택): 파티션 결정/정렬에 영향
  • value(필수): 실제 데이터(payload)
  • headers(선택), timestamp 등

Kafka는 네트워크로 보내기 위해 직렬화(serializer)가 필요하다.

 

3-2. Partitioner: 어느 파티션으로 보낼까

  • 키가 있는 경우: 일반적으로 같은 키는 같은 파티션으로 간다(순서 보장/집계 용이).
    • 메시지에 key = "k1"이 있다면
    • hash("k1") % 2 = 0 → Partition 0으로 할당
    • 메시지에 key = "k2"가 있다면
    • hash("k2") % 2 = 1 → Partition 1로 할당
    • 중요: 같은 key를 가진 메시지는 항상 같은 partition으로
  • 키가 없는 경우: 과거엔 라운드로빈 성격이 강했지만, “배치 효율”을 높이기 위해 sticky(스티키) 파티셔닝이 도입되어 기본 동작이 바뀐 흐름이 있다. KIP 문서에서도 sticky partitioner가 기본 파티셔너가 되었다고 설명한다

⚠️ 주의
“키가 같으면 반드시 같은 파티션”은 기본 파티셔너의 일반적 특성이지만, “어떤 파티셔너를 쓰는지/토픽 파티션 수가 바뀌었는지”에 따라 결과가 달라질 수 있다. 운영 중 파티션 수 변경은 키→파티션 매핑을 바꿔 순서 가정이 깨질 수 있으니 신중해야 한다.

 

3-3. Batch(배치)와 성능

Kafka 프로듀서는 보통 레코드를 모아서 배치로 전송한다.
배치가 커질수록 네트워크/IO 효율이 좋아지지만, 너무 오래 모으면 지연(latency)이 늘어난다. 그래서 linger.ms 같은 “조금 기다렸다가 묶어 보내는” 튜닝이 자주 등장한다.

카프카는 Recod 데이터를 Byte Array로 저장

 

 

4) Broker & Cluster: 확장·고가용성을 만드는 운영 단위

4-1. Broker와 Cluster

  • Broker: Kafka 서버 프로세스(데이터 읽기/쓰기, 파티션 리더/팔로워 역할 수행).
  • Cluster: 여러 Broker의 집합. 보통 장애 허용을 위해 다수 구성.
  • RF : N개의 Broker가 있으면 RF는 최대 N까지 사용하여 Topic 생성, 각 partition이 가야하는 broker 개수가 정해져있기 때문에 장애 대비를 위해 1개 더 만들어 놓는 것을 권장 

 

4-2. ZooKeeper vs KRaft(요즘 Kafka 운영에서 매우 중요)

원문에는 ZooKeeper 설명이 있지만, 최근 Kafka는 KRaft 모드로 “메타데이터/컨트롤 플레인”을 Kafka 내부로 통합하는 방향이 명확하다. KRaft 모드에서는 ZooKeeper 의존성이 제거되고, 컨트롤러(Quorum Controller)가 Raft 기반으로 메타데이터를 관리한다.

 

 

4-3) Page Cache 

브로커의 유저스페이스 힙 메모리 에 저장할 필요 없이, 다이렉트로 네트워크 버퍼에 있는 데이터를 OsPageCache로 그냥 전송할 수 있음 

Partition은 Log Segment File

 

 

 

5) Replication, ISR, HWM: “데이터를 잃지 않기”의 핵심 메커니즘

5-1. Replication(복제) 기본

각 파티션은 복제 계수(replication factor, RF)에 따라 여러 브로커에 복제된다.

  • Leader replica: 프로듀서/컨슈머가 기본적으로 읽고/쓰는 대상
  • Follower replica: 리더의 로그를 복제하며 장애 시 리더 승격 후보

 

 

 

5-2. ISR(In-Sync Replicas)와 HWM(High Watermark)

  • ISR: 리더를 충분히 따라잡고 있는 “동기화된 복제본 집합”
  • HWM: 컨슈머에게 “커밋된(committed) 데이터”로 공개 가능한 경계(대략 “ISR에 안전하게 반영된 지점”)
    → 컨슈머는 보통 “커밋된 레코드”만 읽는 흐름으로 이해하면 사고가 적다(정확한 동작은 설정/클라이언트에 따라 달라질 수 있음).

fetcher thread가 요청

주키퍼에게 ISR을 팔로우업해서 알려주고 cluster 내의 다른 Broker 정보를 모니터링 

 

 

6) acks · min.insync.replicas · unclean leader election: 내구성 vs 가용성 트레이드오프

Kafka에서 “유실 가능성/중복 가능성” 논의는 결국 아래 3개를 같이 봐야 한다.

 

6-1. acks(프로듀서 내구성 레벨)

Kafka 문서에서 acks는 “프로듀서가 성공으로 간주하기 위해 필요한 확인(acknowledgment) 수준”이라고 정의한다.

  • acks=0: 서버 응답을 기다리지 않음(가장 빠르나 유실 위험 큼)
  • acks=1: 리더에만 기록되면 성공(리더 장애 타이밍에 따라 유실 가능)
  • acks=all(-1): ISR에 충분히 복제될 때까지 기다림(가장 강한 내구성, 대신 지연/실패 가능성 증가)

6-2. min.insync.replicas(얼마나 복제돼야 “쓰기 허용”할까)

토픽 설정 min.insync.replicas는 acks와 함께 “더 강한 내구성 보장”을 만들기 위한 핵심 레버다. Kafka 문서에서도 RF=3, min.insync.replicas=2, acks=all 같은 조합을 대표 시나리오로 설명한다.

 

6-3. unclean.leader.election.enable(최후의 리더 선출)

unclean.leader.election.enable은 “ISR에 없는 복제본도 최후의 수단으로 리더가 되게 할지”를 결정하며, 그렇게 하면 데이터 유실 가능성이 있다고 Kafka 문서에 명시돼 있다.

✅ 운영 관점 한 줄 요약

  • **내구성(유실 방지)**을 올리려면: acks=all + min.insync.replicas 강화 + unclean election 비활성(보수적으로)
  • **가용성(멈추지 않기)**을 올리려면: 반대로 더 느슨한 설정(단, 그 대가가 “유실/중복/불일치”임)

 

[Replica Failure]

ISR은 Leader가 관리함 (Follower 장애 여부를 Zookeeper에게 알림) 

Zookeeper가 Leader 장애가 있는지 감지하고 컨트롤러가 새로운 Leader를 선출하고 ISR 리스트를 Zookeeper에게 기록하고 Leader 변경 

Partition Leader 가 없으면 Leader가 선출될때까지 해당 Partition 사용할 수 없음 

 

[Replica Recovery]

Leader 가 가지고 있었던 데이터 중에 복제본이 아직 그 데이터를 commit 하지 못한 경우에 Leader 죽음 

-> Producer는 ack를 못 받았기 때문에 계속해서 retry 

-> 그러나 Leader가 된 Follower 에서 commit 이 안된 데이터를 버리지 않게되어 중복 (idempotence false)

 

ack=1 인 옵션의 경우에는

-> 데이터 유실이 발생할 수도 있음 

 

데이터 유실 발생 / 데이터의 유실은 발생하지 않음 가용성과 내구성 중 선택

 

 

7) Consumer & Consumer Group: 병렬 소비와 오프셋 관리

 

7-1. Consumer Group과 “파티션 할당”

  • 한 파티션은 같은 컨슈머 그룹 내에서 동시에 한 컨슈머에게만 할당된다(병렬 소비 단위=파티션).
  • 서로 다른 그룹은 같은 토픽을 각자 독립적으로 소비할 수 있다(예: 마케팅 그룹, 정산 그룹).
브로커 1: Partition 0, 1
브로커 2: Partition 2, 3  ← Group Coordinator 역할도 수행
브로커 3: Partition 4, 5

컨슈머 A (Group Leader):
- 브로커 2(Coordinator)와 통신하여 그룹 관리
- 파티션 0, 2, 4 할당받음
- 실제 데이터는 브로커 1, 2, 3에서 각각 가져옴

컨슈머 B:
- 브로커 2(Coordinator)와 통신하여 그룹 관리
- 파티션 1, 3, 5 할당받음
- 실제 데이터는 브로커 1, 2, 3에서 각각 가져옴

 

7-2. __consumer_offsets(내부 토픽)

Kafka는 컨슈머 그룹의 오프셋 커밋 정보를 내부 토픽 __consumer_offsets에 저장한다(원문 메모의 “consumer_offsets”는 보통 이 토픽을 의미).
이 토픽도 결국 Kafka의 일반 토픽처럼 파티션을 가지며, 그룹 코디네이터가 해당 파티션을 관리한다(운영/모니터링 시 매우 중요).

 

7-3. 리밸런싱(Rebalancing)과 Heartbeat

컨슈머는 그룹에 “살아있다”는 신호(heartbeat)를 보내고, 멤버 변동(추가/이탈/장애)이나 토픽 파티션 변화가 있으면 리밸런싱이 일어난다. 리밸런싱 중에는 할당이 재조정되며, 전략에 따라 “일시 정지” 체감이 생길 수 있다.

 

 

7-4. Partition Assignment Strategy(할당 전략)

원문에 나온 Range / RoundRobin / Sticky / Cooperative Sticky는 “어떻게 파티션을 분배하고, 리밸런싱 충격을 얼마나 줄이느냐”의 차이다.

  • Range: 토픽별 파티션 범위를 연속 구간으로 나눠 할당(토픽이 여러 개면 편향이 생길 수 있음)
  • RoundRobin: 파티션을 번갈아 배치(균등해 보이지만 토픽/구성에 따라 들쭉날쭉 가능)
  • Sticky: 기존 할당을 최대한 유지하려고 노력(불필요한 이동 감소)
    Consumer C0:
    - orders-topic: 파티션 0
    - payments-topic: 파티션 0
    
    Consumer C1:
    - orders-topic: 파티션 1
    - payments-topic: 파티션 1
    
    Consumer C2:
    - orders-topic: 파티션 2
    - payments-topic: 파티션 2
  • Cooperative Sticky: “한 번에 다 뺏고 다시 나눠주기”가 아니라, 점진적으로 재조정해 스톱 시간을 줄이는 방향



8) Exactly-Once Semantics(EOS): “정확히 한 번 처리”는 언제 성립하나

EOS는 말이 흔하지만, Kafka에서는 보통 read → process → write 파이프라인에서 “커밋된 레코드 기준으로 중복/유실 없이 처리”를 목표로 한다. 이를 위해 idempotent producer + transactions 조합을 사용한다는 것이 핵심이다(생산자 트랜잭션 사용 시 transactional.id 설정이 필요).

  • Idempotent Producer(멱등 생산자): 재시도(retry)로 인해 같은 레코드가 중복 저장되는 위험을 줄임
  • Transactions(트랜잭션): “소비한 것”과 “생산한 것”을 하나의 원자적 단위로 묶어, 파이프라인의 일관성을 강화

✅ 오해 방지
EOS는 “세상 모든 상황에서 절대 중복이 없다”가 아니라, 특정 조건(트랜잭션/설정/커밋 모델) 하에서 Kafka가 제공하는 강한 보장 모델이다.

 

 

9) Kafka Connect · Schema Registry · Streams/ksqlDB: 주변 생태계 한 번에 보기

9-1. Kafka Connect

Kafka Connect는 외부 시스템(DB, S3, ES 등)과 Kafka 사이를 연결하는 표준 통합 런타임이다.

  • Source Connector: 외부 → Kafka
  • Sink Connector: Kafka → 외부
  • Worker/Task 구조로 병렬 처리/확장

 

9-2. Schema Registry(스키마 관리)

메시지를 “그냥 JSON”으로 흘리면 편하지만, 시간이 지나면 필드 변경/호환성 문제로 장애가 난다.
Schema Registry(특히 Avro/Protobuf/JSON Schema 계열)는 스키마를 중앙에서 버저닝하고 호환성 규칙을 적용해, 데이터 계약(contract)을 운영 가능하게 만든다.

 

Single Message Transform(SMT),Converter



9-3. Kafka Streams / ksqlDB

 

  • Kafka Streams: 애플리케이션 코드(라이브러리)로 스트림 처리를 구현
  • ksqlDB: SQL로 스트리밍 처리를 정의/운영(머티리얼라이즈드 뷰 등)
    Kafka는 ksqlDB을 consume -> 쿼리로 데이터를 변환해서 kafka에 넣어줌 (=produce)

 

 


✳ 출처

- 주요 개념

https://velog.io/@kidae92/Apache-Kafka-%EC%A3%BC%EC%9A%94-%EC%9A%94%EC%86%8C1Producer-Consumer-Topic

- 주키퍼 

https://velog.io/@kidae92/Apache-Kafka-%EC%A3%BC%EC%9A%94-%EC%9A%94%EC%86%8C2

- 파티션 / 복제 

https://velog.io/@hyun6ik/Apache-Kafka-Producer

- kafka 심화 개념 

https://dortmoot.tistory.com/131

- Replication 

https://damdam-kim.tistory.com/17

- ksqlDB

https://yeji-shin.github.io/kafka/2022/08/28/17.-Kafka-Streams,-ksqlDB.html