์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ RabbitMQ vs ์•„ํŒŒ์น˜ ์นดํ”„์นด: ๋ฉ”์‹œ์ง€ ํ์™€ ์ด๋ฒคํŠธ ์ŠคํŠธ๋ฆฌ๋ฐ ํ”Œ๋žซํผ์˜ ๋ชจ๋“  ๊ฒƒ

๐Ÿš€ RabbitMQ vs ์•„ํŒŒ์น˜ ์นดํ”„์นด: ๋ฉ”์‹œ์ง€ ํ์™€ ์ด๋ฒคํŠธ ์ŠคํŠธ๋ฆฌ๋ฐ ํ”Œ๋žซํผ์˜ ๋ชจ๋“  ๊ฒƒ

์นœ๊ตฌ์ฒ˜๋Ÿผ ์‰ฝ๊ฒŒ ํ’€์–ด๋ณด๋Š” ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์˜ ์„ธ๊ณ„

๐Ÿ’ฌ "์•ผ, ์šฐ๋ฆฌ ์„œ๋น„์Šค ํŠธ๋ž˜ํ”ฝ์ด ๊ฐ‘์ž๊ธฐ ํญ์ฆํ–ˆ๋Š”๋ฐ ์„œ๋ฒ„๊ฐ€ ๋‹ค์šด๋์–ด!"
๐Ÿ“Š "์ฃผ๋ฌธ ๋ฐ์ดํ„ฐ๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์Œ“์ด๋Š”๋ฐ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜์ง€?"
๐Ÿ”„ "๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋ผ๋ฆฌ ์–ด๋–ป๊ฒŒ ํ†ต์‹ ์‹œ์ผœ์•ผ ์•ˆ์ •์ ์ผ๊นŒ?"

์ด๋Ÿฐ ๊ณ ๋ฏผ ํ•œ ๋ฒˆ์ฏค ํ•ด๋ดค์ง€? ์˜ค๋Š˜์€ ํ˜„๋Œ€ ์†Œํ”„ํŠธ์›จ์–ด ์•„ํ‚คํ…์ฒ˜์—์„œ ๋นผ๋†“์„ ์ˆ˜ ์—†๋Š” ๋‘ ๊ฐ€์ง€ ํ•ต์‹ฌ ๊ธฐ์ˆ , RabbitMQ์™€ ์•„ํŒŒ์น˜ ์นดํ”„์นด(Apache Kafka)์— ๋Œ€ํ•ด ์™„์ „ ์ •๋ณตํ•ด๋ณผ ๊ฑฐ์•ผ! ๐Ÿ˜Ž

RabbitMQ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค ๐Ÿฐ ์ž‘์—… ํ ๋ผ์šฐํŒ… ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ ๋ณด์žฅ Apache Kafka ์ด๋ฒคํŠธ ์ŠคํŠธ๋ฆฌ๋ฐ ๐Ÿ“Š ๋Œ€์šฉ๋Ÿ‰ ์ฒ˜๋ฆฌ ๋กœ๊ทธ ์ˆ˜์ง‘ ์‹ค์‹œ๊ฐ„ ๋ถ„์„ VS

๐Ÿ“š ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์ด ๋ญ๊ธธ๋ž˜?

๋ณธ๊ฒฉ์ ์œผ๋กœ ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—, ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์ด ์™œ ํ•„์š”ํ•œ์ง€๋ถ€ํ„ฐ ์ดํ•ดํ•ด๋ณด์ž!

์˜›๋‚  ์˜›์ ์—๋Š” ์„œ๋น„์Šค๊ฐ€ ๋‹จ์ˆœํ–ˆ์–ด. ํ•˜๋‚˜์˜ ๊ฑฐ๋Œ€ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(๋ชจ๋†€๋ฆฌ์‹)์ด ๋ชจ๋“  ๊ฑธ ์ฒ˜๋ฆฌํ–ˆ์ง€. ๊ทผ๋ฐ ์„œ๋น„์Šค๊ฐ€ ์ปค์ง€๋ฉด์„œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์–ด:

๐Ÿ”ฅ ์ „ํ†ต์ ์ธ ๋ฐฉ์‹์˜ ๋ฌธ์ œ์ ๋“ค:
โ€ข ํ•œ ๋ถ€๋ถ„์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋ฉด ์ „์ฒด ์‹œ์Šคํ…œ์ด ๋‹ค์šด
โ€ข ํŠธ๋ž˜ํ”ฝ ํญ์ฆ ์‹œ ์„œ๋ฒ„๊ฐ€ ๋ฒ„ํ‹ฐ์ง€ ๋ชปํ•จ
โ€ข ์„œ๋น„์Šค ๊ฐ„ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ์œผ๋กœ ์œ ์ง€๋ณด์ˆ˜ ์ง€์˜ฅ
โ€ข ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๊ฐ€ ์–ด๋ ค์›€

