Ver3.0 ๐ RabbitMQ vs ์ํ์น ์นดํ์นด: ๋ฉ์์ง ํ์ ์ด๋ฒคํธ ์คํธ๋ฆฌ๋ฐ ํ๋ซํผ์ ๋ชจ๋ ๊ฒ

๐ RabbitMQ vs ์ํ์น ์นดํ์นด: ๋ฉ์์ง ํ์ ์ด๋ฒคํธ ์คํธ๋ฆฌ๋ฐ ํ๋ซํผ์ ๋ชจ๋ ๊ฒ
์น๊ตฌ์ฒ๋ผ ์ฝ๊ฒ ํ์ด๋ณด๋ ๋ฉ์์ง ์์คํ ์ ์ธ๊ณ
๐ฌ "์ผ, ์ฐ๋ฆฌ ์๋น์ค ํธ๋ํฝ์ด ๊ฐ์๊ธฐ ํญ์ฆํ๋๋ฐ ์๋ฒ๊ฐ ๋ค์ด๋์ด!"
๐ "์ฃผ๋ฌธ ๋ฐ์ดํฐ๊ฐ ์ค์๊ฐ์ผ๋ก ์์ด๋๋ฐ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ์ง?"
๐ "๋ง์ดํฌ๋ก์๋น์ค๋ผ๋ฆฌ ์ด๋ป๊ฒ ํต์ ์์ผ์ผ ์์ ์ ์ผ๊น?"
์ด๋ฐ ๊ณ ๋ฏผ ํ ๋ฒ์ฏค ํด๋ดค์ง? ์ค๋์ ํ๋ ์ํํธ์จ์ด ์ํคํ
์ฒ์์ ๋นผ๋์ ์ ์๋ ๋ ๊ฐ์ง ํต์ฌ ๊ธฐ์ , RabbitMQ์ ์ํ์น ์นดํ์นด(Apache Kafka)์ ๋ํด ์์ ์ ๋ณตํด๋ณผ ๊ฑฐ์ผ! ๐
๐ ๋ฉ์์ง ์์คํ ์ด ๋ญ๊ธธ๋?
๋ณธ๊ฒฉ์ ์ผ๋ก ๋ค์ด๊ฐ๊ธฐ ์ ์, ๋ฉ์์ง ์์คํ
์ด ์ ํ์ํ์ง๋ถํฐ ์ดํดํด๋ณด์!
์๋ ์์ ์๋ ์๋น์ค๊ฐ ๋จ์ํ์ด. ํ๋์ ๊ฑฐ๋ํ ์ ํ๋ฆฌ์ผ์ด์
(๋ชจ๋๋ฆฌ์)์ด ๋ชจ๋ ๊ฑธ ์ฒ๋ฆฌํ์ง. ๊ทผ๋ฐ ์๋น์ค๊ฐ ์ปค์ง๋ฉด์ ๋ฌธ์ ๊ฐ ์๊ฒผ์ด:
๐ฅ ์ ํต์ ์ธ ๋ฐฉ์์ ๋ฌธ์ ์ ๋ค:
โข ํ ๋ถ๋ถ์ ๋ฌธ์ ๊ฐ ์๊ธฐ๋ฉด ์ ์ฒด ์์คํ
์ด ๋ค์ด
โข ํธ๋ํฝ ํญ์ฆ ์ ์๋ฒ๊ฐ ๋ฒํฐ์ง ๋ชปํจ
โข ์๋น์ค ๊ฐ ๊ฐํ ๊ฒฐํฉ์ผ๋ก ์ ์ง๋ณด์ ์ง์ฅ
โข ์ค์๊ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๊ฐ ์ด๋ ค์
๊ทธ๋์ ๋ฑ์ฅํ ๊ฒ ๋ฐ๋ก ๋ฉ์์ง ์์คํ
์ด์ผ! ๐ฏ
๐ก ๋ฉ์์ง ์์คํ
์ ํต์ฌ ๊ฐ๋
๋ฉ์์ง ์์คํ
์ ์ค๊ฐ ๋ค๋ฆฌ ์ญํ ์ ํด. ์ ํ๋ฆฌ์ผ์ด์
๋ค์ด ์ง์ ํต์ ํ๋ ๊ฒ ์๋๋ผ, ๋ฉ์์ง๋ฅผ ์ค๊ฐ์ ์๋ ์์คํ
์ ๋ณด๋ด๊ณ ๋ฐ๋ ๊ฑฐ์ง.
๋ฐ์ ์(Producer) โ ๋ฉ์์ง ์์คํ
โ ์์ ์(Consumer)
์ด๋ ๊ฒ ํ๋ฉด ๋ฐ์ ์์ ์์ ์๊ฐ ์๋ก๋ฅผ ๋ชฐ๋ผ๋ ๋ผ! ์ด๊ฑธ ๋์จํ ๊ฒฐํฉ(Loose Coupling)์ด๋ผ๊ณ ํด. ๐
๐ฐ RabbitMQ: ๋๋ํ ๋ฉ์์ง ๋ฐฐ๋ฌ๋ถ
RabbitMQ๋ 2007๋
์ ํ์ํ ๋ฉ์์ง ๋ธ๋ก์ปค์ผ. ์ด๋ฆ์์ ์ ์ ์๋ฏ์ด ํ ๋ผ์ฒ๋ผ ๋น ๋ฅด๊ณ ๋ฏผ์ฒฉํ๊ฒ ๋ฉ์์ง๋ฅผ ์ ๋ฌํ๋ ๊ฒ ํน์ง์ด์ง!
๐ฏ RabbitMQ์ ํ์ ๋ฐฐ๊ฒฝ
RabbitMQ๋ AMQP(Advanced Message Queuing Protocol)๋ฅผ ๊ตฌํํ ์คํ์์ค ๋ฉ์์ง ๋ธ๋ก์ปค์ผ. Erlang ์ธ์ด๋ก ์์ฑ๋์๋๋ฐ, Erlang์ ํต์ ์์คํ
์ ์ํด ๋ง๋ค์ด์ง ์ธ์ด๋ผ์ ์์ ์ฑ๊ณผ ๋์์ฑ ์ฒ๋ฆฌ๊ฐ ๋ฐ์ด๋!
โจ ์ฌ๋ฏธ์๋ ์ฌ์ค!
RabbitMQ์ ๋ก๊ณ ๊ฐ ํ ๋ผ์ธ ์ด์ ๋ ๋จ์ํ ๋น ๋ฅด๋ค๋ ์๋ฏธ๋ฟ๋ง ์๋๋ผ, ํ ๋ผ๊ฐ ๋ง์ด ๋ฒ์ํ๋ฏ์ด ๋ฉ์์ง๋ฅผ ์ฌ๋ฌ ๊ณณ์ผ๋ก ๋ณต์ ํด์ ๋ณด๋ผ ์ ์๋ค๋ ์๋ฏธ๋ ๋ด๊ฒจ์์ด!
๐๏ธ RabbitMQ์ ํต์ฌ ๊ตฌ์กฐ
RabbitMQ๋ฅผ ์ดํดํ๋ ค๋ฉด ๋ช ๊ฐ์ง ํต์ฌ ๊ฐ๋
์ ์์์ผ ํด:
1๏ธโฃ Producer (์์ฐ์)
๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ ์ ํ๋ฆฌ์ผ์ด์
์ด์ผ. ์ฃผ๋ฌธ ์์คํ
, ๊ฒฐ์ ์์คํ
๋ฑ์ด ๋ ์ ์์ง.
2๏ธโฃ Exchange (๊ตํ๊ธฐ)
์ด๊ฒ RabbitMQ์ ํต์ฌ์ด์ผ! ๋ฉ์์ง๋ฅผ ๋ฐ์์ ์ด๋ ํ๋ก ๋ณด๋ผ์ง ๊ฒฐ์ ํ๋ ๋ผ์ฐํฐ ์ญํ ์ ํด. ๋ง์น ์ฐ์ฒด๊ตญ์ ๋ถ๋ฅ ์์คํ
๊ฐ์ ๊ฑฐ์ง.
3๏ธโฃ Queue (ํ)
๋ฉ์์ง๊ฐ ์ค์ ๋ก ์ ์ฅ๋๋ ๊ณณ์ด์ผ. Consumer๊ฐ ๊ฐ์ ธ๊ฐ ๋๊น์ง ๋ฉ์์ง๋ฅผ ๋ณด๊ดํด.
4๏ธโฃ Consumer (์๋น์)
๋ฉ์์ง๋ฅผ ๋ฐ์์ ์ฒ๋ฆฌํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ด์ผ. ์ด๋ฉ์ผ ๋ฐ์ก ์๋น์ค, ์๋ฆผ ์๋น์ค ๋ฑ์ด ๋ ์ ์์ด.
5๏ธโฃ Binding (๋ฐ์ธ๋ฉ)
Exchange์ Queue๋ฅผ ์ฐ๊ฒฐํ๋ ๊ท์น์ด์ผ. "์ด๋ฐ ๋ฉ์์ง๋ ์ ํ๋ก ๋ณด๋ด!"๋ผ๊ณ ์ ์ํ๋ ๊ฑฐ์ง.
๐จ Exchange ํ์
์ ์ข
๋ฅ
RabbitMQ๋ 4๊ฐ์ง Exchange ํ์
์ ์ ๊ณตํด:
๐ Direct Exchange
๋ผ์ฐํ
ํค๊ฐ ์ ํํ ์ผ์นํ๋ ํ๋ก๋ง ๋ฉ์์ง๋ฅผ ๋ณด๋ด. ๊ฐ์ฅ ๋จ์ํ๊ณ ๋ช
ํํด!
์: "error" ํค๋ฅผ ๊ฐ์ง ๋ฉ์์ง๋ ์๋ฌ ๋ก๊ทธ ํ๋ก๋ง ์ ์ก
๐ Fanout Exchange
์ฐ๊ฒฐ๋ ๋ชจ๋ ํ์ ๋ฉ์์ง๋ฅผ ๋ธ๋ก๋์บ์คํธํด. ๋ผ์ฐํ
ํค๋ ๋ฌด์๋ผ!
์: ๊ณต์ง์ฌํญ์ ๋ชจ๋ ์ฌ์ฉ์์๊ฒ ์ ์ก
๐ Topic Exchange
ํจํด ๋งค์นญ์ผ๋ก ๋ผ์ฐํ
ํด. ์์ผ๋์นด๋(*์ #)๋ฅผ ์ฌ์ฉํ ์ ์์ด!
์: "log.error.*"๋ ๋ชจ๋ ์๋ฌ ๋ก๊ทธ๋ฅผ, "log.#"๋ ๋ชจ๋ ๋ก๊ทธ๋ฅผ ๋ฐ์
๐ Headers Exchange
๋ฉ์์ง ํค๋์ ์์ฑ์ ๊ธฐ๋ฐ์ผ๋ก ๋ผ์ฐํ
ํด. ๋ณต์กํ ์กฐ๊ฑด์ด ํ์ํ ๋ ์ฌ์ฉ!
๐ป RabbitMQ ์ค์ ์์
์ค์ ๋ก ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง ์ฝ๋๋ก ๋ณผ๊น? Python์ผ๋ก ๊ฐ๋จํ ์์ ๋ฅผ ๋ง๋ค์ด๋ณผ๊ฒ!
import pika
# RabbitMQ ์ฐ๊ฒฐ
connection = pika.BlockingConnection(
pika.ConnectionParameters('localhost')
)
channel = connection.channel()
# ํ ์ ์ธ
channel.queue_declare(queue='order_queue', durable=True)
# ๋ฉ์์ง ๋ฐ์ก
message = "์ฃผ๋ฌธ๋ฒํธ: 12345, ์ํ: ๋
ธํธ๋ถ, ์๋: 1"
channel.basic_publish(
exchange='',
routing_key='order_queue',
body=message,
properties=pika.BasicProperties(
delivery_mode=2, # ๋ฉ์์ง๋ฅผ ๋์คํฌ์ ์ ์ฅ
)
)
print(f"๋ฉ์์ง ์ ์ก ์๋ฃ: {message}")
connection.close()
import pika
def callback(ch, method, properties, body):
print(f"๋ฐ์ ๋ฉ์์ง: {body.decode()}")
# ์ฌ๊ธฐ์ ์ฃผ๋ฌธ ์ฒ๋ฆฌ ๋ก์ง ์คํ
print("์ฃผ๋ฌธ ์ฒ๋ฆฌ ์๋ฃ!")
ch.basic_ack(delivery_tag=method.delivery_tag)
connection = pika.BlockingConnection(
pika.ConnectionParameters('localhost')
)
channel = connection.channel()
channel.queue_declare(queue='order_queue', durable=True)
# Consumer ์ค์
channel.basic_qos(prefetch_count=1)
channel.basic_consume(
queue='order_queue',
on_message_callback=callback
)
print('๋ฉ์์ง ๋๊ธฐ ์ค...')
channel.start_consuming()
๐ ์ฝ๋ ์ค๋ช
durable=True: RabbitMQ ์๋ฒ๊ฐ ์ฌ์์๋์ด๋ ํ๊ฐ ์ฌ๋ผ์ง์ง ์์!
delivery_mode=2: ๋ฉ์์ง๋ฅผ ๋์คํฌ์ ์ ์ฅํด์ ์๋ฒ ์ฌ์์ ์์๋ ๋ณด์กด๋ผ!
prefetch_count=1: Consumer๊ฐ ํ ๋ฒ์ ํ๋์ ๋ฉ์์ง๋ง ์ฒ๋ฆฌํ๋๋ก ์ ํ!
basic_ack: ๋ฉ์์ง ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋์๋ค๊ณ RabbitMQ์ ์๋ ค์ค!
๐ฏ RabbitMQ์ ๊ฐ์
โ
๋ฉ์์ง ์ ๋ฌ ๋ณด์ฅ
RabbitMQ๋ ๋ฉ์์ง๊ฐ ํ์คํ ์ ๋ฌ๋๋๋ก ์ฌ๋ฌ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํด:
โข Publisher Confirms: ๋ฉ์์ง๊ฐ ํ์ ์ ์ฅ๋์๋์ง ํ์ธ
โข Consumer Acknowledgements: ๋ฉ์์ง๊ฐ ์ฒ๋ฆฌ๋์๋์ง ํ์ธ
โข ๋ฉ์์ง ์ง์์ฑ: ๋์คํฌ์ ์ ์ฅํด์ ์๋ฒ ์ฌ์์์๋ ์์
โ
์ ์ฐํ ๋ผ์ฐํ
๋ค์ํ Exchange ํ์
์ผ๋ก ๋ณต์กํ ๋ฉ์์ง ๋ผ์ฐํ
ํจํด ๊ตฌํ ๊ฐ๋ฅ!
โ
๊ด๋ฆฌ UI
์น ๊ธฐ๋ฐ ๊ด๋ฆฌ ์ฝ์์ด ๊ธฐ๋ณธ ์ ๊ณต๋ผ์ ๋ชจ๋ํฐ๋ง์ด ์ฌ์!
โ
๋ค์ํ ํ๋กํ ์ฝ ์ง์
AMQP, MQTT, STOMP ๋ฑ ์ฌ๋ฌ ํ๋กํ ์ฝ์ ์ง์ํด์ ๋ค์ํ ํ๊ฒฝ์์ ์ฌ์ฉ ๊ฐ๋ฅ!
โ
ํ๋ฌ๊ทธ์ธ ์ํ๊ณ
ํ์ํ ๊ธฐ๋ฅ์ ํ๋ฌ๊ทธ์ธ์ผ๋ก ํ์ฅํ ์ ์์ด!
๐ค RabbitMQ๋ ์ธ์ ์ฌ์ฉํ ๊น?
RabbitMQ๊ฐ ๋น์ ๋ฐํ๋ ์ํฉ๋ค์ ์์๋ณด์:
1๏ธโฃ ์์
ํ (Task Queue)
์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ์์
์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ฒ๋ฆฌํ ๋ ์๋ฒฝํด!
์: ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง, ๋์์ ์ธ์ฝ๋ฉ, ๋๋ ์ด๋ฉ์ผ ๋ฐ์ก
2๏ธโฃ ๋ง์ดํฌ๋ก์๋น์ค ํต์
์๋น์ค ๊ฐ ๋น๋๊ธฐ ํต์ ์ด ํ์ํ ๋ ์ต๊ณ ์ผ!
์: ์ฃผ๋ฌธ ์๋น์ค โ ์ฌ๊ณ ์๋น์ค โ ๋ฐฐ์ก ์๋น์ค
3๏ธโฃ ๋ณต์กํ ๋ผ์ฐํ
์ด ํ์ํ ๊ฒฝ์ฐ
๋ฉ์์ง๋ฅผ ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ค๋ฅธ ๊ณณ์ผ๋ก ๋ณด๋ด์ผ ํ ๋!
์: ๋ก๊ทธ ๋ ๋ฒจ์ ๋ฐ๋ผ ๋ค๋ฅธ ์ฒ๋ฆฌ (ERROR๋ ์๋ฆผ, INFO๋ ์ ์ฅ๋ง)
4๏ธโฃ ์ฐ์ ์์ ํ
์ค์ํ ๋ฉ์์ง๋ฅผ ๋จผ์ ์ฒ๋ฆฌํด์ผ ํ ๋!
์: VIP ๊ณ ๊ฐ์ ์ฃผ๋ฌธ์ ์ผ๋ฐ ๊ณ ๊ฐ๋ณด๋ค ๋จผ์ ์ฒ๋ฆฌ
๐ข ์ค์ ์ฌ์ฉ ์ฌ๋ก
Instagram: ์ฌ์ง ํํฐ๋ง๊ณผ ์๋ฆผ ์์คํ
์ RabbitMQ ์ฌ์ฉ
Reddit: ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ฒ๋ฆฌ์ ํ์ฉ
9GAG: ์ด๋ฏธ์ง ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ ์ฌ์ฉ
์ด๋ฐ ๋ํ ์๋น์ค๋ค์ด RabbitMQ๋ฅผ ์ ํํ ์ด์ ๋ ์์ ์ฑ๊ณผ ์ ์ฐ์ฑ ๋๋ฌธ์ด์ผ!
๐ Apache Kafka: ๋์ฉ๋ ์ด๋ฒคํธ ์คํธ๋ฆฌ๋ฐ์ ์ ์
์ด์ ์นดํ์นด ์ฐจ๋ก์ผ! ์นดํ์นด๋ 2011๋
LinkedIn์์ ๊ฐ๋ฐํด์ ์คํ์์ค๋ก ๊ณต๊ฐํ ๋ถ์ฐ ์ด๋ฒคํธ ์คํธ๋ฆฌ๋ฐ ํ๋ซํผ์ด์ผ.
๐ฏ Kafka์ ํ์ ์คํ ๋ฆฌ
LinkedIn์ด ๊ธ์ฑ์ฅํ๋ฉด์ ์์ฒญ๋ ์์ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ์ฒ๋ฆฌํด์ผ ํ์ด. ๊ธฐ์กด ๋ฉ์์ง ์์คํ
์ผ๋ก๋ ํ๊ณ๊ฐ ์์์ง. ๊ทธ๋์ ์ง์ ๋ง๋ ๊ฒ ๋ฐ๋ก Kafka์ผ! ์ด๋ฆ์ ์๊ฐ ํ๋์ธ ์นดํ์นด์์ ๋ฐ์๋๋ฐ, ๊ฐ๋ฐ์๊ฐ ๊ทธ์ ํฌ์ด์๋! ๐
๐ ๋๋ผ์ด ์ฑ๋ฅ!
Kafka๋ ์ด๋น ์๋ฐฑ๋ง ๊ฐ์ ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ ์ ์์ด! LinkedIn์์๋ ํ๋ฃจ์ 1์กฐ ๊ฐ ์ด์์ ๋ฉ์์ง๋ฅผ Kafka๋ก ์ฒ๋ฆฌํ๋ค๊ณ ํด. ์์์ด ๊ฐ?
๐๏ธ Kafka์ ํต์ฌ ๊ตฌ์กฐ
Kafka๋ RabbitMQ์๋ ์์ ํ ๋ค๋ฅธ ์ฒ ํ์ผ๋ก ์ค๊ณ๋์์ด:
1๏ธโฃ Topic (ํ ํฝ)
๋ฉ์์ง๊ฐ ์ ์ฅ๋๋ ์นดํ
๊ณ ๋ฆฌ์ผ. RabbitMQ์ Queue์ ๋น์ทํ์ง๋ง, ํจ์ฌ ๊ฐ๋ ฅํด!
์: "user-events", "order-logs", "payment-transactions"
2๏ธโฃ Partition (ํํฐ์
)
์ด๊ฒ Kafka์ ํต์ฌ์ด์ผ! ํ๋์ ํ ํฝ์ ์ฌ๋ฌ ํํฐ์
์ผ๋ก ๋๋ ์ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํด.
๊ฐ ํํฐ์
์ ์์๊ฐ ๋ณด์ฅ๋๋ ๋ถ๋ณ์ ๋ก๊ทธ ํ์ผ์ด์ผ!
3๏ธโฃ Producer (์์ฐ์)
ํ ํฝ์ ๋ฉ์์ง๋ฅผ ๋ฐํํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ด์ผ.
4๏ธโฃ Consumer (์๋น์)
ํ ํฝ์์ ๋ฉ์์ง๋ฅผ ์ฝ์ด๊ฐ๋ ์ ํ๋ฆฌ์ผ์ด์
์ด์ผ. ์ฌ๋ฌ Consumer๊ฐ Consumer Group์ ๋ง๋ค์ด์ ํ๋ ฅํ ์ ์์ด!
5๏ธโฃ Broker (๋ธ๋ก์ปค)
Kafka ์๋ฒ๋ฅผ ๋งํด. ์ฌ๋ฌ ๋ธ๋ก์ปค๊ฐ ํด๋ฌ์คํฐ๋ฅผ ๊ตฌ์ฑํด์ ๊ณ ๊ฐ์ฉ์ฑ์ ์ ๊ณตํด!
6๏ธโฃ ZooKeeper / KRaft
ํด๋ฌ์คํฐ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๋ ์์คํ
์ด์ผ. ์ต์ ๋ฒ์ ์์๋ ZooKeeper ์์ด๋ ๋์ํ๋ KRaft ๋ชจ๋๊ฐ ๋์
๋์์ด!
๐จ Kafka์ ๋
ํนํ ํน์ง
๐ ๋ก๊ทธ ๊ธฐ๋ฐ ์ ์ฅ
Kafka๋ ๋ฉ์์ง๋ฅผ ์ญ์ ํ์ง ์๊ณ ์ผ์ ๊ธฐ๊ฐ ๋ณด๊ดํด! ์ด๊ฒ ์์ฒญ๋ ์ฅ์ ์ด์ผ.
โข ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ ๋ฒ ์ฝ์ ์ ์์ด (Replay ๊ฐ๋ฅ)
โข ์๋ก์ด Consumer๊ฐ ๊ณผ๊ฑฐ ๋ฐ์ดํฐ๋ถํฐ ์ฒ๋ฆฌ ๊ฐ๋ฅ
โข ๋ฐ์ดํฐ ๋ถ์๊ณผ ๋๋ฒ๊น
์ด ์ฌ์์ ธ!
๐ Offset ๊ด๋ฆฌ
๊ฐ Consumer๋ ์์ ์ด ์ด๋๊น์ง ์ฝ์๋์ง offset์ ๊ด๋ฆฌํด.
์ด๋ฅผ ํตํด ์ ํํ ํ ๋ฒ(Exactly Once) ์ฒ๋ฆฌ๋ฅผ ๋ณด์ฅํ ์ ์์ด!
๐ ๋ถ์ฐ ์ฒ๋ฆฌ
ํํฐ์
์ ์ฌ๋ฌ ๋ธ๋ก์ปค์ ๋ถ์ฐ์์ผ์ ์ํ ํ์ฅ์ด ์ฌ์!
ํธ๋ํฝ์ด ๋์ด๋๋ฉด ๋ธ๋ก์ปค๋ง ์ถ๊ฐํ๋ฉด ๋ผ!
๐ป Kafka ์ค์ ์์
Python์ผ๋ก Kafka๋ฅผ ์ฌ์ฉํ๋ ์์ ๋ฅผ ๋ณผ๊น?
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')
)
# ์ด๋ฒคํธ ๋ฐ์ดํฐ
event = {
'user_id': 'user123',
'action': 'purchase',
'product_id': 'laptop-001',
'amount': 1500000,
'timestamp': datetime.now().isoformat()
}
# ํ ํฝ์ ์ด๋ฒคํธ ๋ฐํ
future = producer.send('user-events', value=event)
# ์ ์ก ์๋ฃ ๋๊ธฐ
result = future.get(timeout=10)
print(f"์ด๋ฒคํธ ์ ์ก ์๋ฃ! Partition: {result.partition}, Offset: {result.offset}")
producer.close()
from kafka import KafkaConsumer
import json
# Consumer ์์ฑ
consumer = KafkaConsumer(
'user-events',
bootstrap_servers=['localhost:9092'],
auto_offset_reset='earliest', # ์ฒ์๋ถํฐ ์ฝ๊ธฐ
enable_auto_commit=True,
group_id='analytics-group',
value_deserializer=lambda m: json.loads(m.decode('utf-8'))
)
print('์ด๋ฒคํธ ์์ ๋๊ธฐ ์ค...')
for message in consumer:
event = message.value
print(f"๋ฐ์ ์ด๋ฒคํธ: {event}")
print(f"Partition: {message.partition}, Offset: {message.offset}")
# ์ด๋ฒคํธ ์ฒ๋ฆฌ ๋ก์ง
if event['action'] == 'purchase':
print(f"๊ตฌ๋งค ์ด๋ฒคํธ ์ฒ๋ฆฌ: {event['user_id']}๋์ด {event['amount']}์ ๊ฒฐ์ ")
๐ ์ฝ๋ ์ค๋ช
bootstrap_servers: Kafka ํด๋ฌ์คํฐ์ ์ฃผ์ ๋ชฉ๋ก
auto_offset_reset='earliest': ์ ์ฅ๋ offset์ด ์์ผ๋ฉด ์ฒ์๋ถํฐ ์ฝ๊ธฐ
group_id: Consumer Group ์๋ณ์. ๊ฐ์ ๊ทธ๋ฃน์ Consumer๋ค์ ํํฐ์
์ ๋๋ ์ ์ฒ๋ฆฌ!
enable_auto_commit: offset์ ์๋์ผ๋ก ์ปค๋ฐํ ์ง ์ฌ๋ถ
๐ฏ Kafka์ ๊ฐ์
โ
์์ฒญ๋ ์ฒ๋ฆฌ๋
์ด๋น ์๋ฐฑ๋ง ๊ฐ์ ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ ์ ์์ด! ๋น
๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ์ต์ ํ๋์ด ์์ง.
โ
๋ด๊ตฌ์ฑ๊ณผ ์์ ์ฑ
๋ฐ์ดํฐ๋ฅผ ๋์คํฌ์ ์ ์ฅํ๊ณ ๋ณต์ ํด์ ๋ฐ์ดํฐ ์์ค์ ๋ฐฉ์งํด!
โ
ํ์ฅ์ฑ
์ํ ํ์ฅ์ด ์ฌ์์ ํธ๋ํฝ ์ฆ๊ฐ์ ์ ์ฐํ๊ฒ ๋์ ๊ฐ๋ฅ!
โ
์ค์๊ฐ ์ฒ๋ฆฌ
๋ฐ๋ฆฌ์ด ๋จ์์ ์ง์ฐ์๊ฐ์ผ๋ก ์ค์๊ฐ ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ ๊ตฌ์ถ ๊ฐ๋ฅ!
โ
๋ฐ์ดํฐ ์ฌ์ฒ๋ฆฌ
๊ณผ๊ฑฐ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ์ฝ์ ์ ์์ด์ ๋ถ์์ด๋ ๋๋ฒ๊น
์ด ์ฌ์!
โ
์ํ๊ณ
Kafka Streams, Kafka Connect ๋ฑ ๊ฐ๋ ฅํ ๋๊ตฌ๋ค์ด ํ๋ถํด!
๐ค Kafka๋ ์ธ์ ์ฌ์ฉํ ๊น?
Kafka๊ฐ ์ง๊ฐ๋ฅผ ๋ฐํํ๋ ์ํฉ๋ค:
1๏ธโฃ ๋ก๊ทธ ์์ง ๋ฐ ๋ถ์
์๋ง์ ์๋ฒ์์ ๋ฐ์ํ๋ ๋ก๊ทธ๋ฅผ ์ค์๊ฐ์ผ๋ก ์์งํ๊ณ ๋ถ์ํ ๋!
์: ์น ์๋ฒ ๋ก๊ทธ, ์ ํ๋ฆฌ์ผ์ด์
๋ก๊ทธ, ์์คํ
๋ฉํธ๋ฆญ
2๏ธโฃ ์ค์๊ฐ ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ
๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ค๋ฅธ ์์คํ
์ผ๋ก ์ ์กํ ๋!
์: ๋ฐ์ดํฐ๋ฒ ์ด์ค โ Kafka โ Elasticsearch โ ๋์๋ณด๋
3๏ธโฃ ์ด๋ฒคํธ ์์ฑ
๋ชจ๋ ์ํ ๋ณ๊ฒฝ์ ์ด๋ฒคํธ๋ก ์ ์ฅํ๋ ์ํคํ
์ฒ!
์: ์ฃผ๋ฌธ ์์ฑ, ๊ฒฐ์ ์๋ฃ, ๋ฐฐ์ก ์์ ๋ฑ ๋ชจ๋ ์ด๋ฒคํธ๋ฅผ ๊ธฐ๋ก
4๏ธโฃ ์คํธ๋ฆผ ์ฒ๋ฆฌ
์ค์๊ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณํํ๊ณ ์ง๊ณํ ๋!
์: ์ค์๊ฐ ์ถ์ฒ ์์คํ
, ์ด์ ํ์ง, ์ค์๊ฐ ๋์๋ณด๋
5๏ธโฃ ๋ฉ์์ง ๋ฒํผ๋ง
๊ธ๊ฒฉํ ํธ๋ํฝ ์ฆ๊ฐ๋ฅผ ํก์ํ ๋!
์: ๋ธ๋ํ๋ผ์ด๋ฐ์ด ๊ฐ์ ์ด๋ฒคํธ ๊ธฐ๊ฐ์ ์ฃผ๋ฌธ ํญ์ฃผ
๐ข ์ค์ ์ฌ์ฉ ์ฌ๋ก
Netflix: ํ๋ฃจ 7000์ต ๊ฐ ์ด์์ ์ด๋ฒคํธ๋ฅผ Kafka๋ก ์ฒ๋ฆฌ
Uber: ์ค์๊ฐ ์์น ์ถ์ ๊ณผ ์๊ธ ๊ณ์ฐ์ ํ์ฉ
LinkedIn: 1์กฐ ๊ฐ ์ด์์ ๋ฉ์์ง๋ฅผ ๋งค์ผ ์ฒ๋ฆฌ
Airbnb: ์ค์๊ฐ ๋ถ์๊ณผ ๋ชจ๋ํฐ๋ง์ ์ฌ์ฉ
์ด๋ฐ ๊ธ๋ก๋ฒ ๊ธฐ์
๋ค์ด Kafka๋ฅผ ์ ํํ ์ด์ ๋ ๋์ฉ๋ ์ฒ๋ฆฌ ๋ฅ๋ ฅ๊ณผ ํ์ฅ์ฑ ๋๋ฌธ์ด์ผ!
โ๏ธ RabbitMQ vs Kafka: ์๋ฒฝ ๋น๊ต
์, ์ด์ ๋ ๊ธฐ์ ์ ์ง์ ๋น๊ตํด๋ณผ ์๊ฐ์ด์ผ! ์ด๋ค ์ํฉ์์ ๋ฌด์์ ์ ํํด์ผ ํ ๊น? ๐ค
| ๋น๊ต ํญ๋ชฉ | RabbitMQ ๐ฐ | Apache Kafka ๐ |
|---|---|---|
| ์ฃผ์ ๋ชฉ์ | ๋ฉ์์ง ๋ธ๋ก์ปค ์์ ํ ์ฒ๋ฆฌ |
์ด๋ฒคํธ ์คํธ๋ฆฌ๋ฐ ๋์ฉ๋ ๋ก๊ทธ ์ฒ๋ฆฌ |
| ๋ฉ์์ง ์ฒ๋ฆฌ | ๋ฉ์์ง ์ ๋ฌ ํ ์ญ์ (๊ธฐ๋ณธ ๋์) |
์ผ์ ๊ธฐ๊ฐ ๋ณด๊ด (์ฌ์ฒ๋ฆฌ ๊ฐ๋ฅ) |
| ์ฒ๋ฆฌ๋ | ์ด๋น ์๋ง ๊ฐ (์ค์๊ท๋ชจ) |
์ด๋น ์๋ฐฑ๋ง ๊ฐ (๋๊ท๋ชจ) |
| ๋ผ์ฐํ | ๋งค์ฐ ์ ์ฐ (4๊ฐ์ง Exchange) |
๋จ์ (Topic ๊ธฐ๋ฐ) |
| ๋ฉ์์ง ์์ | ํ ๋จ์ ๋ณด์ฅ | ํํฐ์ ๋จ์ ๋ณด์ฅ |
| ํ๋กํ ์ฝ | AMQP, MQTT, STOMP | ์์ฒด ํ๋กํ ์ฝ |
| ํ์ต ๊ณก์ | ๋น๊ต์ ์ฌ์ ๐ | ๋ค์ ๋ณต์ก ๐ค |
| ๊ด๋ฆฌ UI | ๊ธฐ๋ณธ ์ ๊ณต โ | ๋ณ๋ ์ค์น ํ์ |
| ์ฐ์ ์์ ํ | ์ง์ โ | ๋ฏธ์ง์ โ |
| ๋ฐ์ดํฐ ์ฌ์ฒ๋ฆฌ | ์ด๋ ค์ โ | ์ฌ์ โ |
๐ฏ ์ ํ ๊ฐ์ด๋
๐ฐ RabbitMQ๋ฅผ ์ ํํด์ผ ํ๋ ๊ฒฝ์ฐ:
โ
๋ณต์กํ ๋ผ์ฐํ
๋ก์ง์ด ํ์ํ ๋
โ
๋ฉ์์ง ์ ๋ฌ ๋ณด์ฅ์ด ์ค์ํ ๋
โ
์ฐ์ ์์ ํ๊ฐ ํ์ํ ๋
โ
๋ค์ํ ํ๋กํ ์ฝ ์ง์์ด ํ์ํ ๋
โ
์ค์๊ท๋ชจ ๋ฉ์์ง ์ฒ๋ฆฌ
โ
๋น ๋ฅธ ํ๋กํ ํ์ดํ์ด ํ์ํ ๋
โ
๊ด๋ฆฌ UI๊ฐ ์ค์ํ ๋
๐ผ ์ค์ ์ฌ์ฉ ์์:
โข ์ด๋ฉ์ผ ๋ฐ์ก ์์คํ
โข ์ฃผ๋ฌธ ์ฒ๋ฆฌ ์ํฌํ๋ก์ฐ
โข ๋ง์ดํฌ๋ก์๋น์ค ๊ฐ ํต์
โข ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ฒ๋ฆฌ
โข IoT ๋๋ฐ์ด์ค ๋ฉ์์ง (MQTT)
๐ Kafka๋ฅผ ์ ํํด์ผ ํ๋ ๊ฒฝ์ฐ:
โ
๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๊ฐ ํ์ํ ๋
โ
์ค์๊ฐ ์คํธ๋ฆผ ์ฒ๋ฆฌ๊ฐ ํ์ํ ๋
โ
๋ก๊ทธ ์์ง ๋ฐ ๋ถ์
โ
์ด๋ฒคํธ ์์ฑ ์ํคํ
์ฒ
โ
๋ฐ์ดํฐ ์ฌ์ฒ๋ฆฌ๊ฐ ํ์ํ ๋
โ
๋์ ์ฒ๋ฆฌ๋์ด ์ค์ํ ๋
โ
์ํ ํ์ฅ์ด ํ์ํ ๋
๐ผ ์ค์ ์ฌ์ฉ ์์:
โข ์น ๋ก๊ทธ ์์ง ๋ฐ ๋ถ์
โข ์ค์๊ฐ ์ถ์ฒ ์์คํ
โข ์ฌ์ฉ์ ํ๋ ์ถ์
โข ๋ฉํธ๋ฆญ ์์ง ๋ฐ ๋ชจ๋ํฐ๋ง
โข CDC (Change Data Capture)
โข ์ค์๊ฐ ๋์๋ณด๋
โ ๏ธ ์ฃผ์์ฌํญ
RabbitMQ ์ฃผ์์ :
โข ๋์ฉ๋ ์ฒ๋ฆฌ ์ ์ฑ๋ฅ ์ ํ ๊ฐ๋ฅ
โข ๋ฉ์์ง ์ฌ์ฒ๋ฆฌ๊ฐ ์ด๋ ค์
โข ํด๋ฌ์คํฐ ๊ตฌ์ฑ์ด ๋ณต์กํ ์ ์์
Kafka ์ฃผ์์ :
โข ์ด๊ธฐ ์ค์ ์ด ๋ณต์กํจ
โข ์์ ๋ฉ์์ง ์ฒ๋ฆฌ ์ ์ค๋ฒํค๋
โข ์ด์ ๊ด๋ฆฌ์ ์ ๋ฌธ ์ง์ ํ์
โข ๋ฆฌ์์ค ์ฌ์ฉ๋์ด ๋ง์
๐ ํจ๊ป ์ฌ์ฉํ๊ธฐ
์ฌ์ค RabbitMQ์ Kafka๋ ๊ฒฝ์ ๊ด๊ณ๊ฐ ์๋์ผ! ๋ง์ ๊ธฐ์
๋ค์ด ๋ ๊ธฐ์ ์ ํจ๊ป ์ฌ์ฉํด์ ๊ฐ๊ฐ์ ์ฅ์ ์ ํ์ฉํ๊ณ ์์ด.
๐จ ํ์ด๋ธ๋ฆฌ๋ ์ํคํ
์ฒ ์์:
์๋๋ฆฌ์ค: ๋ํ ์ด์ปค๋จธ์ค ํ๋ซํผ
Kafka ์ฌ์ฉ ์์ญ:
โข ์ฌ์ฉ์ ํด๋ฆญ ์คํธ๋ฆผ ์์ง (์ด๋น ์์ญ๋ง ์ด๋ฒคํธ)
โข ์ฃผ๋ฌธ ์ด๋ฒคํธ ๋ก๊ทธ ์ ์ฅ (์ด๋ฒคํธ ์์ฑ)
โข ์ค์๊ฐ ์ฌ๊ณ ๋ชจ๋ํฐ๋ง
โข ๋ฐ์ดํฐ ๋ถ์ ํ์ดํ๋ผ์ธ
RabbitMQ ์ฌ์ฉ ์์ญ:
โข ์ฃผ๋ฌธ ํ์ธ ์ด๋ฉ์ผ ๋ฐ์ก
โข ๊ฒฐ์ ์ฒ๋ฆฌ ์ํฌํ๋ก์ฐ
โข ์ฌ๊ณ ๋ถ์กฑ ์๋ฆผ
โข ๊ด๋ฆฌ์ ์๋ฆผ ์์คํ
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ ๊ธฐ์ ์ ๊ฐ์ ์ ์ต๋ํ ํ์ฉํ ์ ์์ด! ๐ช
๐ ๏ธ ์ค์ ๊ตฌ์ถ ๊ฐ์ด๋
์ด๋ก ๋ง ์์์๋ ๋ถ์กฑํ์ง! ์ค์ ๋ก ์ด๋ป๊ฒ ๊ตฌ์ถํ๊ณ ์ด์ํ๋์ง ์์๋ณด์.
๐ฐ RabbitMQ ์ค์น ๋ฐ ์ค์
# RabbitMQ ์ปจํ
์ด๋ ์คํ (๊ด๋ฆฌ UI ํฌํจ)
docker run -d \
--name rabbitmq \
-p 5672:5672 \
-p 15672:15672 \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=admin123 \
rabbitmq:3-management
# ๊ด๋ฆฌ UI ์ ์: http://localhost:15672
# ๊ธฐ๋ณธ ํฌํธ: 5672 (AMQP), 15672 (๊ด๋ฆฌ UI)
# ๋ฉ๋ชจ๋ฆฌ ์ ํ ์ค์
vm_memory_high_watermark.relative = 0.6
# ๋์คํฌ ๊ณต๊ฐ ์ ํ
disk_free_limit.absolute = 2GB
# ํํธ๋นํธ ๊ฐ๊ฒฉ
heartbeat = 60
# ์ต๋ ์ฐ๊ฒฐ ์
max_connections = 1000
# ๋ฉ์์ง TTL (Time To Live)
default_vhost = /
default_user = admin
default_pass = admin123
๐ฏ RabbitMQ ๋ชจ๋ฒ ์ฌ๋ก
1. ๋ฉ์์ง ์ง์์ฑ ์ค์
์ค์ํ ๋ฉ์์ง๋ ๋ฐ๋์ durable ํ์ persistent ๋ฉ์์ง๋ก ์ค์ !
2. Prefetch Count ์กฐ์
Consumer์ prefetch_count๋ฅผ ์ ์ ํ ์ค์ ํด์ ๋ถํ ๋ถ์ฐ!
3. Dead Letter Exchange ํ์ฉ
์ฒ๋ฆฌ ์คํจํ ๋ฉ์์ง๋ฅผ ๋ณ๋ ํ๋ก ๋ณด๋ด์ ์ฌ์ฒ๋ฆฌ ๋๋ ๋ถ์!
4. ๋ชจ๋ํฐ๋ง
ํ ๊ธธ์ด, ๋ฉ์์ง ์ฒ๋ฆฌ์จ, ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ง์์ ์ผ๋ก ๋ชจ๋ํฐ๋ง!
๐ Kafka ์ค์น ๋ฐ ์ค์
version: '3'
services:
zookeeper:
image: confluentinc/cp-zookeeper:latest
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
ports:
- "2181:2181"
kafka:
image: confluentinc/cp-kafka:latest
depends_on:
- zookeeper
ports:
- "9092:9092"
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
KAFKA_LOG_RETENTION_HOURS: 168 # 7์ผ
KAFKA_LOG_SEGMENT_BYTES: 1073741824 # 1GB
# ํ ํฝ ์์ฑ
kafka-topics --create \
--bootstrap-server localhost:9092 \
--topic user-events \
--partitions 3 \
--replication-factor 1
# ํ ํฝ ๋ชฉ๋ก ํ์ธ
kafka-topics --list \
--bootstrap-server localhost:9092
# ํ ํฝ ์์ธ ์ ๋ณด
kafka-topics --describe \
--bootstrap-server localhost:9092 \
--topic user-events
# ํ ํฝ ์ค์ ๋ณ๊ฒฝ
kafka-configs --alter \
--bootstrap-server localhost:9092 \
--entity-type topics \
--entity-name user-events \
--add-config retention.ms=604800000 # 7์ผ
๐ฏ Kafka ๋ชจ๋ฒ ์ฌ๋ก
1. ์ ์ ํ ํํฐ์
์ ์ค์
ํํฐ์
์ = max(์์ ์ฒ๋ฆฌ๋ / Consumer ์ฒ๋ฆฌ๋, Consumer ์)
๋๋ฌด ๋ง์ผ๋ฉด ์ค๋ฒํค๋, ๋๋ฌด ์ ์ผ๋ฉด ๋ณ๋ ฌ ์ฒ๋ฆฌ ์ ํ!
2. ๋ณต์ ํฉํฐ ์ค์
ํ๋ก๋์
ํ๊ฒฝ์์๋ ์ต์ 3๊ฐ์ ๋ณต์ ๋ณธ ์ ์ง!
3. ์์ถ ํ์ฉ
๋คํธ์ํฌ ๋์ญํญ ์ ์ฝ์ ์ํด snappy ๋๋ lz4 ์์ถ ์ฌ์ฉ!
4. Consumer Group ํ์ฉ
์ฌ๋ฌ Consumer๋ฅผ ๊ทธ๋ฃน์ผ๋ก ๋ฌถ์ด์ ์๋ ๋ถํ ๋ถ์ฐ!
5. ๋ชจ๋ํฐ๋ง ์งํ
โข Under-replicated partitions
โข Consumer lag
โข Broker CPU/Memory
โข Disk I/O
๐ ์ฑ๋ฅ ์ต์ ํ ํ
RabbitMQ ์ฑ๋ฅ ์ต์ ํ:
1. ๋ฐฐ์น ์ฒ๋ฆฌ
๋ฉ์์ง๋ฅผ ๊ฐ๋ณ์ ์ผ๋ก ๋ณด๋ด์ง ๋ง๊ณ ๋ฐฐ์น๋ก ๋ฌถ์ด์ ์ ์ก!
2. ์ฐ๊ฒฐ ํ๋ง
์ฐ๊ฒฐ์ ์ฌ์ฌ์ฉํด์ ์ค๋ฒํค๋ ๊ฐ์!
3. ๋ฉ์์ง ํฌ๊ธฐ ์ต์ ํ
ํฐ ๋ฉ์์ง๋ ๋ณ๋ ์ ์ฅ์์ ์ ์ฅํ๊ณ ์ฐธ์กฐ๋ง ์ ์ก!
4. ์ ์ ํ Prefetch ๊ฐ
CPU ์ฝ์ด ์์ 2-3๋ฐฐ ์ ๋๊ฐ ์ ๋น!
Kafka ์ฑ๋ฅ ์ต์ ํ:
1. ๋ฐฐ์น ํฌ๊ธฐ ์กฐ์
batch.size์ linger.ms๋ฅผ ์กฐ์ ํด์ ์ฒ๋ฆฌ๋ ํฅ์!
2. ์์ถ ์ฌ์ฉ
compression.type=snappy ๋๋ lz4 ์ค์ !
3. ์ ์ ํ ํํฐ์ ์
๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ์ํด ์ถฉ๋ถํ ํํฐ์ ํ๋ณด!
4. ๋ฉ๋ชจ๋ฆฌ ์ค์
JVM ํ ํฌ๊ธฐ๋ฅผ ์ ์ ํ ์ค์ (๋ณดํต 6-8GB)!
5. ๋์คํฌ I/O ์ต์ ํ
SSD ์ฌ์ฉ ๊ถ์ฅ, RAID ๊ตฌ์ฑ ๊ณ ๋ ค!
๐ ๊ณ ๊ธ ํจํด ๋ฐ ์ํคํ ์ฒ
์ด์ ์ข ๋ ๊น์ด ๋ค์ด๊ฐ๋ณผ๊น? ์ค๋ฌด์์ ์์ฃผ ์ฌ์ฉ๋๋ ๊ณ ๊ธ ํจํด๋ค์ ์์๋ณด์!
๐ ๋ฉ์์ง ํจํด
1๏ธโฃ Publish-Subscribe (๋ฐํ-๊ตฌ๋
)
ํ๋์ ๋ฉ์์ง๋ฅผ ์ฌ๋ฌ ๊ตฌ๋
์๊ฐ ๋ฐ๋ ํจํด์ด์ผ.
RabbitMQ ๊ตฌํ: Fanout Exchange ์ฌ์ฉ
Kafka ๊ตฌํ: ์ฌ๋ฌ Consumer Group ์ฌ์ฉ
์ฌ์ฉ ์์:
โข ๊ณต์ง์ฌํญ ์ ํ
โข ์บ์ ๋ฌดํจํ
โข ์ด๋ฒคํธ ์๋ฆผ
2๏ธโฃ Request-Reply (์์ฒญ-์๋ต)
๋ฉ์์ง๋ฅผ ๋ณด๋ด๊ณ ์๋ต์ ๊ธฐ๋ค๋ฆฌ๋ ํจํด์ด์ผ.
RabbitMQ ๊ตฌํ: Reply-To ํ์ Correlation ID ์ฌ์ฉ
Kafka ๊ตฌํ: ๋ณ๋ ์๋ต ํ ํฝ ์ฌ์ฉ
์ฌ์ฉ ์์:
โข RPC (Remote Procedure Call)
โข ๋๊ธฐ์ ๋ง์ดํฌ๋ก์๋น์ค ํต์
3๏ธโฃ Competing Consumers (๊ฒฝ์ ์๋น์)
์ฌ๋ฌ Consumer๊ฐ ํ๋์ ํ์์ ๋ฉ์์ง๋ฅผ ๊ฐ์ ธ๊ฐ๋ ํจํด!
RabbitMQ ๊ตฌํ: ํ๋์ ํ์ ์ฌ๋ฌ Consumer ์ฐ๊ฒฐ
Kafka ๊ตฌํ: Consumer Group ํ์ฉ
์ฌ์ฉ ์์:
โข ์์
๋ถํ ๋ถ์ฐ
โข ๋ณ๋ ฌ ์ฒ๋ฆฌ
4๏ธโฃ Priority Queue (์ฐ์ ์์ ํ)
์ค์ํ ๋ฉ์์ง๋ฅผ ๋จผ์ ์ฒ๋ฆฌํ๋ ํจํด!
RabbitMQ ๊ตฌํ: Priority Queue ๊ธฐ๋ฅ ์ฌ์ฉ
Kafka ๊ตฌํ: ๋ณ๋ ํ ํฝ์ผ๋ก ๋ถ๋ฆฌ
์ฌ์ฉ ์์:
โข VIP ๊ณ ๊ฐ ์ฐ์ ์ฒ๋ฆฌ
โข ๊ธด๊ธ ์๋ฆผ
๐๏ธ ์ํคํ ์ฒ ํจํด
๐ฏ Event-Driven Architecture (์ด๋ฒคํธ ์ฃผ๋ ์ํคํ
์ฒ)
์์คํ
์ ์ํ ๋ณํ๋ฅผ ์ด๋ฒคํธ๋ก ํํํ๊ณ , ์ด๋ฒคํธ๋ฅผ ์ค์ฌ์ผ๋ก ์์คํ
์ ์ค๊ณํ๋ ๋ฐฉ์์ด์ผ!
ํต์ฌ ๊ฐ๋
:
โข ์ด๋ฒคํธ ๋ฐํ์์ ๊ตฌ๋
์์ ๋ถ๋ฆฌ
โข ๋น๋๊ธฐ ํต์
โข ๋์จํ ๊ฒฐํฉ
์ฅ์ :
โ
ํ์ฅ์ฑ์ด ๋ฐ์ด๋จ
โ
์์คํ
๊ฐ ๋
๋ฆฝ์ฑ ํ๋ณด
โ
์ค์๊ฐ ๋ฐ์ ๊ฐ๋ฅ
๋จ์ :
โ ๋๋ฒ๊น
์ด ์ด๋ ค์
โ ์ด๋ฒคํธ ์์ ๊ด๋ฆฌ ๋ณต์ก
โ ์ต์ข
์ผ๊ด์ฑ๋ง ๋ณด์ฅ
๐ฏ Event Sourcing (์ด๋ฒคํธ ์์ฑ)
๋ชจ๋ ์ํ ๋ณ๊ฒฝ์ ์ด๋ฒคํธ๋ก ์ ์ฅํ๋ ํจํด! Kafka๊ฐ ์ด ํจํด์ ์ต์ ํ๋์ด ์์ด.
ํต์ฌ ๊ฐ๋
:
โข ํ์ฌ ์ํ๊ฐ ์๋ ์ด๋ฒคํธ ํ์คํ ๋ฆฌ ์ ์ฅ
โข ์ด๋ฒคํธ๋ฅผ ์ฌ์ํด์ ์ํ ๋ณต์
โข ๊ฐ์ฌ ์ถ์ ๊ฐ๋ฅ
์ฅ์ :
โ
์๋ฒฝํ ๊ฐ์ฌ ๋ก๊ทธ
โ
์๊ฐ ์ฌํ ๊ฐ๋ฅ (๊ณผ๊ฑฐ ์ํ ๋ณต์)
โ
์ด๋ฒคํธ ์ฌ์ฒ๋ฆฌ ๊ฐ๋ฅ
์ฌ์ฉ ์์:
โข ๊ธ์ต ๊ฑฐ๋ ์์คํ
โข ์ฃผ๋ฌธ ๊ด๋ฆฌ ์์คํ
โข ๊ฒ์ ์ํ ๊ด๋ฆฌ
๐ ๋ณด์ ๋ฐ ์์ ์ฑ
โ ๏ธ ๋ณด์ ์ฒดํฌ๋ฆฌ์คํธ
RabbitMQ ๋ณด์:
โ ๊ธฐ๋ณธ ๊ณ์ ๋น๋ฐ๋ฒํธ ๋ณ๊ฒฝ
โ SSL/TLS ์ํธํ ํ์ฑํ
โ ๊ฐ์ ํธ์คํธ๋ก ๊ฒฉ๋ฆฌ
โ ์ฌ์ฉ์๋ณ ๊ถํ ์ค์
โ ๊ด๋ฆฌ UI ์ ๊ทผ ์ ํ
Kafka ๋ณด์:
โ SASL ์ธ์ฆ ์ค์
โ SSL ์ํธํ ํ์ฑํ
โ ACL (Access Control List) ์ค์
โ ZooKeeper ๋ณด์ ์ค์
โ ๋คํธ์ํฌ ๊ฒฉ๋ฆฌ
๊ณตํต ๋ณด์ ์ฌํญ:
โ ์ ๊ธฐ์ ์ธ ๋ณด์ ํจ์น
โ ๋ชจ๋ํฐ๋ง ๋ฐ ๋ก๊น
โ ๋ฐฑ์
๋ฐ ๋ณต๊ตฌ ๊ณํ
โ ์ฌํด ๋ณต๊ตฌ ์๋๋ฆฌ์ค
๐ ์ค์ ํ๋ก์ ํธ ์์
์ด๋ก ์ ์ถฉ๋ถํ ๋ฐฐ์ ์ผ๋, ์ค์ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด๋ณด์! ๊ฐ๋จํ ์ฃผ๋ฌธ ์ฒ๋ฆฌ ์์คํ ์ ๊ตฌ์ถํด๋ณผ๊ฒ.
๐ ํ๋ก์ ํธ: ์ด์ปค๋จธ์ค ์ฃผ๋ฌธ ์ฒ๋ฆฌ ์์คํ
์์คํ
์๊ตฌ์ฌํญ:
1. ์ฌ์ฉ์๊ฐ ์ฃผ๋ฌธ์ ์์ฑํ๋ฉด ์ฌ๋ฌ ์๋น์ค๊ฐ ์ฒ๋ฆฌ
2. ์ฌ๊ณ ํ์ธ โ ๊ฒฐ์ ์ฒ๋ฆฌ โ ๋ฐฐ์ก ์ค๋น
3. ๊ฐ ๋จ๊ณ๋ง๋ค ์ด๋ฉ์ผ ์๋ฆผ
4. ์ค์๊ฐ ์ฃผ๋ฌธ ํํฉ ๋ชจ๋ํฐ๋ง
5. ์ฃผ๋ฌธ ์ด๋ฒคํธ ๋ก๊ทธ ์ ์ฅ (๋ถ์์ฉ)
๊ธฐ์ ์คํ:
โข RabbitMQ: ์์
ํ ๋ฐ ์๋ฆผ
โข Kafka: ์ด๋ฒคํธ ๋ก๊ทธ ๋ฐ ๋ชจ๋ํฐ๋ง
โข Python: ๋ฐฑ์๋ ์๋น์ค
โข PostgreSQL: ์ฃผ๋ฌธ ๋ฐ์ดํฐ ์ ์ฅ
# ์ฃผ๋ฌธ ์์ฑ ์๋น์ค
์ฃผ๋ฌธ API
โ
โโโ RabbitMQ (order-queue) โ ์ฌ๊ณ ์๋น์ค
โโโ Kafka (order-events) โ ๋ถ์ ์์คํ
# ์ฌ๊ณ ์๋น์ค
์ฌ๊ณ ํ์ธ
โ
โโโ RabbitMQ (payment-queue) โ ๊ฒฐ์ ์๋น์ค
โโโ RabbitMQ (notification-queue) โ ์ด๋ฉ์ผ ์๋น์ค
# ๊ฒฐ์ ์๋น์ค
๊ฒฐ์ ์ฒ๋ฆฌ
โ
โโโ RabbitMQ (shipping-queue) โ ๋ฐฐ์ก ์๋น์ค
โโโ Kafka (payment-events) โ ๋ถ์ ์์คํ
import pika
from kafka import KafkaProducer
import json
from datetime import datetime
class OrderService:
def __init__(self):
# RabbitMQ ์ฐ๊ฒฐ
self.rabbitmq_conn = pika.BlockingConnection(
pika.ConnectionParameters('localhost')
)
self.rabbitmq_channel = self.rabbitmq_conn.channel()
self.rabbitmq_channel.queue_declare(queue='order-queue', durable=True)
# Kafka ์ฐ๊ฒฐ
self.kafka_producer = KafkaProducer(
bootstrap_servers=['localhost:9092'],
value_serializer=lambda v: json.dumps(v).encode('utf-8')
)
def create_order(self, user_id, items, total_amount):
order = {
'order_id': f'ORD-{datetime.now().strftime("%Y%m%d%H%M%S")}',
'user_id': user_id,
'items': items,
'total_amount': total_amount,
'status': 'created',
'created_at': datetime.now().isoformat()
}
# RabbitMQ๋ก ์์
ํ์ ์ถ๊ฐ
self.rabbitmq_channel.basic_publish(
exchange='',
routing_key='order-queue',
body=json.dumps(order),
properties=pika.BasicProperties(
delivery_mode=2,
content_type='application/json'
)
)
print(f"โ
์ฃผ๋ฌธ ์์ฑ: {order['order_id']}")
# Kafka๋ก ์ด๋ฒคํธ ๋ก๊ทธ ์ ์ฅ
event = {
'event_type': 'order_created',
'order_id': order['order_id'],
'user_id': user_id,
'amount': total_amount,
'timestamp': datetime.now().isoformat()
}
self.kafka_producer.send('order-events', value=event)
print(f"๐ ์ด๋ฒคํธ ๋ก๊ทธ ์ ์ฅ ์๋ฃ")
return order
# ์ฌ์ฉ ์์
service = OrderService()
order = service.create_order(
user_id='user123',
items=[
{'product_id': 'laptop-001', 'quantity': 1, 'price': 1500000}
],
total_amount=1500000
)
import pika
import json
class InventoryService:
def __init__(self):
self.connection = pika.BlockingConnection(
pika.ConnectionParameters('localhost')
)
self.channel = self.connection.channel()
# ํ ์ ์ธ
self.channel.queue_declare(queue='order-queue', durable=True)
self.channel.queue_declare(queue='payment-queue', durable=True)
self.channel.queue_declare(queue='notification-queue', durable=True)
def check_inventory(self, order):
print(f"๐ ์ฌ๊ณ ํ์ธ ์ค: {order['order_id']}")
# ์ฌ๊ณ ํ์ธ ๋ก์ง (์ค์ ๋ก๋ DB ์กฐํ)
inventory_available = True
if inventory_available:
print(f"โ
์ฌ๊ณ ์ถฉ๋ถ: {order['order_id']}")
# ๊ฒฐ์ ํ๋ก ์ ๋ฌ
order['status'] = 'inventory_confirmed'
self.channel.basic_publish(
exchange='',
routing_key='payment-queue',
body=json.dumps(order),
properties=pika.BasicProperties(delivery_mode=2)
)
# ์๋ฆผ ํ๋ก ์ ๋ฌ
notification = {
'type': 'inventory_confirmed',
'order_id': order['order_id'],
'user_id': order['user_id'],
'message': '์ฌ๊ณ ๊ฐ ํ์ธ๋์์ต๋๋ค.'
}
self.channel.basic_publish(
exchange='',
routing_key='notification-queue',
body=json.dumps(notification),
properties=pika.BasicProperties(delivery_mode=2)
)
else:
print(f"โ ์ฌ๊ณ ๋ถ์กฑ: {order['order_id']}")
def start_consuming(self):
def callback(ch, method, properties, body):
order = json.loads(body)
self.check_inventory(order)
ch.basic_ack(delivery_tag=method.delivery_tag)
self.channel.basic_qos(prefetch_count=1)
self.channel.basic_consume(
queue='order-queue',
on_message_callback=callback
)
print('๐ฆ ์ฌ๊ณ ์๋น์ค ์์...')
self.channel.start_consuming()
# ์๋น์ค ์คํ
service = InventoryService()
service.start_consuming()
from kafka import KafkaConsumer
import json
from collections import defaultdict
class MonitoringService:
def __init__(self):
self.consumer = KafkaConsumer(
'order-events',
'payment-events',
bootstrap_servers=['localhost:9092'],
auto_offset_reset='latest',
group_id='monitoring-group',
value_deserializer=lambda m: json.loads(m.decode('utf-8'))
)
self.stats = defaultdict(int)
def start_monitoring(self):
print('๐ ์ค์๊ฐ ๋ชจ๋ํฐ๋ง ์์...')
for message in self.consumer:
event = message.value
event_type = event.get('event_type')
# ํต๊ณ ์
๋ฐ์ดํธ
self.stats[event_type] += 1
# ์ค์๊ฐ ์ถ๋ ฅ
print(f"\n{'='*50}")
print(f"๐ ์ ์ด๋ฒคํธ: {event_type}")
print(f"์ฃผ๋ฌธ ID: {event.get('order_id')}")
print(f"์ฌ์ฉ์ ID: {event.get('user_id')}")
print(f"๊ธ์ก: {event.get('amount', 0):,}์")
print(f"\n๐ ํ์ฌ ํต๊ณ:")
for key, count in self.stats.items():
print(f" {key}: {count}๊ฑด")
print(f"{'='*50}\n")
# ๋ชจ๋ํฐ๋ง ์คํ
monitor = MonitoringService()
monitor.start_monitoring()
๐ฏ ํ๋ก์ ํธ ํต์ฌ ํฌ์ธํธ
1. ์ญํ ๋ถ๋ด
โข RabbitMQ: ์์
์ฒ๋ฆฌ์ ์๋ฆผ (์ ๋ขฐ์ฑ ์ค์)
โข Kafka: ์ด๋ฒคํธ ๋ก๊ทธ์ ๋ถ์ (๋์ฉ๋ ์ฒ๋ฆฌ)
2. ์ฅ์ ๋์
โข ๋ฉ์์ง ์ง์์ฑ ์ค์ ์ผ๋ก ๋ฐ์ดํฐ ์์ค ๋ฐฉ์ง
โข Consumer ACK๋ก ์ฒ๋ฆฌ ๋ณด์ฅ
โข Dead Letter Queue๋ก ์คํจ ๋ฉ์์ง ์ฒ๋ฆฌ
3. ํ์ฅ์ฑ
โข Consumer ์๋ฅผ ๋๋ ค์ ์ฒ๋ฆฌ๋ ์ฆ๊ฐ
โข Kafka ํํฐ์
์ผ๋ก ๋ณ๋ ฌ ์ฒ๋ฆฌ
โข ์๋น์ค๋ณ ๋
๋ฆฝ์ ์ธ ํ์ฅ ๊ฐ๋ฅ
๐ฏ ์ฌ๋ฅ๋ท์์ ๋ฉ์์ง ์ ๋ฌธ๊ฐ ์ฐพ๊ธฐ
๋ฉ์์ง ์์คํ
์ ์ง์ ๊ตฌ์ถํ๊ณ ์ด์ํ๋ ๊ฑด ์ฝ์ง ์์. ํนํ ์ฒ์์ด๋ผ๋ฉด ๋๋์ฑ! ๐
์ฌ๋ฅ๋ท์์๋ RabbitMQ์ Kafka ์ ๋ฌธ๊ฐ๋ค์ ์ฝ๊ฒ ์ฐพ์ ์ ์์ด. ์์คํ
์ค๊ณ๋ถํฐ ๊ตฌ์ถ, ์ต์ ํ, ํธ๋ฌ๋ธ์ํ
๊น์ง ๋ค์ํ ์ฌ๋ฅ์ ๊ฐ์ง ์ ๋ฌธ๊ฐ๋ค์ด ์์ง!
๐ก ์ด๋ฐ ๋์์ ๋ฐ์ ์ ์์ด:
โข ๋ฉ์์ง ์์คํ
์ํคํ
์ฒ ์ค๊ณ ์ปจ์คํ
โข RabbitMQ/Kafka ์ค์น ๋ฐ ๊ตฌ์ฑ
โข ์ฑ๋ฅ ์ต์ ํ ๋ฐ ํ๋
โข ๋ชจ๋ํฐ๋ง ์์คํ
๊ตฌ์ถ
โข ์ฅ์ ๋์ ๋ฐ ํธ๋ฌ๋ธ์ํ
โข ๋ง์ด๊ทธ๋ ์ด์
์ง์
ํผ์ ๊ณ ๋ฏผํ์ง ๋ง๊ณ ์ฌ๋ฅ๋ท์ ์ ๋ฌธ๊ฐ๋ค๊ณผ ํจ๊ป ํด๊ฒฐํด๋ณด๋ ๊ฑด ์ด๋? ์ํ์ฐฉ์ค๋ฅผ ์ค์ด๊ณ ๋น ๋ฅด๊ฒ ์์ ์ ์ธ ์์คํ
์ ๊ตฌ์ถํ ์ ์์ ๊ฑฐ์ผ! ๐
๐ฎ ๋ฏธ๋ ํธ๋ ๋์ ๋ฐ์ ๋ฐฉํฅ
๋ฉ์์ง ์์คํ ์ ๋ฏธ๋๋ ์ด๋ป๊ฒ ๋ ๊น? ์ต์ ํธ๋ ๋๋ฅผ ์์๋ณด์!
๐ ํด๋ผ์ฐ๋ ๋ค์ดํฐ๋ธ
AWS, Azure, GCP ๋ฑ ํด๋ผ์ฐ๋ ํ๋ซํผ์์ ๊ด๋ฆฌํ ์๋น์ค๊ฐ ์ธ๊ธฐ์ผ:
โข Amazon MQ (RabbitMQ ๊ด๋ฆฌํ)
โข Amazon MSK (Kafka ๊ด๋ฆฌํ)
โข Azure Event Hubs
โข Google Cloud Pub/Sub
์ฅ์ : ์ด์ ๋ถ๋ด ๊ฐ์, ์๋ ํ์ฅ, ๊ณ ๊ฐ์ฉ์ฑ
๐ค AI/ML ํตํฉ
๋ฉ์์ง ์์คํ
๊ณผ AI/ML์ ๊ฒฐํฉ:
โข ์ค์๊ฐ ์ด์ ํ์ง
โข ์์ธก ๊ธฐ๋ฐ ์ค์ผ์ผ๋ง
โข ์ง๋ฅํ ๋ผ์ฐํ
โข ์๋ ์ต์ ํ
๐ ์๋ฒ๋ฆฌ์ค ์ํคํ
์ฒ
์ด๋ฒคํธ ๊ธฐ๋ฐ ์๋ฒ๋ฆฌ์ค ํจ์์์ ํตํฉ:
โข AWS Lambda + Kafka
โข Azure Functions + Event Hubs
โข ์๋ ์ค์ผ์ผ๋ง
โข ๋น์ฉ ์ต์ ํ
๐ ๊ฐํ๋ ๋ณด์
์ ๋ก ํธ๋ฌ์คํธ ๋ณด์ ๋ชจ๋ธ ์ ์ฉ:
โข ์๋ํฌ์๋ ์ํธํ
โข ์ธ๋ฐํ ์ ๊ทผ ์ ์ด
โข ๊ฐ์ฌ ๋ก๊ทธ ๊ฐํ
โข ์ปดํ๋ผ์ด์ธ์ค ์๋ํ
๐ ํ์ต ๋ก๋๋งต
์ด๊ธ (1-2๊ฐ์)
โ ๋ฉ์์ง ์์คํ
๊ธฐ๋ณธ ๊ฐ๋
โ RabbitMQ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
โ Kafka ๊ธฐ๋ณธ ๊ฐ๋
โ ๊ฐ๋จํ Producer/Consumer ์์ฑ
์ค๊ธ (3-6๊ฐ์)
โ Exchange ํ์
๋ณ ํ์ฉ
โ Kafka ํํฐ์
๊ณผ Consumer Group
โ ๋ฉ์์ง ์ ๋ฌ ๋ณด์ฅ ๋ฉ์ปค๋์ฆ
โ ํด๋ฌ์คํฐ ๊ตฌ์ฑ
โ ๋ชจ๋ํฐ๋ง ๋ฐ ๋ก๊น
๊ณ ๊ธ (6๊ฐ์ ์ด์)
โ ์ฑ๋ฅ ์ต์ ํ
โ ๊ณ ๊ฐ์ฉ์ฑ ์ํคํ
์ฒ
โ ์ด๋ฒคํธ ์์ฑ ํจํด
โ CQRS ํจํด
โ ๋๊ท๋ชจ ์์คํ
์ค๊ณ
โ ํธ๋ฌ๋ธ์ํ
์ถ์ฒ ํ์ต ์๋ฃ:
โข ๊ณต์ ๋ฌธ์ (ํ์!)
โข Udemy, Coursera ๊ฐ์
โข GitHub ์คํ์์ค ํ๋ก์ ํธ
โข ๊ธฐ์ ๋ธ๋ก๊ทธ (Medium, Dev.to)
โข ์ปจํผ๋ฐ์ค ๋ฐํ ์๋ฃ
๐ก ์ค๋ฌด ํ๊ณผ ์ฃผ์์ฌํญ
โ ๏ธ ํํ ์ค์๋ค
1. ๋ฉ์์ง ํฌ๊ธฐ ๋ฌด์
๋๋ฌด ํฐ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ฉด ์ฑ๋ฅ ์ ํ! ํฐ ๋ฐ์ดํฐ๋ ๋ณ๋ ์ ์ฅ์ ์ฌ์ฉ!
2. ์๋ฌ ์ฒ๋ฆฌ ๋ฏธํก
๋ฉ์์ง ์ฒ๋ฆฌ ์คํจ ์ ์ฌ์๋ ๋ก์ง๊ณผ Dead Letter Queue ํ์!
3. ๋ชจ๋ํฐ๋ง ๋ถ์กฑ
๋ฌธ์ ๊ฐ ์๊ธฐ๊ณ ๋์์ผ ์์์ฐจ๋ฆฌ๋ฉด ๋ฆ์ด! ์ฌ์ ๋ชจ๋ํฐ๋ง ํ์!
4. ์์ ๋ณด์ฅ ์คํด
Kafka๋ ํํฐ์
๋ด์์๋ง ์์ ๋ณด์ฅ! ์ ์ฒด ์์๊ฐ ํ์ํ๋ฉด ํํฐ์
1๊ฐ ์ฌ์ฉ!
5. ๊ณผ๋ํ ๋ณต์ก์ฑ
์ฒ์๋ถํฐ ์๋ฒฝํ ์์คํ
์ ๋ง๋ค๋ ค๊ณ ํ์ง ๋ง! ๋จ์ํ๊ฒ ์์ํด์ ์ ์ง์ ์ผ๋ก ๊ฐ์ !
6. ๋ฐฑ์
๊ณํ ์์
๋ฐ์ดํฐ ์์ค์ ๋๋นํ ๋ฐฑ์
๊ณผ ๋ณต๊ตฌ ๊ณํ ํ์!
7. ํ
์คํธ ๋ถ์กฑ
ํ๋ก๋์
๋ฐฐํฌ ์ ์ถฉ๋ถํ ๋ถํ ํ
์คํธ์ ์ฅ์ ์๋๋ฆฌ์ค ํ
์คํธ!
โจ ํ๋ก ํ
1. ๋ฉฑ๋ฑ์ฑ ๋ณด์ฅ
๊ฐ์ ๋ฉ์์ง๋ฅผ ์ฌ๋ฌ ๋ฒ ์ฒ๋ฆฌํด๋ ๊ฒฐ๊ณผ๊ฐ ๊ฐ๋๋ก ์ค๊ณ!
2. ํ์์์ ์ค์
๋ชจ๋ ๋คํธ์ํฌ ์์
์ ์ ์ ํ ํ์์์ ์ค์ !
3. ๋ก๊น
์ ๋ต
๋ฉ์์ง ID๋ฅผ ํฌํจํ ๊ตฌ์กฐํ๋ ๋ก๊น
์ผ๋ก ์ถ์ ๊ฐ๋ฅํ๊ฒ!
4. ์ ์ง์ ๋กค์์
์๋ก์ด ๊ธฐ๋ฅ์ ์นด๋๋ฆฌ ๋ฐฐํฌ๋ ๋ธ๋ฃจ-๊ทธ๋ฆฐ ๋ฐฐํฌ๋ก ์์ ํ๊ฒ!
5. ๋ฌธ์ํ
๋ฉ์์ง ์คํค๋ง, ํ ํฝ ๊ตฌ์กฐ, ๋ผ์ฐํ
๊ท์น ๋ฑ์ ๋ช
ํํ ๋ฌธ์ํ!
6. ๋ฒ์ ๊ด๋ฆฌ
๋ฉ์์ง ํฌ๋งท ๋ณ๊ฒฝ ์ ํ์ ํธํ์ฑ ์ ์ง!
7. ๋น์ฉ ์ต์ ํ
๋ถํ์ํ ๋ฉ์์ง ๋ณต์ ์ค์ด๊ณ , ๋ณด๊ด ๊ธฐ๊ฐ ์ต์ ํ!
๐ฌ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์! ์ฌ๊ธฐ๊น์ง ์ฝ์๋ค๋ฉด ์ ๋ง ๋๋จํด! ๐
RabbitMQ์ Kafka๋ ํ๋ ์ํํธ์จ์ด ์ํคํ
์ฒ์์ ์์ด์๋ ์ ๋ ํต์ฌ ๊ธฐ์ ์ด์ผ. ๊ฐ๊ฐ์ ํน์ฑ์ ์ดํดํ๊ณ ์ ์ฌ์ ์์ ํ์ฉํ๋ค๋ฉด, ํ์ฅ ๊ฐ๋ฅํ๊ณ ์์ ์ ์ธ ์์คํ
์ ๊ตฌ์ถํ ์ ์์ด!
๐ฏ ํต์ฌ ์ ๋ฆฌ:
RabbitMQ๋ ์ด๋ด ๋!
โข ๋ณต์กํ ๋ผ์ฐํ
์ด ํ์ํ ๋
โข ๋ฉ์์ง ์ ๋ฌ ๋ณด์ฅ์ด ์ค์ํ ๋
โข ์ค์๊ท๋ชจ ๋ฉ์์ง ์ฒ๋ฆฌ
โข ๋น ๋ฅธ ๊ตฌ์ถ์ด ํ์ํ ๋
Kafka๋ ์ด๋ด ๋!
โข ๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
โข ์ค์๊ฐ ์คํธ๋ฆผ ์ฒ๋ฆฌ
โข ์ด๋ฒคํธ ์์ฑ
โข ๋ฐ์ดํฐ ์ฌ์ฒ๋ฆฌ๊ฐ ํ์ํ ๋
๊ฐ์ฅ ์ค์ํ ๊ฑด ์ค์ ๋ก ๋ง๋ค์ด๋ณด๋ ๊ฒ์ด์ผ! ์ด๋ก ๋ง ์์์๋ ๋ถ์กฑํด. ์์ ํ๋ก์ ํธ๋ถํฐ ์์ํด์ ์ ์ ๋ณต์กํ ์์คํ
์ ๋ง๋ค์ด๋ณด์! ๐ช
๊ทธ๋ฆฌ๊ณ ํผ์ ๊ณ ๋ฏผํ์ง ๋ง๊ณ , ์ฌ๋ฅ๋ท์ ์ ๋ฌธ๊ฐ๋ค๊ณผ ํจ๊ป ์ฑ์ฅํ๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด์ผ. ๊ฒฝํ ๋ง์ ๊ฐ๋ฐ์๋ค์ ๋
ธํ์ฐ๋ฅผ ๋ฐฐ์ฐ๋ฉด ํจ์ฌ ๋น ๋ฅด๊ฒ ์ฑ์ฅํ ์ ์๊ฑฐ๋ ! ๐
๋ฉ์์ง ์์คํ
์ ์ธ๊ณ๋ ์ ๋ง ๋๊ณ ๊น์ด. ํ์ง๋ง ํ ๊ฑธ์์ฉ ๋์๊ฐ๋ค ๋ณด๋ฉด ์ด๋์ ์ ๋ฌธ๊ฐ๊ฐ ๋์ด ์์ ๊ฑฐ์ผ!
ํ์ดํ
! ๐
๐ฐ ๐ ๐
Happy Messaging!
๐ฌ ๋ ๊ถ๊ธํ ์ ์ด ์๋ค๋ฉด ์ฌ๋ฅ๋ท์์ ์ ๋ฌธ๊ฐ์ ์๋ดํด๋ณด์ธ์!
์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ ์ฑ๊ณต์ ์์ํฉ๋๋ค! ๐
๊ด๋ จ ํค์๋
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.

๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.