Skip to content

Commit 448ba7d

Browse files
committed
Write Kafka Post " [카프카 핵심 가이드] CHAPTER 1. 카프카 시작하기 "
- Update Kafka Post " [카프카 핵심 가이드] CHAPTER 3. 카프카 프로듀서: 카프카에 메시지 쓰기 " - Update " 2025 DevHistory "
1 parent c21dff2 commit 448ba7d

9 files changed

+158
-12
lines changed

_posts/2025-01-01-2025-DevHistory.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,6 @@ author: devFancy
5151

5252
* [MDC와 GlobalTraceId를 활용한 분산 추적](https://devfancy.github.io/SpringBoot-Distributed-Tracing-With-MDC/)
5353

54+
* [[카프카 핵심 가이드] CHAPTER 1. 카프카 시작하기](https://devfancy.github.io/Kafka-Why-And-Concept/)
55+
5456
* [[카프카 핵심 가이드] CHAPTER 3. 카프카 프로듀서: 카프카에 메시지 쓰기](https://devfancy.github.io/Kafka-Producer/)
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
---
2+
layout: post
3+
title: " [카프카 핵심 가이드] CHAPTER 1. 카프카 시작하기 "
4+
categories: Kafka
5+
author: devFancy
6+
---
7+
* content
8+
{:toc}
9+
10+
> 이 글은 [카프카 핵심 가이드](https://product.kyobobook.co.kr/detail/S000201464167?utm_source=google&utm_medium=cpc&utm_campaign=googleSearch&gad_source=1) 책을 읽고 정리한 글입니다.
11+
>
12+
> 이 글에서 다루는 모든 코드는 [깃허브](https://github.com/devFancy/springboot-coupon-system)에서 확인하실 수 있습니다.
13+
>
14+
> `참고`: 본 글에서 소개되는 코드 예시는 현재 시점의 구현을 바탕으로 작성되었으며, 프로젝트가 발전함에 따라 내용이 변경되거나 개선될 수 있음을 미리 알려드립니다.
15+
16+
## Prologue
17+
18+
'카프카 핵심 가이드' 책의 1장 '카프카 시작하기'를 읽고, 꼭 알아야 할 내용(핵심 위주)만 정리했다.
19+
20+
이 글에서는 카프카를 왜 사용해야 하는지(Why), 그리고 카프카를 구성하는 핵심 개념은 무엇인지에 초점을 맞췄다.
21+
22+
자세한 내용은 책의 1장을 참고하자.
23+
24+
25+
---
26+
27+
## 카프카를 왜 사용하는가?
28+
29+
초기 시스템은 데이터를 보내는 애플리케이션(프로듀서)과 받아서 사용하는 애플리케이션(컨슈머)이 직접 연결된 단순한 구조로 시작한다.
30+
31+
하지만 비즈니스가 성장하고 시스템이 복잡해지면서, 데이터를 생산하는 프로듀서와 데이터를 필요로 하는 컨슈머의 수가 계속 늘어난다.
32+
이때마다 시스템 간의 직접 연결(Point-to-Point)을 추가하면, 아래 그림과 같이 전체 아키텍처는 거미줄처럼 얽혀 추적하고 관리하기가 매우 어려워진다.
33+
34+
![](/assets/img/kafka/Kafka-Why-and-Concept-1.png)
35+
36+
이러한 복잡성을 해결하기 위해 **발행/구독(Publish/Subscribe) 모델**을 사용한다.
37+
모든 프로듀서는 데이터를 중앙 시스템으로 보내고, 모든 컨슈머는 이 중앙 시스템으로부터 데이터를 가져간다.
38+
이 중앙 시스템이 바로 메시지 큐 또는 카프카와 같은 브로커다.
39+
이를 통해 아래 그림처럼 프로듀서와 컨슈머 간의 직접적인 의존성이 제거되어 **결합도가 낮아진다.**
40+
41+
![](/assets/img/kafka/Kafka-Why-and-Concept-2.png)
42+
43+
그러나 여기서 또 다른 문제가 발생할 수 있다. 모니터링 지표, 서버 로그, 사용자 클릭 정보 등 **데이터의 종류**에 따라 각각 별개의 메시징 시스템을 구축하는 것이다.
44+
이는 결국 아래 그림과 같이 여러 개의 시스템을 **중복**으로 관리해야 하는 비효율을 초래한다.
45+
46+
![](/assets/img/kafka/Kafka-Why-and-Concept-3.png)
47+
48+
카프카는 이러한 문제를 해결하기 위해 등장한 `중앙 집중형 발행/구독 시스템`이다. (`분산 스트리밍 플랫폼` 이라고 부르기도 한다.)
49+
다양한 종류의 데이터를 모두 처리할 수 있는, 즉 데이터 허브(Data Hub) 역할을 수행한다.
50+
51+
결론적으로 카프카는 다음과 같은 강력한 특징 때문에 사용된다.
52+
53+
* **다수의 프로듀서와 다수의 컨슈머**: 여러 시스템이 동시에 데이터를 보내고, 여러 시스템이 간섭 없이 각자 필요한 데이터를 소비할 수 있다.
54+
55+
* **디스크 기반 데이터 보존**: 데이터를 `디스크`에 안전하게 보존하므로, 컨슈머가 일시적으로 중단되거나 느려져도 데이터 유실 없이 나중에 처리할 수 있다.
56+
57+
* **확장성과 고성능**: 데이터양이 급증하더라도 브로커를 추가하는 방식으로 손쉽게 수평 확장이 가능하며, 높은 처리량과 낮은 지연 시간을 보장한다.
58+
59+
60+
## 카프카 핵심 개념
61+
62+
### 메시지 (Message)
63+
64+
* 카프카에서 다루는 데이터의 기본 단위다.
65+
66+
* 단순한 **바이트 배열** 로, 특정 형식이나 의미를 갖지 않는다.
67+
68+
* 메시지는 **키(Key)와 밸류(Value)** 로 구성된다.
69+
70+
* 키는 메시지를 어느 파티션에 저장할지 결정하는 데 사용된다.
71+
72+
### 스키마 (Schema)
73+
74+
* 메시지의 구조를 정의하는 형식이다. 카프카 자체는 메시지를 바이트 배열로만 보지만, 데이터를 올바르게 해석하기 위해 스키마를 사용하는 것을 권장한다.
75+
76+
* 프로듀서와 컨슈머가 스키마를 통해 데이터를 **일관된 형식**으로 주고받을 수 있어 서로 독립적으로 개발 및 변경이 가능하다. (e.g. JSON, Avro)
77+
78+
* 이를 통해 프로듀서와 컨슈머의 결합을 더욱 낮추는 핵심적인 역할을 한다
79+
80+
### 토픽 (Topic)과 파티션 (Partition)
81+
82+
* 메시지를 구분하는 카테고리를 `토픽` 이라고 한다. 데이터베이스의 테이블이나 파일 시스템의 폴더와 유사하다.
83+
84+
* 토픽은 하나 이상의 **파티션**으로 나뉜다. 파티션은 하나의 로그 파일과 같다.
85+
86+
* 메시지는 파티션에 추가(append-only) 방식으로 저장된다.
87+
88+
* 메시지의 순서는 **단일 파티션 내** 에서만 보장된다. 토픽 전체에 대한 순서는 보장되지 않는다.
89+
90+
* 파티션을 통해 데이터를 분산 저장하여 확장성과 가용성을 높인다. (아래 그림 참고)
91+
92+
![](/assets/img/kafka/Kafka-Why-and-Concept-4.png)
93+
94+
### 프로듀서 (Producer)와 컨슈머 (Consumer)
95+
96+
* `프로듀서`는 새로운 메시지를 생성하여 특정 토픽으로 보내는 역할을 한다.
97+
98+
* `컨슈머`는 특정 토픽에서 메시지를 읽어오는 역할을 한다.
99+
100+
* 컨슈머는 `컨슈머 그룹(Consumer Group)`에 속해서 동작한다.
101+
102+
* 아래 그림과 같이, 하나의 파티션은 컨슈머 그룹 내에서 **오직 하나의 컨슈머에 의해서**만 소비된다. 이를 통해 메시지 처리를 병렬로 수행할 수 있다.
103+
104+
![](/assets/img/kafka/Kafka-Why-and-Concept-5.png)
105+
106+
### 브로커 (Broker)와 클러스터 (Cluster)
107+
108+
* 카프카 서버 하나를 `브로커`라고 부른다.
109+
110+
* 브로커는 프로듀서로부터 메시지를 받아 저장하고, 컨슈머의 요청에 따라 메시지를 전달한다.
111+
112+
* 여러 브로커가 모여 하나의 **클러스터** 를 구성한다.
113+
114+
* 클러스터 내의 브로커 중 하나는 **컨트롤러(Controller) 역할** 을 맡아 다른 브로커들을 관리한다.
115+
116+
* 아래 그림은 각 파티션이 하나의 리더(Leader) 브로커와 하나 이상의 팔로워(Follower) 브로커로 복제되어, 리더 브로커에 장애 발생 시 데이터 유실 없이 서비스를 지속하는 모습을 보여준다.
117+
118+
![](/assets/img/kafka/Kafka-Why-and-Concept-6.png)
119+
120+
### 오프셋 (Offset)
121+
122+
* 파티션에 저장된 각 메시지의 **고유한 순번**을 나타내는 정수 값이다.
123+
124+
* 컨슈머는 자신이 **어디까지 메시지를 읽었는지 `오프셋`을 통해 기록** 한다.
125+
126+
* 이를 통해 컨슈머에 장애가 발생했다가 복구되어도 마지막으로 읽은 위치부터 다시 작업을 이어갈 수 있다.
127+
128+
### 보존 (Retention)
129+
130+
* 카프카가 메시지를 얼마나 오랫동안 디스크에 보관할지를 정하는 정책이다.
131+
132+
* 메시지를 특정 시간(예: 7일) 또는 파티션의 크기(예: 1GB) 기준으로 보존할 수 있다.
133+
134+
* 이 보존 정책 덕분에 컨슈머가 실시간으로 동작하지 않아도 데이터가 유실되지 않으며, 필요할 때 언제든 과거의 데이터를 소비할 수 있다. 이는 카프카의 핵심적인 내구성(durability) 기능이다.
135+
136+
## References
137+
138+
* [카프카 핵심 가이드](https://product.kyobobook.co.kr/detail/S000201464167?utm_source=google&utm_medium=cpc&utm_campaign=googleSearch&gad_source=1)

_posts/2025-07-24-Kafka-Producer.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ author: devFancy
77
* content
88
{:toc}
99

10-
1110
> 이 글은 [카프카 핵심 가이드](https://product.kyobobook.co.kr/detail/S000201464167?utm_source=google&utm_medium=cpc&utm_campaign=googleSearch&gad_source=1) 책을 읽고 정리한 글입니다.
1211
>
1312
> 이 글에서 다루는 모든 코드는 [깃허브](https://github.com/devFancy/springboot-coupon-system)에서 확인하실 수 있습니다.
@@ -70,7 +69,7 @@ author: devFancy
7069

7170
* 브로커는 메시지를 성공적으로 받으면 토픽, 파티션, 오프셋 정보가 담긴 메타데이터(Metadata)를 반환한다.
7271

73-
* 만약 실패하면 에러를 반환하며, 프로듀서는 설정에 따라 몇 번 더 재전송을 시도할 수 있다.
72+
* 만약 실패하면 에러를 반환하며, 프로듀서는 설정에 따라 몇 번 더 재전송을 시도한다.
7473

7574

7675
## 프로듀서를 생성하기 위한 필수 옵션
@@ -149,7 +148,7 @@ public class KafkaProducerConfig {
149148

150149
* 비동기 전송 (Asynchronous send)
151150

152-
* `send()` 메서드에 **콜백(Callback) 함수**를 함께 전달하는 방식이다. 브로커로부터 응답이 오면 미리 지정한 콜백 함수가 실행된다. **애플리케이션을 차단하지 않으면서도 전송 결과를 확실하게 처리**할 수 있어 가장 널리 사용된다.
151+
* `send()` 메서드에 **콜백(Callback) 함수**를 함께 전달하는 방식이다. 브로커로부터 응답이 오면 미리 지정한 콜백 함수가 실행된다. **애플리케이션을 차단하지 않으면서도 전송 결과를 확실하게 처리**할 수 있어 가장 널리 사용하는 방식이다.
153152

154153

155154
```java
@@ -170,9 +169,9 @@ public class KafkaTemplate<K, V> implements KafkaOperations<K, V>, ApplicationCo
170169

171170
* 참고: Spring Kafka의 `KafkaTemplate.send()` 메서드는 기본적으로 `CompletableFuture` (또는 이전 버전의 `ListenableFuture`)를 반환하여 비동기적으로 동작한다.
172171

173-
* 따라서 `send()`만 호출하고 반환된 `Future` 객체를 처리하지 않으면 겉보기에는 "파이어 앤 포겟"처럼 보일 수 있다.
172+
* 따라서 `send()`만 호출하고 반환된 `Future` 객체를 처리하지 않으면 겉보기에는 '파이어 앤 포겟'처럼 보일 수 있다.
174173

175-
* 하지만 실제로는 백그라운드에서 비동기 전송이 이루어지고 있으며, 명시적으로 `whenComplete`와 같은 콜백을 등록하여 성공 또는 실패를 처리하면 완전한 "비동기 전송" 방식으로 활용할 수 있다.
174+
* 하지만 실제로는 백그라운드에서 비동기 전송이 이루어지고 있으며, 명시적으로 `whenComplete`와 같은 콜백을 등록하여 성공 또는 실패를 처리하면 완전한 '비동기 전송' 방식으로 활용할 수 있다.
176175

177176

178177
쿠폰 시스템의 경우, 사용자가 쿠폰 발급 버튼을 눌렀을 때 즉시 "`쿠폰 발급 요청이 처리 중입니다`" 라고 응답하고 실제 발급 처리는 백그라운드에서 수행하는 것이 좋다. 이는 비동기 전송 방식에 가장 적합한 시나리오다.
@@ -337,7 +336,7 @@ public class CouponIssueScheduler {
337336

338337
* 이를 통해 '최소 한 번 전송(At-Least-Once)'에서 **'정확히 한 번 전송(Exactly-Once)'에 가까운 효과**를 낼 수 있다.
339338

340-
* 참고: `enable.idempotence=true`로 설정하면, 카프카는 신뢰도를 보장하기 위해 내부적으로 다른 주요 설정값들을 안전한 값으로 강제한다.
339+
* 참고: `enable.idempotence=true`로 설정하면, 카프카는 신뢰도를 보장하기 위해 내부적으로 다른 주요 설정값들을 안전한 값으로 강제하므로, 신뢰성이 중요한 대부분의 실무 환경에서는 이 옵션을 true로 설정하는 것이 좋다.
341340

342341
* (`retries`는 Integer.MAX_VALUE로, `acks`는 all로, `max.in.flight.requests.per.connection`은 5 이하로 유지).
343342

@@ -388,7 +387,7 @@ public class CouponIssueScheduler {
388387

389388
* `retries`는 기본값(사실상 무한)으로 두는 방식이다.
390389

391-
* 이렇게 하면 프로듀서는 주어진 최종 마감 시간 안에서 스스로 끈기 있게 재시도를 수행하므로, 개발자가 복잡한 재시도 로직을 계산할 필요가 없어진다.
390+
* 이렇게 하면 프로듀서는 주어진 최종 마감 시간 안에서 스스로 끈기 있게 재시도를 수행하므로, 개발자가 복잡한 재시도 로직을 계산할 필요가 없어지는 장점이 있다.
392391

393392
### 4. 데이터 포맷 설정 (Serializer)
394393

@@ -449,7 +448,7 @@ public class KafkaProducerConfig {
449448
// 따라서 실질적인 재시도 제어는 'delivery.timeout.ms'가 담당하게 된다.
450449
config.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true);
451450

452-
// 재시도 횟수: 일시적인 네트워크 문제나 브로커 장애 시 메시지를 재전송할 최대 횟수이다
451+
// 재시도 횟수: 일시적인 네트워크 문제나 브로커 장애 시 메시지를 재전송할 최대 횟수다.
453452
// 멱등성 옵션이 활성화되면 이 설정은 무시되고, 내부적으로 Integer.MAX_VALUE로 설정되므로 주석 처리한다.
454453
//config.put(ProducerConfig.RETRIES_CONFIG, 3);
455454

@@ -472,7 +471,7 @@ public class KafkaProducerConfig {
472471
return new DefaultKafkaProducerFactory<>(config);
473472
}
474473

475-
// 카프카 토픽에 데이터를 전송하기 위해 사용할 Kafka Template 을 생성
474+
// 카프카 토픽에 데이터를 전송하기 위해 사용할 KafkaTemplate을 생성한다.
476475
@Bean
477476
public KafkaTemplate<String, Object> kafkaTemplate() {
478477
return new KafkaTemplate<>(producerFactory());
@@ -490,7 +489,7 @@ public class KafkaProducerConfig {
490489

491490
#### 1. 잘못된 가정과 첫 번째 테스트
492491

493-
만약 우리가 `enable.idempotence=true``retries=3`을 동시에 설정했다면, 어떤 일이 벌어질까?
492+
만약 `enable.idempotence=true``retries=3`을 동시에 설정했다면, 어떤 일이 벌어질까?
494493

495494
아래는 이 상태를 검증하는 초기 테스트 코드다.
496495

@@ -518,7 +517,7 @@ class KafkaProducerConfigTest {
518517

519518
![](/assets/img/kafka/Kafka-Producer-Test-1.png)
520519

521-
놀랍게도 이 테스트는 성공한다. 여기서 "멱등성이 켜지면 `retries``Integer.MAX_VALUE`로 강제된다고 했는데 왜 테스트는 통과하지?" 라는 의문이 생긴다.
520+
놀랍게도 이 테스트는 성공한다. 여기서 '멱등성이 켜지면 `retries``Integer.MAX_VALUE`로 강제된다고 했는데 왜 테스트는 통과하지?' 라는 의문이 생긴다.
522521

523522
그 이유는 이 테스트가 '실제 동작하는 클라이언트'가 아닌, Spring의 `ProducerFactory`가 보관 중인 **'원본 설정값'** 을 확인하기 때문이다.
524523

@@ -531,7 +530,7 @@ class KafkaProducerConfigTest {
531530

532531
이러한 혼란을 없애고 코드의 의도를 명확히 하기 위해, `KafkaProducerConfig``retries` 설정을 주석 처리했다.
533532

534-
우리의 의도는 **"멱등성 옵션을 켤 것이므로, `retries`는 따로 설정하지 않고 카프카의 기본 정책에 맡긴다"** 이다.
533+
필자의 의도는 **"멱등성 옵션을 켤 것이므로, `retries`는 따로 설정하지 않고 카프카의 기본 정책에 맡긴다"** 이다.
535534

536535
따라서 최종 테스트 코드는 `retries` 값이 `3`임을 확인하는 대신, 해당 설정이 **'없음'(null)을 확인**하는 것이 정확하다.
537536

@@ -567,3 +566,10 @@ class KafkaProducerConfigTest {
567566
이처럼 설정과 테스트를 함께 뜯어보는 과정을 통해, 프로듀서의 동작 원리를 좀 더 깊이 이해하고 코드의 의도를 명확히 다듬어볼 수 있었다.
568567

569568
아직 완벽하게 이해할 수 있다고 보기는 어렵지만 차근차근 개념과 실무 경험을 쌓아가보자.
569+
570+
571+
## References
572+
573+
* [카프카 핵심 가이드](https://product.kyobobook.co.kr/detail/S000201464167?utm_source=google&utm_medium=cpc&utm_campaign=googleSearch&gad_source=1)
574+
575+
* [[공식문서] Kafka 3.3 Producer Configs](https://kafka.apache.org/documentation/#producerconfigs)
248 KB
Loading
230 KB
Loading
323 KB
Loading
236 KB
Loading
283 KB
Loading
299 KB
Loading

0 commit comments

Comments
 (0)