위와 같은 의문을 가졌었습니다.
맞는 말이에요. 다만, 상황에 따라 목적에 따라 결정하는 부분이라고 생각합니다.
: 현재 애플리케이션 프로세스 안에서 새로운 스레드를 만들어 비동기적으로 백그라운드 스레드에서 돌아가도록 합니다.
✅ 애플리케이션 내부에서 단순 백그라운드 실행을 해도 될 때 사용하면 됩니다.
❌ 서버 인스턴스가 죽으면 스레드 작업도 같이 날라갑니다.
❌ 스레드풀 한계로 인해 트래픽이 몰리면 병목 발생할 수 있습니다.
❌ 여러 서버 인스턴스에서 작업 순서를 제어하거나 재시도(retry), 보장(delivery guarantee) 같은 로직을 처리하기 어렵습니다.
: 단순 "스레드 분리"가 아니라, 생산자(Producer) → 브로커(Kafka 서버) → 소비자(Consumer) 구조로 이루어진 분산 메시징 시스템입니다.
✅ 내구성 & 재시도 보장: Kafka는 디스크에 로그를 저장 → 장애 나도 메시지 유실 X
✅ 수평 확장성: 여러 Consumer 그룹으로 분산 처리 가능
✅ 서비스 간 결합도↓: 발행/구독 구조로, 서비스 간 의존도 낮음
✅ 지속적인 이벤트 스트림 처리 가능 (예: 로그 집계, 실시간 통계 등)
❌ 운영 복잡성 (Kafka 클러스터 운영, 오프셋 관리 등)
❌ 메시지 처리 순서, 중복 처리 등 고려 필요
❌ 트랜잭션 일관성 확보 어려움 (특히 DB 트랜잭션과 분리되므로)
▶️ DLT(Dead Letter Topic)는 오류로 인해 처리할 수 없는 메시지 (재시도(Retry) 조차 실패한 메시지)를 임시로 저장하는 토픽입니다.
✅ Spring Kafka는
@RetryableTopic를 사용하면 자동으로 DLT 토픽을 생성하고 메시지를 전송해줍니다.
기본 DLT 토픽명:{기존 토픽명}-dlt
1. DLT에 저장된 실패 메시지를 로그 시스템에 전송해 장애 원인을 추적할 수 있도록 한다.
2. DLT에 메시지가 저장되자마자 수동으로 대처할 수 있게 알림을 설정한다.
3. 알림을 받은 관리자는 로그에 쌓인 내용을 보고 장애 원인을 분석하고, 그에 맞게 메시지를 수동으로 처리한다.
여기서 3번째 내용중에 '메시지를 수동으로 처리한다' 부분을 다시 나누면
1. 메시지를 원래 토픽으로 직접 다시 보내기
2. 메시지 폐기하기
3. (사후 처리) 잘못된 메시지 내용이 Kafka에 들어가지 않게 Producer의 검증 로직 보완하기
▶️ 큐(메시지를 임시로 저장할 수 있는 공간)를 여러개로 늘려서 병렬 처리를 가능하게 하는 기본단위입니다.


파티션 #0에 컨슈머 #0이 할당됐을 때, 컨슈머 #0은 오프셋이 0인 메시지를 다 처리하고 난 뒤에 오프셋이 1인 메시지를 처리합니다.
// 문법
$ bin/kafka-topics.sh \
--bootstrap-server <kafka 주소> \
--create \
--topic <토픽명> \
--partitions <파티션 수>
// 예제
$ bin/kafka-topics.sh \
--bootstrap-server localhost:9092 \
--create \
--topic test.topic \
--partitions 3
$ bin/kafka-topics.sh \
--bootstrap-server localhost:9092 \
--describe --topic test.topic

PartitionCount: 토픽이 가지고 있는 파티션의 총 개수Partition: 파티션 번호 (0번 부터 시작)// 문법
$ bin/kafka-topics.sh \
--bootstrap-server <kafka 주소> \
--alter \
--topic <토픽명> \
--partitions <변경할 최종 파티션 수>
// 예제
$ bin/kafka-topics.sh \
--bootstrap-server localhost:9092 \
--alter \
--topic test.topic \
--partitions 5
✅ 파티션을 줄이는 과정은 내부적으로 문제(데이터 손실, 성능 저하 등)가 많이 발생하기 때문에 카프카가 에러를 발생시킵니다.
처음 파티션 수를 설정할 때 신중하게 설정하는 걸 권장합니다.🙏




