서론: 왜 EDA인가?
현대 애플리케이션은 점점 더 복잡해지고, 하나의 장애가 전체 시스템을 멈추게 하는 단일 장애점(SPOF) 문제가 빈번하게 발생합니다. 특히 동기식 HTTP 호출로 구성된 마이크로서비스 아키텍처는 하나의 서비스가 느려지면 연쇄적으로 타임아웃이 발생하는 '장애의 전파'를 경험하게 됩니다.
Amazon Key 팀(스마트 잠금장치 및 배송 시스템)도 같은 문제를 겪었습니다. 초기에는 주문 처리, 배송 알림, 디바이스 제어 등이 모두 동기식 REST API로 연결되어 있었습니다. 하지만 블랙 프라이데이 같은 대규모 트래픽이 발생하면 특정 서비스의 지연이 전체 시스템의 병목이 되었죠.
이들의 해결책은 이벤트 기반 아키텍처(EDA) 로의 전환이었습니다. 이 글에서는 Amazon Key 팀이 실제로 사용한 패턴과 주의사항을 정리합니다. 특히, 단순히 "EDA가 좋다"는 추상적인 이야기가 아니라, 어떤 문제를 어떻게 해결했는지에 초점을 맞춥니다. (참고로, 이 글의 핵심 내용은 원문 자료를 기반으로 재구성했습니다.)
본론 1: 동기식 호출의 문제점과 이벤트 기반 전환의 시작
Amazon Key 팀이 가장 먼저 깨달은 것은 동기식 호출의 한계였습니다. 예를 들어, 주문 처리 서비스가 배송 서비스를 호출하고, 배송 서비스가 다시 디바이스 제어 서비스를 호출하는 구조에서는 어느 하나가 느려지면 전체 응답 시간이 증가합니다.
| 패턴 | 문제점 |
|---|---|
| 동기식 REST | 타임아웃, 재시도 폭탄, 장애 전파 |
| 비동기 메시지 | 복잡성 증가, 순서 보장 어려움 |
| 이벤트 기반 | 중간 단계 제거, 확장성 향상 |
이들은 이벤트 버스(Amazon EventBridge) 를 도입하여 각 서비스가 이벤트를 발행하고 구독하는 방식으로 전환했습니다. 예를 들어, 주문이 완료되면 OrderPlaced 이벤트가 발행되고, 배송 서비스는 이를 구독하여 처리합니다. 이렇게 하면 주문 서비스는 배송 서비스의 상태를 알 필요가 없어집니다.
핵심 코드 예제 (TypeScript):
// 이벤트 발행 예제 (AWS SDK 사용)
import { EventBridgeClient, PutEventsCommand } from "@aws-sdk/client-eventbridge";
const client = new EventBridgeClient({ region: "us-east-1" });
async function publishOrderPlaced(orderId: string, userId: string) {
const command = new PutEventsCommand({
Entries: [
{
Source: "order.service",
DetailType: "OrderPlaced",
Detail: JSON.stringify({ orderId, userId }),
EventBusName: "default",
},
],
});
await client.send(command);
console.log(`이벤트 발행 완료: ${orderId}`);
}
이 코드는 주문 서비스가 이벤트를 발행하는 가장 기본적인 예시입니다. 실제로는 이벤트 스키마를 명확히 정의하고, DLQ(Dead Letter Queue)를 설정하는 것이 중요합니다.
본론 2: EDA 도입 시 주의사항과 실무 팁
EDA로 전환하는 것은 단순히 기술 스택을 바꾸는 문제가 아닙니다. Amazon Key 팀은 다음과 같은 주의사항을 강조합니다.
1. 이벤트 스키마 관리
이벤트는 계약(Contract)입니다. 이벤트 스키마가 변경되면 모든 구독자에게 영향을 주므로, 스키마 레지스트리를 사용해 버전 관리를 해야 합니다. 예를 들어, OrderPlaced 이벤트에 필드를 추가할 때는 반드시 새 버전을 만들고, 구독자들이 마이그레이션할 시간을 줘야 합니다.
2. 순서 보장과 멱등성
특정 이벤트는 순서가 중요할 수 있습니다(예: OrderCreated → OrderPaid). 하지만 분산 시스템에서 순서를 완벽히 보장하는 것은 어렵습니다. 따라서 이벤트 처리 로직은 멱등성(Idempotency) 을 가져야 합니다. 즉, 같은 이벤트를 두 번 처리해도 결과가 같아야 합니다.
// 멱등성 보장 예제: 주문 상태를 업데이트할 때 현재 상태를 확인
async function handleOrderPaid(event: OrderPaidEvent) {
const order = await getOrder(event.orderId);
if (order.status === "PAID") {
console.log("이미 처리된 이벤트입니다. 건너뜁니다.");
return;
}
// 실제 처리 로직
}
3. 관찰 가능성(Observability)
이벤트 기반 시스템은 흐름을 추적하기 어렵습니다. 따라서 분산 추적(Distributed Tracing) 과 로그 수집을 필수로 구성해야 합니다. AWS X-Ray이나 OpenTelemetry를 사용하면 이벤트의 생애주기를 추적할 수 있습니다.
4. 한국 개발 생태계에서의 적용 맥락
국내에서는 대부분의 시스템이 여전히 동기식 API에 의존하고 있습니다. 특히 금융권이나 공공기관은 레거시 시스템과의 통합 문제로 EDA 도입이 쉽지 않습니다. 하지만 신규 프로젝트에서는 처음부터 이벤트 기반을 고려하는 것이 좋습니다. 예를 들어, 쿠팡이나 배달의민족 같은 대규모 트래픽을 처리하는 서비스는 이미 EDA를 적극적으로 사용하고 있습니다.
5. 이 기술의 한계 또는 주의사항
EDA는 만능 해결책이 아닙니다. 이벤트 기반 시스템은 디버깅이 어렵고, 초기 설계 비용이 높습니다. 또한, 이벤트가 쌓이는 지연 시간이 발생할 수 있어 실시간 처리가 필요한 경우에는 오히려 동기식이 적합할 수 있습니다. 따라서 트레이드오프를 명확히 이해하고 도입해야 합니다.
결론: 실무 적용 조언 및 마무리
Amazon Key 팀의 경험에서 얻은 핵심 교훈은 '단일 장애점을 제거하는 것' 입니다. EDA는 이를 위한 훌륭한 도구이지만, 도입 과정에서 발생하는 복잡성을 관리하는 것이 더 중요합니다.
다음 단계로는 이벤트 스키마 레지스트리, 서킷 브레이커, 그리고 이벤트 소싱 패턴을 공부해보시길 권장합니다. 또한, Vercel Pro 팀의 역할 기반 접근 권한처럼, 시스템의 접근 제어도 이벤트 기반으로 설계할 수 있는지 고민해보세요.
마지막으로, EDA 도입은 팀 전체의 합의가 필요합니다. 개발자뿐 아니라 운영, 기획, 디자인까지 모두가 이벤트 중심의 사고를 가져야 성공할 수 있습니다. 시작은 작게, 그러나 확실하게!

