이벤트 기반 아키텍처
출처: Dev.to
Uncle(백엔드 아키텍처) 과 Nephew(호기심 많은 개발자) 사이의 대화, 이벤트, 퍼블리셔, 구독자, Redis Pub/Sub, RabbitMQ, Kafka에 대해
시작: 이벤트란 무엇일까?
👦 네프ュー: 언클, 직업 소개 글에서는 “Redis Pub/Sub”, “RabbitMQ”, “Kafka” 라는 단어들을 많이 보여. 각각은 무엇을 하나? 같은 건가요?
👨🦳 언클: (웃으며) 아니요, 서로 다릅니다. 하지만 먼저 이름이 confusione를 일으키지 않게 하겠습니 다. 한 가지 질문 드릴게요. TV에서 뉴스를 본 적 있으신가요?
👦 네프ュー: 예, 언클, 매일 아침!
👨🦳 언클: 완벽해! 그래서 뉴스 채널이 “브레이킹 뉴스: 인도가 크리켓 경기에서 승리했습니다” 라고 말하면 어떻게 될까?
👦 네프ュー: 중요한 일이 일어났… 그리고 그들은 발표했다!
👨🦳 언클: 정확히! 그 “중요한 일이 발생했다”는 것을 이벤트 라고 부릅니다. 소프트웨어에서 어떤 일이 일어나면 - 사용자가 주문을 넣거나, 결제가 성공하거나, 파일이 업로드될 때 - 그것이 이벤트예요.
👦 네프ュー: 즉, 이벤트 = 일어난 일이라는 거야?
👨🦳 언클: 그래!Think of it as news. Zomato에서 주문을 넣으면那是 이벤트야. Google Pay에서 결제 알림을 받으면那是 이벤트야. Instagram에서 누군가가 당신을 팔로우하면那是 이벤트야.
👦 네프ュー: 알겠어. 그런데 언클, 이 “이벤트” 개념이 왜 중요한데, 그냥 직접 코드를 작성하면 되지 않아?
👨🦳 언클: 아! 진짜 이야기가 시작되는 곳이야…
문제: 스파게티 코드
👨🦳 **언클:**想象你拥有一家食品配送公司。客户下单后,需要发生哪些事情?
👦 네프ュー: 응… 주문을 저장하고, 이메일 확인을 보낼 것 같고, 레스토랑에 알릴 것도 있지?
👨🦳 언클: Good! Let me write the code without events:
function placeOrder(orderId) {
saveOrder(orderId);
sendEmailConfirmation(orderId);
sendSMSNotification(orderId);
notifyRestaurant(orderId);
updateAnalyticsDashboard(orderId);
addLoyaltyPoints(orderId);
updateInventory(orderId);
}
Enter fullscreen mode
Exit fullscreen mode
Now, one day your boss says “Also send WhatsApp notification”. What do you do?
👦 네프ュー: 코드에 또 함수 호출을 추가하면 되지 않나요?
👨🦳 언클: 네, 하지만 그러면 함수는 더 커집니다. 내일 상사가 “알림도 보내라”고 하면 추가로 함수를 넣어야 합니다. Order Service는 이제 주문을 저장하고 이메일·SMS·레스토랑 알리기·분석 대시보드 업데이트·로열티 포인트 적립·재고 업데이트 등 10가지 일을 모두 수행하는 거대한 코드 블롭이 됩니다.
Hard to maintain - Change one thing, something else breaks
Tightly coupled - Every service knows about every other service
Hard to scale - One service dying affects everything
This is called spaghetti code. Everyone is tangled together.
👦 네프ュー: That sounds awful! So what’s the solution?
👨🦳 언클: What if the Order Service just announces “Order Created” and doesn’t care who’s listening?
Enter: Publisher & Subscriber
👨🦳 언클: Remember the news channel? The channel broadcasts news. The viewers listen if they want. The channel doesn’t know who’s watching – could be 1 person or 1 million.
👦 네프ュー: Yes, like YouTube!
👨🦳 언클: Perfect! YouTube is the Publisher – they create content. You are the Subscriber – you listen. The video upload is the Event.
Now in our food delivery system:
Order Service = Publisher (creates the event “Order Created”)
Email Service, SMS Service, Analytics = Subscribers (listen to that event)
The Order Service just announces:
📢 "Order Created - Order #123"
Enter fullscreen mode
Exit fullscreen mode
And doesn’t care who listens!
👦 네프ュー: So if tomorrow boss wants WhatsApp notification, I just add another subscriber?
👨🦳 언클: Exactly! Order Service doesn’t change. You just create a WhatsApp Service that subscribes to “Order Created” events. Beautiful decoupling!
👦 네프ュー: Amazing! But uncle, how do they communicate? There must be something in the middle passing messages around?
👨🦳 언클: Yes! That’s where Redis Pub/Sub comes in…
Redis Pub/Sub: The Simple Messenger
👨🦳 언클: Think of it like a WhatsApp group. You have a group called “Order Events”. When someone posts a message, everyone in the group sees it.
👦 네프ュー: Oh! So Order Service is like one person posting in the group, and others are reading?
👨🦳 언클: Exactly! Here’s how it works:
Order Service (Publisher)
|
| Publishes to channel: "order-created"
v
Redis
|
-----+-----
| | |
v v v
Email SMS Analytics
Service Service Service
(Subscribers)
Enter fullscreen mode
Exit fullscreen mode
Each service subscribes to a “channel” – like joining a WhatsApp group.
Order Service publishes:
redis.publish('order-created', {
orderId: 123,
userId: 456,
amount: 500
});
Enter fullscreen mode
Exit fullscreen mode
Email Service listens:
redis.subscribe('order-created', (message) => {
sendEmail(message.userId);
});
Enter fullscreen mode
Exit fullscreen mode
👦 네프ュー: So Redis is like the WhatsApp server?
👨🦳 언클: Exactly! Redis is the messenger sitting in the middle, broadcasting messages.
👦 네프ュー: This seems perfect! Why would we need anything else?
👨🦳 언클: Ah, great question! Here comes the problem…
The Crash: Redis Pub/Sub’s Dirty Secret
👨🦳 언클: Imagine it’s 10:00 AM. Order Service publishes:
"Order Created - Order #123"
Enter fullscreen mode
Exit fullscreen mode
But at that exact moment, Email Service has crashed (network issue). Redis broadcasts the message. Email Service isn’t listening. Message is gone. Forever.
👦 네프ュー: Oh no! So the customer never gets the confirmation email?
👨🦳 언클: Exactly! At 10:01 AM, Email Service comes back online. Can it ask Redis “Hey, what messages did I miss?”
👦 네프ュー: Can’t it?
👨🦳 언클: No! Redis says “Sorry, that message was 1 minute ago. I already sent it. I don’t save messages.”
Think of it like FM Radio:
-
Radio broadcasts live music
-
If you’re listening: ✅ You hear it
-
If you’re not listening: ❌ You miss it
-
Radio doesn’t replay old songs
👦 네프ュー: That’s a problem for important stuff like payment notifications!
👨🦳 언클: Exactly! What if the event is “Payment Success”? We CANNOT lose that message. A customer should get confirmation even if they restart their phone.
For such critical events, we need something that:
Stores messages (doesn’t lose them)
Retries (if service is down, deliver later)
Confirms (acknowledges delivery)
Redis Pub/Sub can’t do any of this. And this pain gave birth to the next hero…
RabbitMQ: The Reliable Messenger
👦 네프ュー: What can RabbitMQ do that Redis can’t?
👨🦳 언클: Let me draw you a scenario. Same 10:00 AM order.
Order Service sends to RabbitMQ:
Order #123 Created
Enter fullscreen mode
Exit fullscreen mode
RabbitMQ says “Got it! I’m storing this message in a Queue.”
Now, even if Email Service is down, the message stays in the queue.
When Email Service comes back online at 10:01 AM, RabbitMQ says:
“Hey! You have 1 message. Here it is.”
Email Service reads and processes it.
👦 네프ュー: So RabbitMQ is like a post office?
👨🦳 언클: Perfect analogy! The post office stores your letters even if the recipient isn’t home. When they come back, they get the letter.
But there’s a twist…
Queues & Workers
👨🦳 언클: In RabbitMQ, we don’t have “subscribers listening”. Instead, we have workers pulling messages.
Imagine a pizza shop:
- Kitchen has a Queue of pizza orders written on paper
Worker 1 pulls an order: “Margherita Pizza”
-
Worker 1 makes it and says “ACK” (acknowledgement) – “I got it!”
-
Order is removed from queue
Worker 2 pulls next order