학습 목표

시나리오

주문 서비스가 이벤트를 게시하고, 여러 팀이 각자 반응합니다.

마지막 조건이 이벤트 버스를 고르는 이유입니다. 구독자를 추가하는 일이 규칙 하나를 만드는 일로 끝납니다.

아키텍처 개요

SNS 팬아웃과 EventBridge 라우팅의 구조 차이
항목 Amazon SNS 팬아웃 Amazon EventBridge
전달 방식 주제를 구독한 모든 대상에 브로드캐스트 이벤트 패턴에 맞는 규칙의 대상에만 전달
필터링 구독 필터 정책으로 메시지 속성 기준 이벤트 본문 구조 전체를 패턴으로 매칭
대상 종류 큐·함수·HTTP·이메일 등 훨씬 다양한 AWS 서비스
AWS 서비스 이벤트 직접 받지 않는다 기본 버스로 들어온다
스키마 정의되지 않는다 스키마 레지스트리로 관리할 수 있다

이 실습은 사용자 지정 버스를 씁니다. AWS 서비스가 내보내는 이벤트는 기본 버스로 들어오므로, 애플리케이션 이벤트를 섞지 않으려면 버스를 나누는 편이 관리하기 쉽습니다.

구성 단계

1 · 사용자 지정 이벤트 버스

create-bus.sh — 버스 생성
aws events create-event-bus \
  --name lab08-orders-bus \
  --query 'EventBusArn' --output text

2 · 이벤트 형태 정하기

EventBridge 이벤트는 Source · DetailType · Detail 세 가지가 핵심입니다. 이 셋을 규칙에서 매칭하므로, 처음에 명명 규칙을 정해 두면 나중이 편합니다.

put-events.sh — 주문 생성 이벤트 게시
aws events put-events --entries '[
  {
    "EventBusName": "lab08-orders-bus",
    "Source": "example.orders",
    "DetailType": "OrderCreated",
    "Detail": "{\"orderId\":\"ord-1001\",\"customerId\":\"cust-001\",\"totalAmount\":42000}"
  }
]'

3 · 규칙과 대상

rule-created.json — 주문 생성 이벤트만 매칭하는 패턴
{
  "source": ["example.orders"],
  "detail-type": ["OrderCreated"]
}
rule-high-value.json — 금액 기준을 넘는 주문만 매칭
{
  "source": ["example.orders"],
  "detail-type": ["OrderCreated"],
  "detail": {
    "totalAmount": [{ "numeric": [">=", 1000000] }]
  }
}
create-rules.sh — 규칙 생성과 대상 연결 (ARN은 예시입니다)
aws events put-rule \
  --name lab08-order-created \
  --event-bus-name lab08-orders-bus \
  --event-pattern file://rule-created.json \
  --state ENABLED

aws events put-targets \
  --rule lab08-order-created \
  --event-bus-name lab08-orders-bus \
  --targets '[
    {
      "Id": "notify-fn",
      "Arn": "arn:aws:lambda:ap-northeast-2:123456789012:function:lab08-notify",
      "RetryPolicy": { "MaximumRetryAttempts": 2, "MaximumEventAgeInSeconds": 3600 },
      "DeadLetterConfig": {
        "Arn": "arn:aws:sqs:ap-northeast-2:123456789012:lab08-events-dlq"
      }
    }
  ]'

aws events put-rule \
  --name lab08-high-value \
  --event-bus-name lab08-orders-bus \
  --event-pattern file://rule-high-value.json \
  --state ENABLED

aws events put-targets \
  --rule lab08-high-value \
  --event-bus-name lab08-orders-bus \
  --targets '[
    {
      "Id": "review-queue",
      "Arn": "arn:aws:sqs:ap-northeast-2:123456789012:lab08-review"
    }
  ]'

4 · 대상 호출 권한

실습 6과 같은 구조입니다. 대상 쪽에 "EventBridge가 호출해도 된다"는 권한이 있어야 합니다.

grant-invoke.sh — Lambda 대상에 리소스 기반 권한 추가
RULE_ARN=$(aws events describe-rule \
  --name lab08-order-created \
  --event-bus-name lab08-orders-bus \
  --query 'Arn' --output text)

aws lambda add-permission \
  --function-name lab08-notify \
  --statement-id eventbridge-order-created \
  --action lambda:InvokeFunction \
  --principal events.amazonaws.com \
  --source-arn "$RULE_ARN"

SQS 큐가 대상이면 큐 정책에 events.amazonaws.com의 sqs:SendMessage를 허용하고, 조건으로 규칙 ARN을 지정합니다.

5 · 예약 규칙

create-schedule.sh — 주기적으로 대상을 호출하는 규칙 (기본 버스에서만 동작합니다)
aws events put-rule \
  --name lab08-nightly-reconcile \
  --schedule-expression "cron(0 18 * * ? *)" \
  --state ENABLED

