🔥 Events, EventBridge의 이전 이름과 현재

2057자
23분

16:9 가로 표지 일러스트레이션. 흰 배경, 둥근 모서리, 절제된 그림자. 위쪽에 'EventBridge Events' 제목이 다크 슬레이트 #1e293b 굵은 산세리프로 적혀 있다. 가운데에는 큰 envelope 형태 카드가 둥근 모서리 슬레이트 #cbd5e1 외곽선으로 그려져 있고, 그 위에 'event' 문자가 모노스페이스 폰트로 적혀 있다. envelope 카드 아래에는 작은 라벨 9개 ('version', 'id', 'detail-type', 'source', 'account', 'time', 'region', 'resources', 'detail')가 두 줄로 정렬돼 있다. 카드 좌우로 가로 화살표가 뻗어 좌측에는 EC2/S3/Lambda 작은 AWS 오렌지 #ff9900 아이콘 묶음(producers), 우측에는 Lambda/SQS/SNS/Step Functions 작은 에메랄드 그린 #10b981 아이콘 묶음(targets)이 그려져 있다. 왼쪽 위 모서리에는 '2019-07 → EventBridge'라는 작은 슬레이트 #475569 타임라인 배지가 사선으로 적혀 있다. 흰 배경, 둥근 모서리, 절제된 그림자, 깔끔한 산세리프 글꼴의 프로페셔널 IT 표지

EC2 인스턴스 한 대가 새벽 2시에 stopped 상태로 떨어진 적이 있다. 자동 종료 정책이 잘못 걸려 있었던 대목이었는데, 그 자체보다 더 흥미로웠던 건 그 다음 줄이었다. Lambda 한 줄이 자동으로 다시 켰다. EC2 콘솔도, CloudWatch 알람도 만지지 않았는데. 그 사이를 잇는 한 줄이 EventBridge Rule이었다는 사실을 그날 새벽에 처음 또렷하게 봤다.

이 섹션의 첫 편에서 CloudWatch 4축 중 한 군데(Event)가 2019년 7월에 EventBridge라는 형제 서비스로 분리된 이야기를 한 단락으로 짚었다. 그 글이 이름이 바뀌었는지까지는 풀지 않고 다음 글로 미뤘는데, 그 다음 글이 이 지점다. 분리 자체가 아니라 Event 한 줄이 어떻게 만들어지고, 어떤 형태로 이동하고, 어디까지 닿는지를 짚는다. 이름이 왜 바뀌었는지에 대한 짧은 답은 마지막 단락에서 한 줄로 닫는다.

Event 한 줄의 형태, JSON envelope 9필드

콘솔에서 EventBridge → Event buses → default를 누르면 그 위로 이동하는 한 줄 한 줄이 다 같은 구조다. 9개 표준 필드 묶음이고, AWS 서비스가 보내든 내가 PutEvents로 직접 보내든 같은 envelope 안에 들어간다(Archive로부터 replay된 이벤트는 추가 replay-name 필드가 함께 붙는다).

그 9필드를 한 화면에 적으면 이렇게 생겼다.

json
{
  "version": "0",
  "id": "6a7e8feb-b491-4cf7-a9f1-bf3703467718",
  "detail-type": "EC2 Instance State-change Notification",
  "source": "aws.ec2",
  "account": "111122223333",
  "time": "2026-04-27T17:00:00Z",
  "region": "ap-northeast-2",
  "resources": ["arn:aws:ec2:ap-northeast-2:111122223333:instance/i-1234567890abcdef0"],
  "detail": {
    "instance-id": "i-1234567890abcdef0",
    "state": "stopped"
  }
}
json
{
  "version": "0",
  "id": "6a7e8feb-b491-4cf7-a9f1-bf3703467718",
  "detail-type": "EC2 Instance State-change Notification",
  "source": "aws.ec2",
  "account": "111122223333",
  "time": "2026-04-27T17:00:00Z",
  "region": "ap-northeast-2",
  "resources": ["arn:aws:ec2:ap-northeast-2:111122223333:instance/i-1234567890abcdef0"],
  "detail": {
    "instance-id": "i-1234567890abcdef0",
    "state": "stopped"
  }
}