▶️ 카프카에서 사용하는 랙의 의미는 지연된 메시지 수(컨슈머가 아직 처리하지 못한 메시지 수)입니다. 컨슈머 랙(Consumer Lag)이라고도 부릅니다.

1초에 메시지가 3개씩 전송되는데 1초에 메시지를 1개씩 밖에 처리를 하지 못한다면, 1초 당 2개의 메시지가 계속해서 쌓일것입니다.
사용자들 입장에서 요청을 보낸 내용이 처리되지 않아 서비스에 버그가 생겼다고 생각할 것입니다.
빠르게 조치하려면 컨슈머 랙을 지속적으로 모니터링 할 수 있어야 합니다.
외부 모니터링 툴을 사용해서 컨슈머 랙(Conusmer Lag)을 지속적으로 모니터링하면서, 특정 케이스에 대해 알림을 발송하게 만들어서 빠르게 대처할 수 있게 셋팅하는 편입니다.
많이 사용하는 외부 모니터링 툴로는 이런 것들이 있습니다.
현업에서는 카프카를 직접 구축해서 사용하지 않고, 클라우드의 카프카 서비스를 사용하는 경우도 많다. 대표적인 서비스로 AWS MSK와
Confluent Cloud가 있습니다. 이 서비스를 사용하면 자체적으로 컨슈머 랙(Consumer Lag)에 대한 모니터링 기능을 같이 제공하는 경우가
많습니다.
⭐️ Kafka의 고가용성(시스템이 장애 상황에서도 멈추지 않고 정상적으로 서비스를 제공할 수 있는 능력)을 확보하는 방법을 이해하려면 해당 용어들을 알고있어야 합니다.
▶️ 카프카가 설치되어 있는 서버 단위
💡 서비스 장애를 방지하기 위해 실무에서는 위 그림과 같이 노드(node)를 1대만 두지 않고, 최소 3대의 노드(node)를 구성합니다. 즉, 최소 카프카 서버 3대를 구축해서 운용한다는 뜻입니다.

▶️ 여러 대의 서버가 연결되어 하나의 시스템처럼 동작하는 서버들의 집합

예를 들면, 서로 들어오는 메시지를 나눠 저장하고, 서로의 복제본을 생성해서 유지할 수도 있으며, 장애 시 시스템 전체가 중단없이 작동되게 만듭니다. 이와 같이 유기적으로 작동하는 노드들을 묶어서 클러스터(cluster)라고 부릅니다.
💡
Kafka 서버는 크게 컨트롤러와 브로커로 구성되어 있으며, 기본적으로 kafka 노드에서 브로커는 9092 포트, 컨트롤러는 9093 포트에서 별개의 프로세스로 실행됩니다.
▶️ 컨트롤러: 브로커들간의 연동과 전반적인 클러스터의 상태를 총괄합니다.(총관리자)
▶️ 브로커: 메시지를 저장하고 클라이언트의 요청을 처리하는 역할을 합니다.(직원)

▶️ 데이터의 안정성과 가용성을 높이기 위해
토픽의 파티션을 여러 노드에 복제하는 걸 의미합니다.
리더 파티션(원본)과 팔로워 파티션(복제본)으로 구분됩니다.리더 파티션은 프로듀서나 컨슈머가 직접적으로 메시지를 읽고 쓰는 파티션입니다. 반면에 팔로워 파티션은 프로듀서나 컨슈머가 직접적으로 메시지를 일고 쓰지 않습니다.팔로워 파티션은 리더 파티션의 메시지를 실시간으로 복제하며 유지합니다.리더 파티션에 장애가 발생하면 팔로워 파티션이 리더 역할(프로듀서로부터 메시지를 받고, 컨슈머가 메시지를 처리)을 대신 수행합니다. 이미 팔로워 파티션은 리더 파티션 내부에 있는 메시지까지 복제해서 가지고 있기 때문에, 리더 파티션의 노드가 중간에 장애가 난다고 하더라도 메시지는 정상적으로 이어서 처리할 수 있습니다.

