Kafka ํ๋ก๋์ ๊ตฌํํ๊ธฐ: ๋ฉ์์ง ์ ์ก๋ถํฐ ์ฌ์๋ ์ฒ๋ฆฌ๊น์ง
Apache Kafka ๋ ๋๊ท๋ชจ์ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ์ฒ๋ฆฌํ๋๋ฐ ๋งค์ฐ ์ ์ฉํ ๋ถ์ฐ ๋ฉ์์ง ์์คํ ์ ๋๋ค. ๊ทธ ์ค์์๋ Kafka ํ๋ก๋์ ๋ ๋ฐ์ดํฐ๋ฅผ Kafka ํ ํฝ ์ผ๋ก ์ ์กํ๋ ํต์ฌ ์ญํ ์ ๋ด๋นํฉ๋๋ค. ์ด๋ฒ ํฌ์คํ ์์๋ Kafka ํ๋ก๋์ ์๋น์ค ์์ฑ , ๋ฉ์์ง ์ ์ก ๋ฐฉ๋ฒ , Ack(์ํฌ๋ ธ๋ ์ง๋จผํธ) ์ฒ๋ฆฌ , ์ฌ์๋์ ๋ฒํผ๋ง ์ค์ ๊น์ง ๋ค๋ฃน๋๋ค. ์ค๋ฌด์์ ์์ฃผ ์ฌ์ฉํ๋ ์์ ์ ํจ๊ป ๋ฐ๋ผ ํ๋ฉด์ ์ฝ๊ฒ ์ดํดํ ์ ์์ต๋๋ค.
1. Kafka ํ๋ก๋์ ์๋น์ค ์์ฑ
Kafka ํ๋ก๋์ ์๋น์ค๋ ์คํ๋ง ๋ถํธ ์์ KafkaTemplate ์ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค. KafkaTemplate ์ ๋ฉ์์ง๋ฅผ Kafka๋ก ์ ์กํ๋ ๋ฐ ํ์ํ ๋ชจ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
@Service
public class KafkaProducerService {
private static final Logger logger = LoggerFactory.getLogger(KafkaProducerService.class);
private final KafkaTemplate<String, String> kafkaTemplate;
@Autowired
public KafkaProducerService(KafkaTemplate<String, String> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
public void sendMessage(String message) {
logger.info(String.format("#### -> Producing message -> %s", message));
kafkaTemplate.send("my_topic", message);
}
}
์ค๋ช :
- KafkaTemplate ์ ์ฃผ์ ๋ฐ์ ๋ฉ์์ง๋ฅผ Kafka๋ก ์ ์กํฉ๋๋ค.
sendMessage
๋ฉ์๋๋ ๋ฉ์์ง๋ฅผ my_topic ์ผ๋ก ์ ์กํ๋ฉฐ, ๋ก๊ทธ๋ฅผ ํตํด ์ ์ก๋ ๋ฉ์์ง๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
2. Kafka ํ ํฝ์ผ๋ก ๋ฉ์์ง ์ ์กํ๊ธฐ
Kafka์์๋ ํ๋ก๋์๋ฅผ ํตํด ํน์ ํ ํฝ(topic) ์ผ๋ก ๋ฉ์์ง๋ฅผ ์ ์กํฉ๋๋ค. ์ฌ๊ธฐ์๋
KafkaTemplate.send()
๋ฉ์๋๋ฅผ ํตํด ๋ฉ์์ง๋ฅผ ํ ํฝ์ผ๋ก ์ ์กํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช
ํฉ๋๋ค.
๋ฉ์์ง ์ ์ก ์์
@RestController
@RequestMapping("/api/kafka")
public class KafkaController {
private final KafkaProducerService producerService;
@Autowired
public KafkaController(KafkaProducerService producerService) {
this.producerService = producerService;
}
@PostMapping("/publish")
public ResponseEntity<String> sendMessageToKafkaTopic(@RequestParam("message") String message) {
producerService.sendMessage(message);
return ResponseEntity.ok("Message sent to Kafka topic: " + message);
}
}
์ค๋ช :
- ์ฌ์ฉ์๊ฐ HTTP POST ์์ฒญ์ผ๋ก ๋ฉ์์ง๋ฅผ ์ ์กํ๋ฉด, ํด๋น ๋ฉ์์ง๊ฐ
my_topic
์ผ๋ก ์ ์ก๋ฉ๋๋ค. - ์ ์ก์ด ์๋ฃ๋๋ฉด ์ฑ๊ณต ์๋ต์ ๋ฐํํฉ๋๋ค.
์ ๋ ฅ ์์ :
- HTTP ์์ฒญ:
POST /api/kafka/publish?message=HelloKafka
- ๊ฒฐ๊ณผ: Kafka ํ ํฝ์ “HelloKafka” ๋ฉ์์ง๊ฐ ์ ์ก๋จ.
3. ํ๋ก๋์ ์ํฌ๋ ธ๋ ์ง๋จผํธ(Ack) ์ฒ๋ฆฌ
Kafka ํ๋ก๋์๋ ๋ฉ์์ง๋ฅผ ๋ธ๋ก์ปค๋ก ์ ์กํ ํ Ack(ํ์ธ ์๋ต) ์ ๋ฐ์ต๋๋ค. ์ด๋ฅผ ํตํด ๋ฉ์์ง๊ฐ ์ฑ๊ณต์ ์ผ๋ก ๋ธ๋ก์ปค์ ๋์ฐฉํ๋์ง ํ์ธํ ์ ์์ต๋๋ค. ACK ์ค์ ์ ๋ฉ์์ง ์ ๋ฌ ๋ณด์ฅ์ ์ํด ์ค์ํ๋ฉฐ, ์๋์ ๊ฐ์ ์ต์
์ด ์์ต๋๋ค:
-
acks=0
: ๋ธ๋ก์ปค๊ฐ Ack๋ฅผ ๋ณด๋ด์ง ์์(๋ฎ์ ์์ ์ฑ, ๋น ๋ฅธ ์ฑ๋ฅ).
-
acks=1
: ๋ฆฌ๋ ๋ธ๋ก์ปค์์๋ง ๋ฉ์์ง๋ฅผ ๊ธฐ๋กํ๋ฉด Ack ์ ์ก.
-
acks=all
: ๋ชจ๋ ํ๋ก์ ๋ธ๋ก์ปค์ ๋ฉ์์ง๊ฐ ๊ธฐ๋ก๋ ํ Ack ์ ์ก(๊ฐ์ฅ ๋์ ์์ ์ฑ).
Ack ์ค์ ์์ (
application.yml
)
spring:
kafka:
producer:
acks: all
retries: 3
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
์ค๋ช :
- acks: all : ๋ชจ๋ ๋ธ๋ก์ปค์ ๋ฉ์์ง๊ฐ ์ ์ฅ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ํ ์ฑ๊ณต ์ฒ๋ฆฌ.
- retries: 3 : ๋ฉ์์ง ์ ์ก ์คํจ ์ 3๋ฒ๊น์ง ์ฌ์๋.
4. ํ๋ก๋์ ์ฌ์๋์ ๋ฒํผ๋ง ์ค์
Kafka๋ ๋ฉ์์ง ์ ์ก ์ค ๋ฐ์ํ ์ ์๋ ๋คํธ์ํฌ ์ค๋ฅ ๋ ๋ธ๋ก์ปค ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฌ์๋ ๋ฉ์ปค๋์ฆ ์ ์ ๊ณตํฉ๋๋ค. ๋ํ, ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํด ๋ฉ์์ง ๋ฒํผ๋ง ์ ํตํด ํ ๋ฒ์ ์ฌ๋ฌ ๋ฉ์์ง๋ฅผ ์ ์กํ ์ ์์ต๋๋ค.
์ฌ์๋ ๋ฐ ๋ฒํผ๋ง ์ค์ ์์ (
application.yml
)
spring:
kafka:
producer:
retries: 5 # ๋ฉ์์ง ์ ์ก ์คํจ ์ ์ต๋ 5๋ฒ ์ฌ์๋
batch-size: 16384 # ๋ฉ์์ง ๋ฐฐ์น ํฌ๊ธฐ (16KB)
linger-ms: 10 # ๋ฐฐ์น ์ ์ก์ ์ํด 10ms ๋๊ธฐ
buffer-memory: 33554432 # ๋ฒํผ ๋ฉ๋ชจ๋ฆฌ ํฌ๊ธฐ (32MB)
์ค๋ช :
- retries : ๋ฉ์์ง ์ ์ก ์คํจ ์ ์ต๋ 5๋ฒ๊น์ง ์ฌ์๋ํฉ๋๋ค.
- batch-size : ๋ฐฐ์น๋ก ์ ์กํ ๋ฉ์์ง ํฌ๊ธฐ๋ฅผ 16KB๋ก ์ค์ ํฉ๋๋ค.
- linger-ms : ๋ฐฐ์น ์ ์ก์ ์ํด ๋ฉ์์ง๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์๊ฐ์ ๋๋ค. 10ms ๋์ ๋๊ธฐํ์ฌ ์ฌ๋ฌ ๋ฉ์์ง๋ฅผ ๋ชจ์ ์ ์กํฉ๋๋ค.
- buffer-memory : ๋ฉ์์ง๋ฅผ ์ ์กํ๊ธฐ ์ ์ ์์๋ก ์ ์ฅํ ๋ฉ๋ชจ๋ฆฌ ํฌ๊ธฐ๋ฅผ 32MB๋ก ์ค์ ํฉ๋๋ค.
Kafka ํ๋ก๋์ ํ์ฉ ํธ๋ ๋ ๋ฐ ํต๊ณ
์ต๊ทผ ์ค์๊ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ฐ ํ์ํ ์ฐ์ ์์ Kafka ํ๋ก๋์๋ ํ์์ ์ธ ๋๊ตฌ๋ก ์๋ฆฌ ์ก์์ต๋๋ค. ํนํ ์ด๋ฒคํธ ๊ธฐ๋ฐ ์ํคํ ์ฒ ์์ ์ค์ํ ์ญํ ์ ํ๋ฉฐ, ๊ธ์ต ์๋น์ค , IoT , ๋ก๊ทธ ์์ง ๊ณผ ๊ฐ์ ๋ถ์ผ์์ ๊ด๋ฒ์ํ๊ฒ ์ฌ์ฉ๋๊ณ ์์ต๋๋ค.
2023๋ ๊ฐ๋ฐ์ ์กฐ์ฌ ์ ๋ฐ๋ฅด๋ฉด, ๋ง์ ๊ฐ๋ฐ์๋ค์ด ๋๊ท๋ชจ ์ค์๊ฐ ๋ฐ์ดํฐ ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ Kafka ํ๋ก๋์๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ, ๊ทธ ์ค 80% ์ด์์ด ๋ฐ์ดํฐ ์์ค ์์ด ์์ ์ ์ผ๋ก ์ ์ก ์ ๊ตฌํํ๊ณ ์์ต๋๋ค.
์์ฃผ ๋ฌป๋ ์ง๋ฌธ (FAQ)
Q1. Kafka ํ๋ก๋์์์ acks ์ค์ ์ ์ ์ค์ํ๊ฐ์?
A1. acks ์ค์ ์ ๋ฉ์์ง๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์ ์ก๋์๋์ง ํ์ธํ๋ ๋ฐฉ๋ฒ์
๋๋ค.
acks=all
๋ก ์ค์ ํ๋ฉด ๋ชจ๋ ๋ธ๋ก์ปค๊ฐ ๋ฉ์์ง๋ฅผ ์ ์ฅํ ํ Ack๋ฅผ ๋ณด๋ด๋ฏ๋ก ๋ฐ์ดํฐ ์์ค ๊ฐ๋ฅ์ฑ์ ์ต์ํํ ์ ์์ต๋๋ค.
Q2. Kafka ํ๋ก๋์์์ ์ฌ์๋ ํ์๋ ๋ช ๋ฒ์ผ๋ก ์ค์ ํด์ผ ํ๋์?
A2. ์ผ๋ฐ์ ์ผ๋ก 3~5ํ ์ ๋๋ก ์ค์ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋๋ฌด ๋ง์ผ๋ฉด ์ฑ๋ฅ์ ์ํฅ์ ์ค ์ ์์ผ๋ฏ๋ก, ์ ์ ํ ์ฌ์๋ ํ์๋ฅผ ์ค์ ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
Q3. Kafka์์ ๋ฐฐ์น ์ ์ก์ด๋ ๋ฌด์์ธ๊ฐ์?
A3. ๋ฐฐ์น ์ ์ก ์ ์ฌ๋ฌ ๋ฉ์์ง๋ฅผ ๋ชจ์์ ํ ๋ฒ์ ์ ์กํ๋ ๋ฐฉ์์
๋๋ค. ์ด ๋ฐฉ์์ ๋คํธ์ํฌ ํธ๋ํฝ์ ์ค์ด๊ณ , ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
Q4. Kafka ํ๋ก๋์์์ ๋ฒํผ ๋ฉ๋ชจ๋ฆฌ ์ค์ ์ ๋ฌด์์ ์๋ฏธํ๋์?
A4. ๋ฒํผ ๋ฉ๋ชจ๋ฆฌ ๋ ํ๋ก๋์๊ฐ ๋ฉ์์ง๋ฅผ ๋ธ๋ก์ปค๋ก ์ ์กํ๊ธฐ ์ ์ ์ผ์์ ์ผ๋ก ๋ฉ์์ง๋ฅผ ์ ์ฅํ๋ ๊ณต๊ฐ์
๋๋ค. ๋ฒํผ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ถฉ๋ถํ ํฌ๋ฉด ๋ ๋ง์ ๋ฉ์์ง๋ฅผ ๋ชจ์ ํ ๋ฒ์ ์ ์กํ ์ ์์ต๋๋ค.
Q5. Kafka ํ๋ก๋์๋ฅผ ํตํด ์ฌ๋ฌ ํ ํฝ์ ๋ฉ์์ง๋ฅผ ๋ณด๋ผ ์ ์๋์?
A5. ๋ค, ๊ฐ๋ฅํฉ๋๋ค. KafkaTemplate ์
send
๋ฉ์๋์์ ํ ํฝ ์ด๋ฆ์ ๋ค๋ฅด๊ฒ ์ง์ ํ๋ฉด ์ฌ๋ฌ ํ ํฝ์ ๋ฉ์์ง๋ฅผ ์ ์กํ ์ ์์ต๋๋ค.
๋๊ธ