version은 항상 "0"이다. 이게 바뀌어 있는 사례를 본 적이 한 번도 없다. 미래에 schema가 진화할 부분을 비워 둔 항목이라고 공식 docs에 적혀 있다. id는 EventBridge가 PutEvents 시점에 V4 UUID로 직접 만들어서 채운다. 사용자는 id를 지정할 수 없다는 한 줄짜리 규칙이 있다. 그래서 같은 페이로드를 두 번 보내도 두 개의 다른 id가 응답으로 돌아온다는 사실이 distributed tracing을 시작할 때 가장 먼저 부딪히는 대목이었다.

source는 누가 이 이벤트를 만들었는지 가리키는 필드다. AWS 서비스가 만든 모든 이벤트는 aws.로 시작한다, aws.ec2, aws.s3, aws.codepipeline. 그래서 내가 직접 만드는 custom 이벤트는 aws.로 시작하면 안 된다. 올리려고 시도하면 PutEvents가 InvalidArgument로 거절한다. 회사 도메인을 prefix로 쓰는 게 관습이라, 나는 보통 kr.codingmax.<service> 형태로 둔다.

detail-type은 이벤트의 종류를 한 문장으로 적은 라벨이다. source와 묶여서 Rule이 이 이벤트를 잡을지 말지를 결정하는 부분이라 이름이 흔들리면 안 된다. AWS 서비스 이벤트는 정한 detail-type 목록이 있어서 Service detail reference 페이지에 다 나와 있고, 내가 만든 이벤트는 내가 정한 문자열을 그대로 쓴다.

detail은 자유 형태 JSON 객체다. 비워 둘 수 있다({}). 페이로드의 본체이고, Rule이 어떤 state로 떨어진 인스턴스만 잡을지 같은 세밀한 분기를 거는 대목이기도 하다.

나머지 네 항목(account, time, region, resources)는 내가 비워 두면 EventBridge가 채운다. account는 호출자 계정 ID, region은 PutEvents가 호출된 리전, time은 이벤트 도착 시각이 들어간다. resources는 AWS 서비스 이벤트의 경우 ARN 배열로 자동 채워지고, custom 이벤트는 내가 적어 넣는다.

엔벨로프 9필드를 다 알고 나면 그 다음 단계, PutEvents, 가 더 단순하다. PutEvents 한 호출에 위 형태의 entry를 최대 10개까지 묶을 수 있고, 호출 전체 크기가 1 MB(1,048,576 bytes)를 넘을 수 없다는 한 줄짜리 한도가 있다(API Reference 출처). 한 entry가 1 MB를 다 차지하는 건 그 entry가 호출의 유일한 entry일 때 얘기고, 10개를 묶으면 합쳐 1 MB 안에 들어와야 한다. 왜 1 MB냐면, EventBridge가 이벤트를 받아 Rule pattern을 평가한 다음 5개 target까지 fan-out해야 하는데 그 모든 단계가 메모리 안에서 돌아가야 latency가 한 군데수 밀리초로 들어오기 때문이다. 1 MB가 넘는 위치에서는 claim check 패턴, 본문은 S3에 올리고 EventBridge에는 S3 Object URL만 넘기는, 이 권장이다.

PutEvents 한 호출 안에 10개 entry를 묶었을 때 일부만 실패하는 경우는 응답에 FailedEntryCountEntries[].ErrorCode로 표시한다. 전체가 한 트랜잭션이 아니라 entry 단위라는 뜻이고, 실패 entry만 골라 다음 호출에서 재시도하는 책임은 호출자한테 있다. 이 패턴이 Kafka client의 batch 응답 형식과 같은 구조라 한 번 보면 익숙하다.

16:9 가로 다이어그램. 흰 배경, 둥근 모서리, 절제된 그림자. 가운데에 큰 슬레이트 테두리 카드 한 장이 EventBridge Event JSON envelope을 표현한다. 카드 안쪽에 9개 필드가 두 단으로 정렬돼 있다. 좌측 단: version 0 (작은 회색 배지), id UUID (모노스페이스 폰트), detail-type EC2 Instance State-change Notification (앰버 강조), source aws.ec2 (AWS 오렌지). 우측 단: account 111122223333 (모노스페이스), time 2026-04-27T17:00:00Z (슬레이트), region ap-northeast-2 (서울 표시), resources ARN 배열 (작은 박스 한 줄), detail JSON 객체 instance-id state stopped (에메랄드 그린). 카드 위쪽에는 가로 화살표로 EC2 아이콘 → EventBridge default bus → Rule → 5개 Target 카드(Lambda, SQS, SNS, Step Functions, ECS)로 이어지는 흐름이 그려져 있다. 슬레이트 그레이 텍스트, AWS 오렌지 서비스 아이콘, 에메랄드 그린 detail 강조의 프로페셔널 IT 다이어그램