aws events put-targets \
  --rule lab08-nightly-reconcile \
  --targets '[{
      "Id": "reconcile-fn",
      "Arn": "arn:aws:lambda:ap-northeast-2:123456789012:function:lab08-reconcile"
    }]'

검증 방법

패턴을 먼저 시험한다

규칙을 만들기 전에 패턴이 실제 이벤트와 맞는지 확인할 수 있습니다. 이벤트가 전달되지 않는 문제의 대부분은 패턴 불일치입니다.

test-pattern.sh — 패턴과 이벤트를 대조
aws events test-event-pattern \
  --event-pattern '{"source":["example.orders"],"detail-type":["OrderCreated"]}' \
  --event '{
      "id": "test-1",
      "source": "example.orders",
      "detail-type": "OrderCreated",
      "account": "123456789012",
      "region": "ap-northeast-2",
      "time": "2026-07-29T10:00:00Z",
      "resources": [],
      "detail": { "orderId": "ord-1001", "totalAmount": 42000 }
    }' \
  --query 'Result'
verify.sh — 규칙·대상 확인과 게시 결과
aws events list-rules \
  --event-bus-name lab08-orders-bus \
  --query 'Rules[].[Name,State,EventPattern]' --output table

aws events list-targets-by-rule \
  --rule lab08-order-created \
  --event-bus-name lab08-orders-bus \
  --query 'Targets[].[Id,Arn]' --output table

# 게시 결과에서 실패 항목 수를 확인합니다.
aws events put-events --entries '[{
    "EventBusName":"lab08-orders-bus",
    "Source":"example.orders",
    "DetailType":"OrderCreated",
    "Detail":"{\"orderId\":\"ord-1002\",\"totalAmount\":2000000}"
  }]' \
  --query '[FailedEntryCount, Entries]'
검증 항목과 기대 결과
항목 기대 결과
일반 주문 이벤트 알림 대상만 호출된다
고액 주문 이벤트 알림과 심사 양쪽 규칙에 모두 매칭된다
다른 Source의 이벤트 어느 규칙에도 매칭되지 않는다
권한이 없는 대상 전달이 실패하고 재시도 후 DLQ로 간다
FailedEntryCount 0이어야 한다

비용 고려

요금이 발생하는 항목
항목 성격
사용자 지정 이벤트 게시한 이벤트 수
AWS 서비스 이벤트 기본 버스로 들어오는 이벤트의 취급이 다르다
대상 호출 호출되는 대상 서비스(Lambda·SQS 등)의 요금이 별도로 발생한다
아카이브와 재생 보관한 이벤트 양과 재생한 이벤트 수
재시도 실패가 반복되면 대상 호출이 늘어난다

비용을 좌우하는 것은 이벤트 수입니다. 모든 상태 변화를 이벤트로 만들면 양이 빠르게 늘어납니다. "누군가 반응해야 하는 사실"만 이벤트로 만들고, 내부 상태 변화는 이벤트로 올리지 않는 편이 좋습니다.

프로덕션 고려사항

정리 — 리소스 삭제

cleanup.sh — 대상 · 규칙 · 버스 순서로 삭제
aws events remove-targets \
  --rule lab08-order-created \
  --event-bus-name lab08-orders-bus \
  --ids notify-fn

aws events delete-rule \
  --name lab08-order-created \
  --event-bus-name lab08-orders-bus

aws events remove-targets \
  --rule lab08-high-value \
  --event-bus-name lab08-orders-bus \
  --ids review-queue

aws events delete-rule \
  --name lab08-high-value \
  --event-bus-name lab08-orders-bus

aws events remove-targets --rule lab08-nightly-reconcile --ids reconcile-fn
aws events delete-rule --name lab08-nightly-reconcile

aws events delete-event-bus --name lab08-orders-bus

자주 하는 실수

자주 나오는 실수와 증상
실수 증상 고치는 법
EventBusName을 빠뜨림 이벤트가 기본 버스로 가서 규칙에 잡히지 않는다 게시와 규칙 양쪽에 버스 이름을 명시한다
Detail을 객체로 전달 게시가 실패한다 JSON을 문자열로 인코딩한다
FailedEntryCount를 확인하지 않음 일부 이벤트가 조용히 유실된다 응답을 확인하고 실패 시 재시도한다
대상에 호출 권한이 없음 규칙은 매칭되는데 아무 일도 일어나지 않는다 리소스 기반 정책이나 큐 정책을 추가한다
사용자 지정 버스에 일정 표현식 동작하지 않는다 예약 규칙은 기본 버스에 만든다
일정 표현식을 현지 시각으로 작성 의도한 시각과 다르게 실행된다 UTC로 환산하거나 시간대를 명시한다
DLQ 없이 운영 전달 실패가 흔적 없이 사라진다 대상마다 배달 못한 편지 대기열을 지정한다

이어서 볼 곳

공식 문서 출처