๊ทธ๋ž˜์„œ ๋“ฑ์žฅํ•œ ๊ฒŒ ๋ฐ”๋กœ ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์ด์•ผ! ๐ŸŽฏ

๐Ÿ’ก ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์˜ ํ•ต์‹ฌ ๊ฐœ๋…

๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์€ ์ค‘๊ฐ„ ๋‹ค๋ฆฌ ์—ญํ• ์„ ํ•ด. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋“ค์ด ์ง์ ‘ ํ†ต์‹ ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ๋ฉ”์‹œ์ง€๋ฅผ ์ค‘๊ฐ„์— ์žˆ๋Š” ์‹œ์Šคํ…œ์— ๋ณด๋‚ด๊ณ  ๋ฐ›๋Š” ๊ฑฐ์ง€.

๋ฐœ์‹ ์ž(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์œผ๋กœ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ!

๐Ÿ Producer (๋ฉ”์‹œ์ง€ ๋ฐœ์†ก)
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()
๐Ÿ Consumer (๋ฉ”์‹œ์ง€ ์ˆ˜์‹ )
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๋ฅผ ์„ ํƒํ•œ ์ด์œ ๋Š” ์•ˆ์ •์„ฑ๊ณผ ์œ ์—ฐ์„ฑ ๋•Œ๋ฌธ์ด์•ผ!

RabbitMQ ๋ฉ”์‹œ์ง€ ํ๋ฆ„ Producer ๐Ÿ“ค Exchange ๐Ÿ”€ Queue 1 ๐Ÿ“ฆ Queue 2 ๐Ÿ“ฆ Consumer ๐Ÿ“ฅ ๋ฉ”์‹œ์ง€ ์ „์†ก ๋ผ์šฐํŒ… ์ฒ˜๋ฆฌ ํ•ต์‹ฌ ํŠน์ง• ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ ๋ณด์žฅ ยท ์œ ์—ฐํ•œ ๋ผ์šฐํŒ… ๋‹ค์–‘ํ•œ Exchange ํƒ€์ž… ์ง€์›

๐Ÿ“Š 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๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ๋ณผ๊นŒ?

๐Ÿ Producer (์ด๋ฒคํŠธ ๋ฐœํ–‰)
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()
๐Ÿ Consumer (์ด๋ฒคํŠธ ๊ตฌ๋…)
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๋ฅผ ์„ ํƒํ•œ ์ด์œ ๋Š” ๋Œ€์šฉ๋Ÿ‰ ์ฒ˜๋ฆฌ ๋Šฅ๋ ฅ๊ณผ ํ™•์žฅ์„ฑ ๋•Œ๋ฌธ์ด์•ผ!

Apache Kafka ์•„ํ‚คํ…์ฒ˜ Producer ๐Ÿ“ค Kafka Cluster Partition 0 Offset: 0-999 Partition 1 Offset: 0-999 Partition 2 Offset: 0-999 Topic: user-events โœ“ ๋ถ„์‚ฐ ์ €์žฅ โœ“ ๋ณต์ œ๋ณธ ์œ ์ง€ โœ“ ์ˆœ์„œ ๋ณด์žฅ Consumer ๐Ÿ“ฅ ๋ฐœํ–‰ ๊ตฌ๋… ํ•ต์‹ฌ: ํŒŒํ‹ฐ์…˜ ๊ธฐ๋ฐ˜ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์ดˆ๋‹น ์ˆ˜๋ฐฑ๋งŒ ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ!

โš–๏ธ 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 ์„ค์น˜ ๋ฐ ์„ค์ •

๐Ÿณ Docker๋กœ 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)
โš™๏ธ RabbitMQ ์„ค์ • ํŒŒ์ผ (rabbitmq.conf)
# ๋ฉ”๋ชจ๋ฆฌ ์ œํ•œ ์„ค์ •
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 ์„ค์น˜ ๋ฐ ์„ค์ •

๐Ÿณ Docker Compose๋กœ 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 ํ† ํ”ฝ ์ƒ์„ฑ ๋ฐ ๊ด€๋ฆฌ
# ํ† ํ”ฝ ์ƒ์„ฑ
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()
๐Ÿ ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ์„œ๋น„์Šค (Kafka)
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