Rule = Event Pattern + Target, 한 이벤트가 어디로 가는지

콘솔의 Rules 메뉴에서 Create rule을 누르면 두 부분을 채우게 한다. 첫 위치가 Event pattern, 두 번째가 Target이다. 그 두 위치가 한 줄의 라우팅을 결정한다.

Event pattern은 위 9필드 형태에서 부분 매칭을 거는 작은 JSON이다. 위 EC2 stopped 사례를 잡으려면 이렇게 쓴다.

json
{
  "source": ["aws.ec2"],
  "detail-type": ["EC2 Instance State-change Notification"],
  "detail": {
    "state": ["stopped"]
  }
}
json
{
  "source": ["aws.ec2"],
  "detail-type": ["EC2 Instance State-change Notification"],
  "detail": {
    "state": ["stopped"]
  }
}

세 항목 모두 배열이라는 점이 중요하다. ["stopped", "terminated"]로 넓히면 둘 다 일치한다. 패턴은 exact match, prefix, anything-but, numeric matching, IP address matching, exists 등 여러 연산을 지원하는데, 패턴 한 장이 2,048자를 넘을 수 없다는 한 줄짜리 한도가 있다. 왜 2,048이냐면 패턴 평가가 매 이벤트마다 모든 Rule을 한 번씩 돌아야 해서 평가 비용이 곧 청구서로 들어가기 때문이다.

Target은 패턴이 매칭됐을 때 EventBridge가 호출할 곳이다. 한 Rule에 최대 5개 target을 붙일 수 있고, 이건 hard 한도라 quota 신청으로 늘릴 수 없다. 5개를 넘기면 Rule을 두 개로 쪼개야 한다. 같은 패턴, 다른 Rule, 합쳐 10개 target, 이게 가장 흔한 회피 길이다.

Target으로 받을 수 있는 AWS 서비스가 30종이 넘는데, 매일 마주치는 부분은 다섯 군데 안쪽이다. Lambda(가장 흔함, 트리거 역할), SQS(비동기 버퍼링), SNS(팬아웃 알림), Step Functions(워크플로 시작), ECS task(컨테이너 한 회 실행). 그 너머는 Kinesis stream, Firehose, API destination, EventBridge Pipes로 이어지는 대목이다. Target이 실패하면 최대 24시간, 최대 185회까지 자동 재시도하고, 그래도 실패하면 Dead Letter Queue로 보낼지는 Rule이 아니라 target 하나하나에 따로 설정한다. 한 Rule에 5개 target을 걸어 두고 그중 하나만 DLQ를 안 걸면, 그 한 군데에서 24시간 후에 이벤트가 그냥 없는 상태다는 뜻이라 운영에서 가장 자주 새는 대목이다.

16:9 가로 시퀀스 다이어그램. 흰 배경, 둥근 모서리, 절제된 그림자. 좌측에 EC2 인스턴스 아이콘과 'EC2 stopped' 라벨. 거기서 화살표가 가운데 EventBridge default bus 박스로 진행한다. EventBridge bus 박스에서 세 갈래 화살표가 우측 세 Rule 박스로 나뉜다, Rule A 'state=stopped' (에메랄드 매칭), Rule B 'state=terminated' (회색 미매칭), Rule C 'instance-type=t3' prefix (앰버 prefix 매칭). 각 Rule에서 다시 화살표가 우측 끝의 Target 카드로 진행한다, Rule A → Lambda, SQS 두 개 / Rule C → Step Functions. 매칭되지 않은 Rule B는 점선 X 표시. 슬레이트 그레이 텍스트, AWS 오렌지 EventBridge 강조, 에메랄드 매칭, 코랄 비매칭의 프로페셔널 IT 시퀀스 다이어그램

Event bus 3종, default, partner, custom

여기까지가 EC2 같은 AWS 서비스 이벤트가 이동하는 default bus 한 군데의 이야기다. EventBridge는 bus를 세 종류로 구분한다.

default bus는 한 계정·한 리전마다 하나씩 자동으로 존재한다. 250개가 넘는 AWS 서비스가 자기 이벤트를 여기로 보내고, 사용자는 PutEvents로 custom 이벤트를 같이 흘려 보낼 수도 있다. 가장 흔히 쓰는 대목이다.