cd .. # kafka 디렉터리로 이동
# kafka 종료하기
$ bin/kafka-server-stop.sh
# 처음 실행하는 kafka 노드는 아래 명령어로 실행
$ KAFKA_CLUSTER_ID="$(bin/kafka-storage.sh random-uuid)"
$ KAFKA_CONTROLLER_ID="$(bin/kafka-storage.sh random-uuid)"
$ bin/kafka-storage.sh format \
-t $KAFKA_CLUSTER_ID \
-c config/server.properties \
--initial-controllers "1@localhost:9093:$KAFKA_CONTROLLER_ID"
# 추가로 연동시킬 kafka 노드는 아래 명령어로 실행
# 주의 : server.properties가 아니라 server2.properties를 사용해야 한다.
$ bin/kafka-storage.sh format \
-t $KAFKA_CLUSTER_ID \
-c config/server2.properties \
--no-initial-controllers
# 추가로 연동시킬 kafka 노드는 아래 명령어로 실행
# 주의 : server.properties가 아니라 server3.properties를 사용해야 한다.
$ bin/kafka-storage.sh format \
-t $KAFKA_CLUSTER_ID \
-c config/server3.properties \
--no-initial-controllers
$ bin/kafka-server-start.sh config/server.properties
$ bin/kafka-server-start.sh config/server2.properties
$ bin/kafka-server-start.sh config/server3.properties
# kafka 노드들의 브로커 실행 확인
$ lsof -i:9092 # 노드 1의 브로커
$ lsof -i:19092 # 노드 2의 브로커
$ lsof -i:29092 # 노드 3의 브로커
# kafka 노드들의 컨트롤러 실행 확인
$ lsof -i:9093 # 노드 1의 컨트롤러
$ lsof -i:19093 # 노드 2의 컨트롤러
$ lsof -i:29093 # 노드 3의 컨트롤러
$ bin/kafka-metadata-quorum.sh \
--command-config config/server2.properties \
--bootstrap-server localhost:9092 \
add-controller
$ bin/kafka-metadata-quorum.sh \
--command-config config/server3.properties \
--bootstrap-server localhost:9092 \
add-controller
$ bin/kafka-metadata-quorum.sh \
--bootstrap-server localhost:9092 describe \
--status

위 명렁어를 입력했을 대 CurrentVoters에 3개의 컨트롤러 정보가 찍히면 클러스터에 3개의 컨트롤러가 정상적으로 잘 등록된 것입니다.
$ bin/kafka-topics.sh \
--bootstrap-server localhost:9092 \
--create \
--topic email.send \
--partitions 1 \
--replication-factor 3
# 토픽 세부 정보 조회하기
$ bin/kafka-topics.sh \
--bootstrap-server localhost:9092 \
--describe \
--topic email.send

Replicas와 Isr에 3개의 숫자(1, 2, 3)가 다 있다면 3개의 Kafka 서버가 정상적으로 잘 연동되고 있다는 뜻입니다.

리더 파티션은 프로듀서나 컨슈머가 직접적으로 메시지를 쓰고 읽는 파티션, 팔로워 파티션은 프로듀서나 컨슈머가 직접적으로 메시지를 쓰고 읽지 않는다고 하였습니다.
그러나 팔로워 파티션에 메시지를 넣어도 정상 동작합니다.!

Leader 리더 파티션이 2로 바뀌었습니다. 즉, 리더 파티션에 장애가 발생해서 팔로워 파티션이 리더 역할을 대신 수행하게끔 승격되었습니다.Isr 1번 노드가 빠졌다는 것은 1번 노드의 네트워크가 끊겼거나, 서버에 장애가 생겼거나, 아직 리더 파티션의 데이터와 동기화 되지 않았다는 뜻입니다.kafka 서버를 많이 운용할수록 시스템 전체가 중단될 확률이 줄어들기 때문에 좋기는 하나, 많은 서버를 운용하게 되면 서버 비용이 많이 나옵니다.
그리고 kafka 서버를 1대로 운용한다고 해서 서비스를 아예 운영하지 못할 정도의 치명적인 장애가 발생하는 건 아닙니다. 따라서 아래 지침을 통해 kafka 서버 개수를 정하는 걸 추천합니다.
1. 초기 스타트업, 초기 단계 서비스, 개발/테스트 단계
이 링크를 통해 구매하시면 제가 수익을 받을 수 있어요. 🤗
출처: https://inf.run/wQkoW