본론 1: 동기식 호출의 문제점과 이벤트 기반 전환의 시작
Amazon Key 팀이 가장 먼저 깨달은 것은 동기식 호출의 한계였습니다. 예를 들어, 주문 처리 서비스가 배송 서비스를 호출하고, 배송 서비스가 다시 디바이스 제어 서비스를 호출하는 구조에서는 어느 하나가 느려지면 전체 응답 시간이 증가합니다.
| 패턴 | 문제점 |
|---|---|
| 동기식 REST | 타임아웃, 재시도 폭탄, 장애 전파 |
| 비동기 메시지 | 복잡성 증가, 순서 보장 어려움 |
| 이벤트 기반 | 중간 단계 제거, 확장성 향상 |
이들은 이벤트 버스(Amazon EventBridge) 를 도입하여 각 서비스가 이벤트를 발행하고 구독하는 방식으로 전환했습니다. 예를 들어, 주문이 완료되면 OrderPlaced 이벤트가 발행되고, 배송 서비스는 이를 구독하여 처리합니다. 이렇게 하면 주문 서비스는 배송 서비스의 상태를 알 필요가 없어집니다.
핵심 코드 예제 (TypeScript):
// 이벤트 발행 예제 (AWS SDK 사용)
import { EventBridgeClient, PutEventsCommand } from "@aws-sdk/client-eventbridge";
const client = new EventBridgeClient({ region: "us-east-1" });
async function publishOrderPlaced(orderId: string, userId: string) {
const command = new PutEventsCommand({
Entries: [
{
Source: "order.service",
DetailType: "OrderPlaced",
Detail: JSON.stringify({ orderId, userId }),
EventBusName: "default",
},
],
});
await client.send(command);
console.log(`이벤트 발행 완료: ${orderId}`);
}
이 코드는 주문 서비스가 이벤트를 발행하는 가장 기본적인 예시입니다. 실제로는 이벤트 스키마를 명확히 정의하고, DLQ(Dead Letter Queue)를 설정하는 것이 중요합니다.