partner bus는 SaaS 업체가 EventBridge에 직접 붙어 자기 이벤트를 흘려 보내는 대목이다. Datadog, MongoDB Atlas, Zendesk, PagerDuty, Auth0 같은 외부 서비스의 이벤트를 내 계정의 EventBridge bus에서 받는다는 뜻이고, 중간에 webhook 인프라를 짜지 않아도 되는 점이 가장 큰 차이다. 가격은 custom 이벤트와 같은 $1.00/M 인제스션이다. 한 계정에 partner bus를 여러 개 둘 수 있다.

custom bus는 내가 직접 만드는 bus다. 도메인을 구분하고 싶을 때, 또는 cross-account event 라우팅을 위해 별도 bus가 필요할 때 만든다. 한 리전에 최대 100개 event bus를 가질 수 있다. default 하나 + partner N개 + custom (100 − 1 − N)개 식으로 합산한다.

세 bus의 차이는 누가 이벤트를 보내는가가 결정하고, 가격은 인제스션이 주체별로 다르다. AWS management 이벤트는 default bus에서 무료로 들어온다. custom·partner는 인제스션 단계에서 $1.00/M. cross-account 전달(다른 계정의 event bus로 보내는 경우)은 custom이 $1.00/M 추가, partner가 $0.05/M 추가다. 이 비대칭이 운영에서 가장 자주 헷갈리는 대목이고, 청구서가 어디서 자라는지 짚는 첫 항목이다.

서울 리전(ap-northeast-2) 기준 PutEvents API 호출 자체의 기본 한도는 600 TPS다, us-east-1·us-west-2·eu-west-1의 10,000 TPS와 비교하면 작다. 트래픽이 큰 워크로드를 한국에서 돌릴 거면 quota 신청을 미리 넣어 두는 게 안전한 군데다.

16:9 가로 비교 다이어그램. 흰 배경, 둥근 모서리, 절제된 그림자. 위쪽 제목 'Three event bus types' 다크 슬레이트 #1e293b 굵은 산세리프. 가운데를 가는 슬레이트 #cbd5e1 세로선이 세 단으로 나누고 있다. 좌측 패널: 'default' 헤더 + AWS 오렌지 #ff9900 작은 AWS 로고 + 그 아래 EC2/S3/Lambda/RDS 4개 서비스 아이콘이 작은 화살표로 위쪽 default bus 박스로 모임. 패널 하단 라벨 'AWS management events: free / custom: 1.00/M'. 중앙 패널: 'partner' 헤더 + 외부 SaaS 로고 4개(Datadog/MongoDB/Zendesk/Auth0) 묶음에서 화살표가 가운데 partner bus 박스로 들어옴. 패널 하단 라벨 '1.00/M ingest, 0.05/M cross-account'. 우측 패널: 'custom' 헤더 + 사용자 코드 아이콘과 'PutEvents' 라벨에서 화살표가 우측 custom bus 박스로 들어옴. 패널 하단 라벨 '1.00/M ingest, 1.00/M cross-account'. 세 패널 모두 아래쪽에 작은 한도 배지 'max 100 buses per region'. 슬레이트 그레이 텍스트, AWS 오렌지 default 강조, 에메랄드 그린 partner SaaS, 보라 #8b5cf6 custom 사용자 코드의 프로페셔널 IT 비교 다이어그램

왜 이름이 바뀌었나, 세 가지 확장을 위해

CloudWatch란 무엇인가: AWS 모니터링의 중심 도구에서 한 단락 소비한 군데라 그 사실은 그쪽으로 미루고, 여기서는 왜만 한 줄로 닫는다. 2019년 7월 분리는 단순 리브랜딩이 아니었고, 세 가지 확장을 위한 군데다.

