“우리 서비스에 접속자가 갑자기 폭증했는데, 시스템이 버텨내지 못하고 다운됐어요…” “주문이 들어왔는데 재고 시스템에는 반영이 안 됐어요…” “로그가 너무 많아서 실시간으로 확인할 수가 없어요…” 이런 문제들, 혹시 겪어보셨나요? 오늘 소개할 Apache Kafka(아파치 카프카)가 바로 이런 고민을 해결해주는 도구입니다. 처음부터 차근차근, 쉽게 알아볼게요.

1. Kafka가 뭔가요? – 우체국에 비유하면
일단 간단하게 설명하면, Kafka는 초고속 우체국 같은 거예요.
일반 우체국은 이렇게 동작하죠
보내는 사람 → 우체국 → 받는 사람
한 명이 편지를 보내면, 한 명이 받습니다. 받는 사람이 편지를 읽으면 끝이죠.
Kafka 우체국은 조금 달라요
보내는 사람들 → Kafka → 여러 받는 사람들
(여러 명) (보관함) (각자 복사본을 받음)
특별한 점:
- 하루에 수백만 통의 편지를 처리할 수 있어요 (엄청난 속도)
- 편지를 일정 기간 보관해서, 나중에 다시 읽을 수 있어요
- 한 편지를 여러 사람이 각각 읽을 수 있어요
- 편지가 분실되지 않게 여러 곳에 복사본을 만들어요
이게 바로 Kafka가 하는 일입니다!
실제 사례로 이해하기
쿠팡에서 주문 버튼을 누르는 순간:
① 주문 시스템: "주문이 들어왔어요!" → Kafka에 메시지 전송
② Kafka가 이 메시지를 여러 시스템에 동시에 전달:
- 재고 시스템: "재고 1개 빼야겠네"
- 결제 시스템: "카드 결제 진행해야겠네"
- 배송 시스템: "배송 준비해야겠네"
- 알림 시스템: "고객에게 문자 보내야겠네"
- 분석 시스템: "오늘 매출에 추가해야겠네"
만약 Kafka가 없었다면:
- 주문 시스템이 5개 시스템에 일일이 연결해서 전달해야 함
- 결제 시스템이 다운되면? 주문 시스템도 멈춤
- 나중에 추천 시스템을 추가하려면? 주문 시스템 코드를 수정해야 함
Kafka가 있으면:
- 주문 시스템은 Kafka에만 보내면 끝
- 각 시스템은 독립적으로 동작
- 새 시스템 추가? 그냥 Kafka에서 읽기만 하면 됨
2. 왜 Kafka를 만들었을까? – 링크드인의 고민
2011년 링크드인은 큰 문제가 있었어요.
복잡하게 얽힌 시스템들
[시스템 구조]
회원가입 시스템 ─┬→ 이메일 시스템
├→ 추천 시스템
├→ 검색 시스템
└→ 분석 시스템
이메일 시스템 ──┬→ 알림 시스템
└→ 로그 시스템
추천 시스템 ────┬→ 분석 시스템
└→ 검색 시스템
문제점:
- 시스템이 20개면 연결이 수백 개
- 한 시스템에 문제가 생기면 연결된 모든 시스템 확인 필요
- 새 시스템 추가할 때마다 기존 시스템들과 연결 작업
- 하루 14억 개 메시지 처리하다 보니 시스템이 버티기 힘들었음
Kafka로 단순화
[Kafka 도입 후]
회원가입 시스템 ─┐
이메일 시스템 ───┤
추천 시스템 ─────┤→ Kafka ─┤→ 알림 시스템
검색 시스템 ─────┤ ├→ 로그 시스템
분석 시스템 ─────┘ ├→ 검색 시스템
└→ 추천 시스템
개선 효과:
- 모든 시스템이 Kafka하고만 통신
- 한 시스템 장애가 다른 시스템에 영향 없음
- 새 시스템 추가가 간단함
- 초당 수백만 메시지도 문제없이 처리
3. Kafka의 핵심 개념 – 실생활로 이해하기
Producer (생산자) = 편지 보내는 사람
데이터를 만들어서 Kafka로 보내는 애플리케이션이에요.
실제 예시:
- 웹 서버: “사용자가 상품 페이지를 봤어요”
- 모바일 앱: “사용자가 앱을 열었어요”
- IoT 센서: “현재 온도는 25도예요”
- 주문 시스템: “새 주문이 들어왔어요”
Consumer (소비자) = 편지 받는 사람
Kafka에서 데이터를 읽어서 처리하는 애플리케이션이에요.
실제 예시:
- 추천 시스템: 클릭 데이터를 읽어서 → 추천 알고리즘 업데이트
- 알림 시스템: 주문 데이터를 읽어서 → 고객에게 문자 발송
- 모니터링 시스템: 에러 로그를 읽어서 → 담당자에게 알림
Topic (토픽) = 우편함의 라벨
메시지를 종류별로 분류하는 카테고리예요. 도서관의 책장 라벨과 비슷해요.
[Kafka Topics]
📬 user.signup (회원가입 이벤트)
📬 order.created (주문 생성 이벤트)
📬 payment.success (결제 완료 이벤트)
📬 sensor.temp (온도 센서 데이터)
각 시스템은 필요한 토픽만 구독하면 됩니다.
Partition (파티션) = 여러 개의 창구
토픽을 여러 조각으로 나눈 거예요. 은행 창구를 생각해보세요.
[은행 비유]
창구가 1개일 때:
대기자 100명 → 창구 1개 → 100분 소요
창구가 5개일 때:
대기자 100명 → 창구 5개 → 20분 소요
Kafka도 똑같아요:
[주문 토픽 - 1개 파티션]
주문 1, 2, 3, 4, 5... → 파티션 0 → 처리 느림
[주문 토픽 - 3개 파티션]
주문 1, 4, 7... → 파티션 0 ↘
주문 2, 5, 8... → 파티션 1 → 동시 처리 → 3배 빠름!
주문 3, 6, 9... → 파티션 2 ↗
어떻게 나눠질까요?
- 키가 있으면: 같은 키는 항상 같은 파티션
user123의 모든 활동 → 항상 파티션 0 user456의 모든 활동 → 항상 파티션 1순서가 중요할 때 사용해요.
- 키가 없으면: 골고루 분배
메시지 1 → 파티션 0 메시지 2 → 파티션 1 메시지 3 → 파티션 2 메시지 4 → 파티션 0
Offset (오프셋) = 책의 페이지 번호
각 메시지의 위치를 나타내는 번호예요.
[파티션 0의 메시지들]
오프셋: 0 1 2 3 4 5
메시지: [주문1] [주문4] [주문7] [주문10] [주문13] [주문16]
↑
여기까지 읽음 (오프셋 3)
왜 중요할까요?
책을 읽다가 표시해둔 것처럼:
- “어디까지 읽었지?” → 오프셋으로 확인
- 시스템이 재시작되어도 → 이어서 읽을 수 있음
- 잘못 읽었다면? → 오프셋을 되돌려서 다시 읽기
Broker (브로커) = 우체국 지점
실제로 메시지를 저장하고 관리하는 Kafka 서버예요.
[단일 Broker - 위험]
브로커 1개 → 고장나면 전체 중단 ❌
[클러스터 - 안전]
브로커 1 (메시지 A, B 저장)
브로커 2 (메시지 A, B 복사본)
브로커 3 (메시지 A, B 복사본)
→ 1~2개 고장나도 서비스 정상 ✓
Consumer Group (소비자 그룹) = 협업하는 팀
여러 Consumer가 팀을 이루어 일을 나눠서 처리해요.
[주문 처리 팀 - 4명이 협업]
주문 토픽 (4개 파티션)
├─ 파티션 0 → 직원 A가 처리
├─ 파티션 1 → 직원 B가 처리
├─ 파티션 2 → 직원 C가 처리
└─ 파티션 3 → 직원 D가 처리
결과: 4배 빠른 처리!
중요한 규칙:
- 한 파티션은 그룹 내 한 명만 처리 가능
- 직원이 5명인데 파티션이 4개? → 1명은 대기
- 직원이 2명인데 파티션이 4개? → 1명당 2개씩 처리
다른 팀은 독립적:
[주문 데이터를 각 팀이 독립적으로 사용]
주문 토픽
├─ 배송 팀: 배송지 준비
├─ 분석 팀: 매출 집계
└─ 알림 팀: 고객 문자 발송
(각 팀은 서로 영향 없이 독립적으로 처리)
Replication (복제) = 백업
데이터를 여러 Broker에 복사해서 안전하게 보관해요.
[Replication Factor = 3]
파티션 0 원본 (Leader) → 브로커 1
파티션 0 복사본 (Follower) → 브로커 2
파티션 0 복사본 (Follower) → 브로커 3
브로커 1이 고장나면?
① 브로커 1 다운 🔴
② 브로커 2가 즉시 Leader로 승격 ✓
③ 서비스 중단 없이 계속 동작
④ 브로커 3에서 새 복사본 생성
4. Kafka가 빠른 이유 – 핵심 비결
비결 1: 디스크를 순차적으로 사용
랜덤 쓰기 (느림):
디스크 여기저기 왔다갔다
위치 찾기 → 쓰기 → 위치 찾기 → 쓰기
시간이 오래 걸림
순차 쓰기 (빠름):
디스크에 쭉 이어서 쓰기
쓰기 → 쓰기 → 쓰기 → 쓰기
하드디스크도 SSD처럼 빠름!
Kafka는 메시지를 파일 끝에 계속 추가만 해요. 그래서 빠릅니다.
비결 2: 배치 처리
개별 전송 (비효율):
메시지 1개 → 전송 (네트워크 왕복)
메시지 1개 → 전송 (네트워크 왕복)
메시지 1개 → 전송 (네트워크 왕복)
총 3번의 네트워크 왕복
배치 전송 (효율적):
메시지 100개 모아서 → 한 번에 전송
1번의 네트워크 왕복으로 100개 처리!
비결 3: Zero-Copy
일반적인 방식:
디스크 → 커널 메모리 → 애플리케이션 메모리 → 소켓 버퍼 → 네트워크
(4번 복사)
Kafka의 Zero-Copy:
디스크 → 네트워크
(복사 최소화)
CPU와 메모리를 거의 사용하지 않고 데이터를 전송해요.
비결 4: 파티션 병렬 처리
1개 파티션 = 1명이 일함 → 느림
10개 파티션 = 10명이 동시에 일함 → 10배 빠름
5. Kafka 4.0의 혁신 – 더 쉽고 강력해졌어요
ZooKeeper 없이도 동작! (KRaft 모드)
과거 (복잡했던 시절):
① ZooKeeper 클러스터 설치 (3대)
② Kafka 클러스터 설치 (3대)
③ ZooKeeper와 Kafka 연결 설정
④ 둘 다 관리하고 모니터링
지금 (간단해진 시대):
① Kafka만 설치하면 끝!
② 설정도 훨씬 간단
③ 관리할 시스템이 절반으로
KRaft의 장점:
[비교]
ZooKeeper 시절:
- 최대 파티션: 10만 개
- 클러스터 시작 시간: 수 분
- 관리 복잡도: 높음
KRaft 시대:
- 최대 파티션: 수백만 개
- 클러스터 시작 시간: 수 초
- 관리 복잡도: 낮음
리밸런싱이 훨씬 부드러워졌어요 (KIP-848)
과거의 문제:
① 새 Consumer 추가
② 모든 Consumer 멈춤 🛑
③ 파티션 재분배
④ 모든 Consumer 재시작
⑤ 10초 동안 처리 중단...
지금은 이렇게:
① 새 Consumer 추가
② 필요한 파티션만 조금씩 이동
③ 나머지 Consumer는 계속 처리 ✓
④ 100ms 정도만 지연
실제 체감:
- 과거: “어? 갑자기 처리가 멈췄네?”
- 지금: “언제 Consumer 추가된 거지?” (못 느낌)
Queue 기능 추가! (Share Group)
기존 Kafka:
파티션 0 → Consumer A만 읽을 수 있음
파티션 1 → Consumer B만 읽을 수 있음
Share Group (새로운 기능):
파티션 0 → Consumer A, B, C 모두 협력해서 처리
(메시지별로 한 명씩만 처리, RabbitMQ처럼!)
언제 유용할까요?
[택시 호출 시스템]
호출 요청 100건이 파티션 0에 들어옴
→ 매칭 서버 A, B, C가 협력
→ A가 30건, B가 35건, C가 35건 처리
→ 병렬 처리로 빠른 매칭!
6. 실제로 사용해보기 – 단계별 가이드
준비: Java 17
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install openjdk-17-jdk
# 확인
java -version
# openjdk version "17.0.x" 나오면 성공!
Kafka 다운로드
# 최신 버전 다운로드
wget https://downloads.apache.org/kafka/4.1.0/kafka_2.13-4.1.0.tgz
# 압축 풀기
tar -xzf kafka_2.13-4.1.0.tgz
cd kafka_2.13-4.1.0
Kafka 시작 (정말 간단해요!)
# 1단계: ID 생성 (맨 처음 한 번만)
KAFKA_CLUSTER_ID="$(bin/kafka-storage.sh random-uuid)"
# 2단계: 저장소 준비
bin/kafka-storage.sh format -t $KAFKA_CLUSTER_ID -c config/kraft/server.properties
# 3단계: Kafka 시작!
bin/kafka-server-start.sh config/kraft/server.properties
화면에 이렇게 나오면 성공:
[KafkaServer id=1] started
토픽 만들기 – 우편함 만들기
새 터미널을 열어서:
bin/kafka-topics.sh --create \
--topic hello-kafka \
--bootstrap-server localhost:9092 \
--partitions 3 \
--replication-factor 1
해석해볼까요?
hello-kafka: 우편함 이름partitions 3: 창구 3개 (3배 빠른 처리)replication-factor 1: 복사본 1개 (혼자 실습이라 1개)
메시지 보내기 – 첫 편지 쓰기
bin/kafka-console-producer.sh \
--topic hello-kafka \
--bootstrap-server localhost:9092
이제 입력할 수 있어요:
> 안녕 Kafka!
> 첫 번째 메시지예요
> 실시간으로 전달될까요?
한 줄씩 입력하고 Enter! 각 줄이 하나의 메시지가 됩니다.
메시지 받기 – 편지 읽기
또 다른 터미널을 열어서:
bin/kafka-console-consumer.sh \
--topic hello-kafka \
--from-beginning \
--bootstrap-server localhost:9092
아까 보낸 메시지들이 화면에 나타나요!
안녕 Kafka!
첫 번째 메시지예요
실시간으로 전달될까요?
실시간 테스트 해보기
Producer 터미널과 Consumer 터미널을 양옆에 나란히 놓고:
Producer에서 입력:
> 실시간 테스트!
Consumer에서 거의 즉시 출력:
실시간 테스트!
신기하죠? 이게 Kafka의 실시간 처리 능력입니다!
7. Docker로 더 쉽게 시작하기
설치 과정이 번거롭다면 Docker를 사용해보세요.
docker-compose.yml 파일 만들기
version: '3.8'
services:
kafka:
image: apache/kafka:4.0.0
container_name: my-kafka
ports:
- "9092:9092"
environment:
# KRaft 모드 설정
KAFKA_NODE_ID: 1
KAFKA_PROCESS_ROLES: broker,controller
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@localhost:9093
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_LOG_DIRS: /tmp/kraft-combined-logs
CLUSTER_ID: MkU3OEVBNTcwNTJENDM2Qk
실행하기
# Kafka 시작
docker-compose up -d
# 잘 동작하는지 확인
docker-compose logs -f
# 토픽 만들기
docker exec -it my-kafka kafka-topics.sh \
--create --topic test \
--bootstrap-server localhost:9092 \
--partitions 3
# 종료
docker-compose down
이게 끝! 정말 간단하죠?
8. 실제 코드로 사용하기
Python으로 메시지 보내기
from kafka import KafkaProducer
import json
from datetime import datetime
# Producer 생성
producer = KafkaProducer(
bootstrap_servers=['localhost:9092'],
value_serializer=lambda v: json.dumps(v).encode('utf-8')
)
# 주문 데이터 보내기
order = {
'주문번호': 'ORD-001',
'상품': '노트북',
'수량': 1,
'가격': 1500000,
'시간': datetime.now().isoformat()
}
# Kafka로 전송!
future = producer.send('orders', value=order)
# 전송 완료 확인
result = future.get(timeout=10)
print(f'전송 완료! 파티션: {result.partition}, 오프셋: {result.offset}')
producer.close()
실행 결과:
전송 완료! 파티션: 2, 오프셋: 15
Python으로 메시지 받기
from kafka import KafkaConsumer
import json
# Consumer 생성
consumer = KafkaConsumer(
'orders',
bootstrap_servers=['localhost:9092'],
auto_offset_reset='earliest', # 처음부터 읽기
group_id='order-processor', # 그룹 이름
value_deserializer=lambda x: json.loads(x.decode('utf-8'))
)
print('주문을 기다리는 중...')
# 메시지 받아서 처리
for message in consumer:
order = message.value
print(f'\n새 주문 도착!')
print(f'주문번호: {order["주문번호"]}')
print(f'상품: {order["상품"]}')
print(f'수량: {order["수량"]}')
print(f'가격: {order["가격"]:,}원')
실행 결과:
주문을 기다리는 중...
새 주문 도착!
주문번호: ORD-001
상품: 노트북
수량: 1
가격: 1,500,000원
Java 간단 예제
Producer:
import org.apache.kafka.clients.producer.*;
import java.util.Properties;
public class OrderProducer {
public static void main(String[] args) {
// 설정
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer",
"org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer",
"org.apache.kafka.common.serialization.StringSerializer");
// Producer 생성
Producer<String, String> producer = new KafkaProducer<>(props);
// 메시지 전송
String orderId = "ORD-001";
String orderData = "노트북,1,1500000";
ProducerRecord<String, String> record =
new ProducerRecord<>("orders", orderId, orderData);
producer.send(record, (metadata, exception) -> {
if (exception == null) {
System.out.println("전송 성공! 파티션: " +
metadata.partition() + ", 오프셋: " + metadata.offset());
} else {
System.out.println("전송 실패: " + exception.getMessage());
}
});
producer.close();
}
}
9. 실무 활용 사례 – 쉽게 이해하기
사례 1: 배달 앱의 실시간 주문 처리
[고객이 치킨을 주문하는 순간]
① 주문 앱 → Kafka (order.created)
"강남구에서 치킨 1마리 주문"
② Kafka에서 여러 시스템이 동시에 읽음:
매칭 시스템:
"가까운 가게 3곳 찾았어요!"
결제 시스템:
"카드 결제 완료했어요!"
알림 시스템:
"고객에게 '주문 접수됐어요' 문자 보냄"
"가게에 '새 주문이요!' 알림 보냄"
실시간 지도:
"배달 현황 지도에 표시"
왜 Kafka를 쓸까요?
- 초당 수천 건의 주문도 처리 가능
- 한 시스템이 느려도 다른 시스템은 정상 동작
- 피크 시간대(저녁 6~8시)에도 안정적
사례 2: 넷플릭스의 추천 시스템
[드라마를 보는 순간순간]
사용자 행동:
- 5초간 미리보기 봄 → Kafka
- 드라마 재생 시작 → Kafka
- 10분 시청 → Kafka
- 일시정지 → Kafka
- 이어보기 클릭 → Kafka
실시간 처리:
- 추천 모델 즉시 업데이트
- "이런 드라마는 어때요?" 갱신
- 시청 패턴 분석
- 다음 에피소드 미리 로드
사례 3: 쿠팡의 재고 관리
[실시간 재고 동기화]
A 지역 창고: "노트북 10대 남음" → Kafka
B 지역 창고: "노트북 5대 남음" → Kafka
C 지역 창고: "노트북 0대 (품절)" → Kafka
→ 웹사이트에 실시간 반영
→ 모바일 앱에 실시간 반영
→ 상품 검색 결과에 반영
→ 판매 가능 수량 계산
효과:
- 품절 상품 주문 방지
- 과다 재고 방지
- 고객 만족도 향상
사례 4: 카카오뱅크의 이체 처리
[100만원 이체하는 순간]
① 이체 요청 → Kafka
② 여러 시스템이 동시에 처리:
잔액 확인: "잔액 충분한가요?"
한도 확인: "일일 한도 내인가요?"
사기 탐지: "의심스러운 거래인가요?"
이체 실행: "송금 완료!"
알림 발송: "100만원 이체됐어요"
회계 처리: "거래 내역 기록"
10. 자주 묻는 질문들
Q1. 파티션은 몇 개로 설정해야 하나요?
간단한 계산법:
목표 처리량이 초당 10,000개라면?
1. Consumer 한 개가 처리하는 속도 측정
→ 예: 초당 2,000개
2. 필요한 Consumer 수 계산
→ 10,000 ÷ 2,000 = 5개
3. 파티션 수 = Consumer 수
→ 파티션 5개로 설정!
4. 여유분 추가 (1.5배)
→ 최종: 파티션 7~8개
경험상 권장:
- 테스트/개발: 3개
- 소규모 서비스: 5~10개
- 중규모 서비스: 20~50개
- 대규모 서비스: 100개 이상
Q2. 메시지를 얼마나 보관해야 하나요?
용도별 가이드:
실시간 알림:
보존 기간 1일
(하루 지난 알림은 의미 없음)
주문 데이터:
보존 기간 30일
(환불, 교환 등을 위해)
로그 데이터:
보존 기간 7일
(분석 후 버림)
중요 이벤트:
보존 기간 무제한
(재처리나 감사를 위해)
설정 방법:
# 7일 보관
bin/kafka-configs.sh --alter \
--entity-type topics \
--entity-name my-topic \
--add-config retention.ms=604800000 \
--bootstrap-server localhost:9092
Q3. Consumer Lag이 뭔가요?
쉽게 설명하면:
[상황]
Producer: 메시지 100개 보냄
Consumer: 메시지 70개 읽음
→ Lag = 30개 (처리해야 할 메시지가 30개 남음)
비유:
식당 주방:
- 주문이 10개 들어옴 (Producer)
- 요리사가 7개 만듦 (Consumer)
- 대기 주문 3개 (Lag)
Lag이 계속 증가하면?
→ 주문이 밀린다!
→ 요리사를 더 투입해야 함 (Consumer 추가)
확인 방법:
bin/kafka-consumer-groups.sh \
--bootstrap-server localhost:9092 \
--group my-group \
--describe
결과:
TOPIC PARTITION LAG
orders 0 0 (좋음!)
orders 1 150 (처리가 밀림!)
orders 2 5 (괜찮음)
Q4. Replication Factor는 어떻게 설정하나요?
상황별 권장:
개발/테스트:
Replication Factor = 1
(혼자 테스트하니까 복사본 불필요)
소규모 운영:
Replication Factor = 2
(하나 고장나도 버틸 수 있음)
중요한 운영:
Replication Factor = 3
(두 개 동시 고장나도 버팀, 추천!)
미션 크리티컬:
Replication Factor = 5
(금융권 등 절대 잃으면 안 되는 데이터)
실제 설정:
bin/kafka-topics.sh --create \
--topic important-data \
--partitions 10 \
--replication-factor 3 \
--bootstrap-server localhost:9092
Q5. Kafka vs Redis, 뭘 써야 하나요?
용도별 선택:
Redis (Pub/Sub):
✓ 메시지 보관 안 함 (휘발성)
✓ 초저지연 (마이크로초)
✓ 간단한 알림
✗ 메시지 유실 가능
예: 채팅 읽음 표시, 실시간 알림
Kafka:
✓ 메시지 영구 보관
✓ 대용량 처리
✓ 여러 Consumer
✓ 데이터 유실 없음
✗ 약간 무거움
예: 주문 처리, 로그 수집, 이벤트 소싱
함께 사용하는 경우:
주문 시스템:
주문 데이터 → Kafka (영구 보관)
실시간 알림 → Redis (빠른 푸시)
11. 자주 접하는 문제 해결 – 막힐 때 이렇게 하세요!
문제 1: “Connection refused” 에러
증상:
Error connecting to node localhost:9092
원인과 해결:
# 1. Kafka가 실행 중인지 확인
ps aux | grep kafka
# 안 뜨면 시작
bin/kafka-server-start.sh config/kraft/server.properties
# 2. 포트가 사용 중인지 확인
lsof -i :9092
# 다른 프로세스가 쓰고 있으면 종료
kill -9 <PID>
문제 2: Consumer Lag이 계속 증가
원인:
Producer: 초당 10,000개 생산
Consumer: 초당 3,000개 처리
→ 초당 7,000개씩 밀림!
해결 1: Consumer 추가
# 원래: Consumer 2개
# 변경: Consumer 5개로 증가
# 그러면 파티션도 충분한지 확인!
bin/kafka-topics.sh --describe --topic my-topic
# 파티션이 3개면 Consumer 5개는 의미 없음
# 파티션을 먼저 늘리기
bin/kafka-topics.sh --alter \
--topic my-topic \
--partitions 10
해결 2: Consumer 처리 속도 개선
# Before: 메시지마다 DB에 저장 (느림)
for message in consumer:
save_to_db(message) # 매번 DB 접근
# After: 배치로 모아서 저장 (빠름)
batch = []
for message in consumer:
batch.append(message)
if len(batch) >= 100:
save_batch_to_db(batch) # 100개씩 한 번에
batch = []
문제 3: 메모리 부족 에러
증상:
java.lang.OutOfMemoryError: Java heap space
해결:
# Kafka 힙 메모리 늘리기
export KAFKA_HEAP_OPTS="-Xmx2G -Xms2G"
# 재시작
bin/kafka-server-start.sh config/kraft/server.properties
문제 4: 디스크 용량 부족
확인:
df -h
해결:
# 보존 기간 단축 (30일 → 7일)
bin/kafka-configs.sh --alter \
--entity-type topics \
--entity-name my-topic \
--add-config retention.ms=604800000
# 또는 사이즈 제한
bin/kafka-configs.sh --alter \
--entity-type topics \
--entity-name my-topic \
--add-config retention.bytes=10737418240
12. 다음 단계 – 더 배우고 싶다면
무료 학습 자료
공식 문서:
무료 강의:
- Kafka 101 – Confluent
- Apache Kafka for Beginners – YouTube
무료 실습:
- Confluent Cloud 무료 평가판 ($400 크레딧)
관리 도구
Kafka UI (무료):
docker run -p 8080:8080 \
-e KAFKA_CLUSTERS_0_NAME=local \
-e KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=localhost:9092 \
provectuslabs/kafka-ui:latest
웹 브라우저로 http://localhost:8080 접속하면:
- 토픽 목록 보기
- 메시지 확인
- Consumer Group 상태 모니터링
- 시각적으로 관리 가능!
마무리하며…
Kafka는 처음엔 어려워 보이지만, 핵심만 이해하면 정말 강력한 도구입니다.
기억해야 할 핵심:
- Kafka = 초고속 우체국
- 많은 편지를 빠르게 전달
- 여러 사람이 같은 편지 읽을 수 있음
- 파티션 = 창구
- 많을수록 빠름
- Consumer 수와 맞춰야 함
- 오프셋 = 책갈피
- 어디까지 읽었는지 기억
- 실패해도 이어서 읽기 가능
- Replication = 백업
- 데이터 안전하게 보관
- 서버 고장도 문제없음
Kafka 4.0부터는 ZooKeeper도 없어져서 훨씬 쉬워졌어요. 지금이 시작하기 딱 좋은 시점입니다!
작은 프로젝트부터 시작해보세요. 로그 수집이나 간단한 이벤트 처리부터 해보면서 익숙해지면, 점점 더 큰 시스템에 적용할 수 있을 거예요. 🙂