본론 2: EDA 도입 시 주의사항과 실무 팁
EDA로 전환하는 것은 단순히 기술 스택을 바꾸는 문제가 아닙니다. Amazon Key 팀은 다음과 같은 주의사항을 강조합니다.
1. 이벤트 스키마 관리
이벤트는 계약(Contract)입니다. 이벤트 스키마가 변경되면 모든 구독자에게 영향을 주므로, 스키마 레지스트리를 사용해 버전 관리를 해야 합니다. 예를 들어, OrderPlaced 이벤트에 필드를 추가할 때는 반드시 새 버전을 만들고, 구독자들이 마이그레이션할 시간을 줘야 합니다.
2. 순서 보장과 멱등성
특정 이벤트는 순서가 중요할 수 있습니다(예: OrderCreated → OrderPaid). 하지만 분산 시스템에서 순서를 완벽히 보장하는 것은 어렵습니다. 따라서 이벤트 처리 로직은 멱등성(Idempotency) 을 가져야 합니다. 즉, 같은 이벤트를 두 번 처리해도 결과가 같아야 합니다.
// 멱등성 보장 예제: 주문 상태를 업데이트할 때 현재 상태를 확인
async function handleOrderPaid(event: OrderPaidEvent) {
const order = await getOrder(event.orderId);
if (order.status === "PAID") {
console.log("이미 처리된 이벤트입니다. 건너뜁니다.");
return;
}
// 실제 처리 로직
}
3. 관찰 가능성(Observability)
이벤트 기반 시스템은 흐름을 추적하기 어렵습니다. 따라서 분산 추적(Distributed Tracing) 과 로그 수집을 필수로 구성해야 합니다. AWS X-Ray이나 OpenTelemetry를 사용하면 이벤트의 생애주기를 추적할 수 있습니다.
4. 한국 개발 생태계에서의 적용 맥락
국내에서는 대부분의 시스템이 여전히 동기식 API에 의존하고 있습니다. 특히 금융권이나 공공기관은 레거시 시스템과의 통합 문제로 EDA 도입이 쉽지 않습니다. 하지만 신규 프로젝트에서는 처음부터 이벤트 기반을 고려하는 것이 좋습니다. 예를 들어, 쿠팡이나 배달의민족 같은 대규모 트래픽을 처리하는 서비스는 이미 EDA를 적극적으로 사용하고 있습니다.
5. 이 기술의 한계 또는 주의사항
EDA는 만능 해결책이 아닙니다. 이벤트 기반 시스템은 디버깅이 어렵고, 초기 설계 비용이 높습니다. 또한, 이벤트가 쌓이는 지연 시간이 발생할 수 있어 실시간 처리가 필요한 경우에는 오히려 동기식이 적합할 수 있습니다. 따라서 트레이드오프를 명확히 이해하고 도입해야 합니다.

결론: 실무 적용 조언 및 마무리
Amazon Key 팀의 경험에서 얻은 핵심 교훈은 '단일 장애점을 제거하는 것' 입니다. EDA는 이를 위한 훌륭한 도구이지만, 도입 과정에서 발생하는 복잡성을 관리하는 것이 더 중요합니다.
다음 단계로는 이벤트 스키마 레지스트리, 서킷 브레이커, 그리고 이벤트 소싱 패턴을 공부해보시길 권장합니다. 또한, Vercel Pro 팀의 역할 기반 접근 권한처럼, 시스템의 접근 제어도 이벤트 기반으로 설계할 수 있는지 고민해보세요.
마지막으로, EDA 도입은 팀 전체의 합의가 필요합니다. 개발자뿐 아니라 운영, 기획, 디자인까지 모두가 이벤트 중심의 사고를 가져야 성공할 수 있습니다. 시작은 작게, 그러나 확실하게!