첫째, partner events. 외부 SaaS 이벤트를 받는 부분은 CloudWatch 안에 머물면 어색했다. CloudWatch는 AWS 자기 자원의 관측 이름이지, Datadog/Zendesk를 받는 이름이 아니었기 때문이다. 둘째, Schema Registry, 2019년 12월 re:Invent 프리뷰, 2020년 4월 30일 GA. 이벤트 형태을 자동으로 발견하고 코드 바인딩을 생성하는 일은 관측 도구가 아니라 통합 플랫폼이 들고 있어야 했고, 그래서 별도 이름이 필요했다. 셋째, EventBridge Pipes(2022년 12월 1일 GA, re:Invent)와 EventBridge Scheduler(2022년 11월 GA). Pipes는 SQS·Kinesis·DynamoDB·MSK·MQ를 source로 받아 enrichment + filtering + transform 후 target으로 흘려 보내는 단방향 통합이고, Scheduler는 cron 스케줄을 EventBridge 위에서 한 번에 14M 인보케이션 무료 한도로 돌리는 대목이다. 두 도구 모두 bus·rule·target 형태에서 출발했지만 별도의 운영 단위라, 이걸 다 CloudWatch 이름 아래 묶기에는 너무 더 무거웠다.

이 세 부분은 EventBridge, 이벤트 버스 섹션에서 따로 잡고 깊게 다룬다. 출발점은 envelope 9필드 + Rule + Target 세 항목고, 그 위에 위에서 짚은 모든 확장이 얹혀 있다는 사실 한 줄로 충분하다.

언제 이걸 쓰지 말아야 하는가

EventBridge가 잘 안 어울리는 위치가 세 군데 있다.

첫 항목, 동기 응답이 필요한 군데. PutEvents는 fire-and-forget이고, target 호출은 비동기다. 요청 → 처리 → 응답이 한 호출 안에 끝나야 하는 API라면 EventBridge 사이에 두는 순간 응답을 받을 길이 없다. 그 경우는 API Gateway + Lambda 직접 호출이 맞다.

둘째, 순서 보장이 필요한 군데. EventBridge는 이벤트 순서를 보장하지 않는다. 같은 source·detail-type 두 이벤트를 1초 간격으로 보내도 target에 도착하는 순서는 뒤바뀔 수 있다. 순서가 비즈니스 의미를 갖는 경우(예: 주문 → 결제 → 배송 상태 천이)는 SQS FIFO나 Kinesis stream의 partition key가 더 잘 맞는다.

셋째, 동일 도메인의 페이로드 폭주. 같은 source의 이벤트가 초당 수만 건 이동하는 워크로드는 EventBridge가 받기는 받지만, target 한 묶음으로 fan-out되는 비용이 빠르게 자란다. 이 형태은 Kinesis stream이 본 일이고, EventBridge Pipes로 Kinesis → 처리 → 다른 stream으로 잇는 경우는 자연스럽지만, 모든 이벤트를 EventBridge bus에 직접 PutEvents로 던지는 건 잘못된 대목이다.

다음 편 예고

뒤에 나오는 글은 Synthetics, 엔드포인트 가용성 모니터링이다. 외부에서 본 우리 엔드포인트가 살아 있는지를 합성 트래픽으로 측정하는 대목이고, EventBridge와는 다른 종류의 관측 도구다. envelope 9필드 형태은 EventBridge, 이벤트 버스 섹션에서 따로 잡을 때 다시 본다, Pipes·Scheduler·Schema Registry까지 깊게 들어가는 대목이다.

한 줄 caveat 하나. EventBridge는 모든 통합의 답이 아니다. 위에서 짚은 세 항목(동기·순서·페이로드 폭주)는 다른 도구가 더 잘 맞는다. EventBridge가 가장 잘 들어맞는 부분은 느슨하게 연결된 여러 도메인을 한 이벤트로 잇는 대목이고, 그 한 군데만 또렷하게 잡으면 청구서도, 운영 복잡도도, 디버깅 난이도도 다 받쳐 준다.

참고 자료

YouTube 영상

채널 보기
트라이(Trie) 자료구조: 파이썬으로 삽입(Insert) 연산 구현하기 | Trie 자료구조 이야기
행렬의 기본 연산 - 행렬 덧셈, 스칼라 곱, 전치 | 선형대수학
AI는 데이터를 어떻게 분류할까? 벡터의 거리와 KNN 알고리즘 | 선형대수학
마지막편, 트라이 노드를 50% 이상 줄이는 방법? 압축 트라이 성능 분석 | Trie 자료구조 이야기
우리가 매일 쓰는 맞춤법 검사기와 라우터 속에 숨겨진 알고리즘은? | Trie 자료구조 이야기
트라이(Trie)를 이용한 자동 완성 알고리즘 | Trie 자료구조 이야기
AI는 왜 수백 차원의 벡터를 사용할까? 고차원 공간과 행렬 | 선형대수학
행렬의 가장 중요한 연산 - 행렬 곱셈 | 선형대수학