목차
19 장

EventBridge / SQS / SNS

AWS의 메시지 인프라를 정리합니다. 세 도구의 차이, SNS topic / SQS queue / EventBridge bus·rule, fan-out 패턴, FIFO vs Standard, DLQ와 멱등성(idempotency), Visibility Timeout, 그리고 Lambda / ECS와 어떻게 묶이는지까지 다룹니다.

17장 Lambda 기초18장 API Gateway + Lambda가 동기 호출의 영역이었다면, 본 챕터는 비동기 / 이벤트 주도 방식입니다. 호출자가 결과를 기다리지 않고, 컴포넌트 사이가 메시지로 느슨하게 연결되는 패턴입니다.

AWS에 이 영역의 도구가 셋 있습니다 — SNS / SQS / EventBridge입니다. 비슷해 보이지만 강조점이 다릅니다. 본 챕터에서 그 차이를 정확히 나누고, fan-out 패턴, DLQ, 멱등성 같은 운영 포인트까지 한 번에 정리합니다. 여기서 잡는 큐와 fan-out은 다음 20장 Secrets Manager / Parameter Store의 설정 관리, 21장 Step Functions 입문의 워크플로우와 맞물립니다.

셋의 차이 #

SNSSQSEventBridge
모델Pub/Sub (push)Queue (pull)Event Bus (push, 라우팅 룰)
받는 쪽0 ~ N 구독자 동시1명만 (한 메시지에)0 ~ N (rule 매칭에 따라)
보존즉시 push, 안 받으면 사라짐최대 14일 큐에 보관rule 매칭 즉시 push
적합한 경우한 이벤트 → 여러 받는 쪽작업 큐, 백프레셔이벤트 기반 라우팅 (다중 소스)
통합Lambda, SQS, HTTP, Email, SMSLambda, ECS, EC2 (폴링)Lambda, SQS, SNS, ECS, Step Functions, … 25+

가장 자주 보는 패턴을 한 줄로 봅니다.

3가지 구성의 흐름
                    ┌──────────────┐
                    │              │
   생산자 ─→ SNS ─→ ├─→ SQS  ─→ Lambda
                    └─→ Lambda    Worker (긴 처리)
   (한 이벤트)        (즉시 push)

   생산자 ─→ EventBridge ──┬─→ Lambda (룰 A 매칭)
   (다양한 소스)            ├─→ Step Functions (룰 B)
                            └─→ SQS (룰 C)

SNS — Pub/Sub #

Topic에 publish 하면 모든 구독자에 즉시 전달됩니다.

모델 #

SNS Topic
publish → Topic ──┬─→ 구독자 1 (Lambda)
                  ├─→ 구독자 2 (SQS)
                  ├─→ 구독자 3 (Email)
                  ├─→ 구독자 4 (HTTP endpoint)
                  └─→ 구독자 5 (SMS)

한 이벤트가 발생했을 때 여러 컴포넌트가 동시에 알아야 하는 경우입니다.

만들기 + Publish #

SNS
TOPIC_ARN=$(aws sns create-topic --name user-events \
  --query TopicArn --output text)

# Lambda 구독
aws sns subscribe \
  --topic-arn $TOPIC_ARN \
  --protocol lambda \
  --notification-endpoint arn:aws:lambda:ap-northeast-2:123456789012:function:on-user-event

# Email 구독 (확인 메일 후 활성화)
aws sns subscribe \
  --topic-arn $TOPIC_ARN \
  --protocol email \
  --notification-endpoint admin@example.com

# Publish
aws sns publish \
  --topic-arn $TOPIC_ARN \
  --message '{"userId":42,"action":"signup"}'

Standard vs FIFO #

  • Standard: 거의 무한 처리량, 순서 보장 없음, 중복 가능
  • FIFO: 그룹 내 순서 보장, 정확히 한 번 전달. 처리량 제한 (3,000msg/s with batching)

이름에 .fifo 접미사가 필수이고, MessageGroupId가 필수입니다.

메시지 필터링 #

같은 Topic에 publish 되어도 구독자가 일부만 받게 할 수 있습니다.

필터 정책
aws sns set-subscription-attributes \
  --subscription-arn $SUB_ARN \
  --attribute-name FilterPolicy \
  --attribute-value '{"event": ["signup", "purchase"]}'

publish 시 MessageAttributesevent가 일치할 때만 전달됩니다.

적합한 경우 #

  • 한 이벤트 → 여러 처리 (이메일, 알림, 분석, 감사 로그)
  • Email / SMS / Mobile Push 알림
  • SQS fan-out의 입구

SQS — Queue #

Queue에 메시지를 넣으면 한 명의 소비자가 polling으로 가져가 처리합니다.

모델 #

SQS Queue
생산자 ─→ Queue ─→ 소비자 (Lambda / ECS Task)
                    pull (polling)

소비자가 받아 가는 모델이라 백프레셔가 자연스럽게 잡힙니다. 소비자가 느리면 Queue에 메시지가 쌓이고, 그동안 생산자는 영향을 받지 않습니다.

만들기 + Send / Receive #

SQS
QUEUE_URL=$(aws sqs create-queue --queue-name jobs \
  --query QueueUrl --output text)

# Send
aws sqs send-message \
  --queue-url $QUEUE_URL \
  --message-body '{"job":"resize","key":"photo.jpg"}'

# Receive
aws sqs receive-message \
  --queue-url $QUEUE_URL \
  --max-number-of-messages 10 \
  --wait-time-seconds 20  # long polling

# Delete (처리 완료 후)
aws sqs delete-message \
  --queue-url $QUEUE_URL \
  --receipt-handle <handle>

Lambda와 자동 연결 #

Lambda에 SQS를 트리거로 붙이면 폴링 / 삭제는 Lambda 인프라가 자동으로 합니다.

SQS → Lambda
aws lambda create-event-source-mapping \
  --function-name process-jobs \
  --event-source-arn arn:aws:sqs:ap-northeast-2:123456789012:jobs \
  --batch-size 10 \
  --maximum-batching-window-in-seconds 5
Lambda 핸들러
def handler(event, context):
    for record in event["Records"]:
        body = json.loads(record["body"])
        process_job(body)
    # 정상 종료 → Lambda가 자동으로 메시지 삭제
    # 예외 → 메시지 큐에 남아 visibility timeout 후 재시도

Visibility Timeout — 가장 중요한 설정 #

소비자가 메시지를 받으면 N 초 동안 다른 소비자에 안 보이게 됩니다. 이 시간 안에 처리와 삭제가 끝나야 합니다. 안 그러면 다시 큐에 떠 다른 소비자가 받습니다 → 중복 처리 위험입니다.

설정권장
평균 처리 시간 1초Visibility Timeout 30초 (여유)
평균 처리 시간 30초60~90초
매우 길어질 수 있는 처리change-message-visibility로 처리 중 연장

Standard vs FIFO #

SNS와 같습니다.

  • Standard: 거의 무한 처리량, 순서 보장 없음, at-least-once (드물게 중복)
  • FIFO: 그룹 내 순서, 정확히 한 번 (MessageDeduplicationId)

Dead Letter Queue (DLQ) #

처리 실패한 메시지를 별도 큐로 이송합니다. 운영 필수입니다.

DLQ 셋업
# DLQ 만들기
DLQ_URL=$(aws sqs create-queue --queue-name jobs-dlq \
  --query QueueUrl --output text)
DLQ_ARN=$(aws sqs get-queue-attributes \
  --queue-url $DLQ_URL --attribute-names QueueArn \
  --query 'Attributes.QueueArn' --output text)

# Main queue에 redrive policy
aws sqs set-queue-attributes \
  --queue-url $QUEUE_URL \
  --attributes '{
    "RedrivePolicy": "{\"deadLetterTargetArn\":\"'"$DLQ_ARN"'\",\"maxReceiveCount\":\"3\"}"
  }'

3회 retry 후 실패하면 DLQ로 이송합니다. DLQ의 메시지는 사람이 분석 / 수정해서 다시 큐로 보냅니다.

적합한 경우 #

  • 작업 큐 (이미지 처리, 메일 발송, 외부 API 호출)
  • 트래픽 스파이크 흡수
  • 컴포넌트 분리 (생산자가 소비자 속도 영향 안 받음)

EventBridge — Event Bus #

EventBridge는 여러 소스에서 들어오는 이벤트를 여러 타겟에 룰 기반으로 라우팅합니다.

모델 #

EventBridge
이벤트 소스 (S3, EC2 상태 변경, 외부 SaaS, 내 코드 ...)
Event Bus (default 또는 사용자 정의)
    ├─ Rule A (패턴: source=aws.s3, eventName=ObjectCreated:Put)
    │     → Lambda
    ├─ Rule B (패턴: source=myapp, detail-type=user.signup)
    │     → SQS + Step Functions (둘 다 타겟)
    └─ Rule C (cron: 매일 03:00)
          → Lambda (배치 작업)

두 종류의 이벤트 #

1) AWS 서비스 이벤트 — AWS가 자동 publish 합니다.

  • EC2 상태 변경 (running → stopped)
  • S3 ObjectCreated
  • CodePipeline 단계 완료

2) Custom 이벤트 — 내 코드가 publish 합니다.

Custom 이벤트 publish
aws events put-events --entries '[{
  "Source": "myapp.users",
  "DetailType": "user.signup",
  "Detail": "{\"userId\":42,\"plan\":\"pro\"}",
  "EventBusName": "default"
}]'

Rule 만들기 #

Rule (이벤트 패턴 기반)
aws events put-rule \
  --name on-user-signup \
  --event-pattern '{
    "source": ["myapp.users"],
    "detail-type": ["user.signup"],
    "detail": {"plan": ["pro"]}
  }'

# 타겟 추가
aws events put-targets \
  --rule on-user-signup \
  --targets 'Id=1,Arn=arn:aws:lambda:ap-northeast-2:123456789012:function:welcome-pro'
Rule (cron / rate 기반 — 스케줄러)
aws events put-rule \
  --name nightly-cleanup \
  --schedule-expression 'cron(0 18 * * ? *)'   # UTC 18:00 = KST 03:00

aws events put-targets \
  --rule nightly-cleanup \
  --targets 'Id=1,Arn=arn:aws:lambda:ap-northeast-2:123456789012:function:cleanup'

스케줄링은 더 깔끔한 도구로 EventBridge Scheduler가 따로 있습니다 (200,000개까지 / cron 또는 rate / 일회성 또는 반복). 새 프로젝트에서는 Scheduler를 우선합니다.

Schema Registry / Pipes #

대규모 이벤트 생태계에서 씁니다.

  • Schema Registry: 이벤트의 스키마를 등록 / 자동 발견합니다. 코드 생성기로 타입 안전한 클라이언트를 만듭니다.
  • EventBridge Pipes: SQS / Kinesis / DynamoDB Streams → (선택적 enrichment / filter) → 타겟으로 잇습니다.

적합한 경우 #

  • AWS 서비스 이벤트에 반응 (S3 업로드 → 처리)
  • 도메인 이벤트 라우팅 (user.signup → 5 가지 처리)
  • 스케줄링 (cron) — Lambda + EventBridge Scheduler가 표준
  • SaaS 통합 (Datadog, PagerDuty, Stripe 등 매니지드 통합)

Fan-out 패턴 #

가장 흔한 운영 패턴 중 하나입니다. 한 이벤트 → 여러 비동기 처리입니다.

SNS + SQS Fan-out
생산자 ─→ SNS Topic ──┬─→ SQS Queue A ─→ Lambda A
                      ├─→ SQS Queue B ─→ Lambda B
                      └─→ SQS Queue C ─→ Lambda C

왜 SNS + SQS 인가? Lambda를 SNS에 직접 붙여도 되지만 SQS를 한 단계 끼우면 다음 이점이 있습니다.

  • 각 처리의 백프레셔가 독립적입니다 (B가 느려도 A는 영향 없음).
  • 각 처리의 retry / DLQ가 독립적입니다.
  • Lambda가 잠시 죽어도 메시지가 SQS에 14일까지 보관됩니다.

EventBridge도 같은 패턴입니다 — 한 이벤트가 여러 룰에 매칭되면 여러 타겟에 동시 전달됩니다.

멱등성 (Idempotency)의 중요성 #

비동기 시스템의 핵심입니다. 같은 메시지를 두 번 받아도 결과가 같아야 합니다.

왜 두 번 받는가는 다음과 같습니다.

  • SQS Standard는 at-least-once 라 가끔 중복됩니다.
  • Visibility Timeout 안에 처리를 못 끝내면 재전달됩니다.
  • Lambda 자동 retry (비동기 호출)가 있습니다.
  • 네트워크 / 클라이언트 재시도가 있습니다.

패턴 1: 자연 멱등 연산 #

# 멱등 (몇 번을 해도 결과 같음)
user.set_status("active")
s3.put_object(Bucket=b, Key=k, Body=data)

# 비멱등
user.add_credit(100)
queue.send(...)

가능하면 자연 멱등으로 설계합니다.

패턴 2: ID + DB 마커 #

처리 ID 중복 방지
def handler(event, context):
    msg = json.loads(event["body"])
    msg_id = msg["id"]

    # 이미 처리한 ID 인가?
    if redis.get(f"processed:{msg_id}"):
        return  # skip

    process(msg)
    redis.setex(f"processed:{msg_id}", 86400, "1")  # 1 일 보관

Lambda Powertools의 Idempotency가 이 패턴을 DynamoDB 백엔드로 깔끔하게 처리합니다.

패턴 3: FIFO Queue의 deduplication #

MessageDeduplicationId 또는 컨텐츠 기반 deduplication입니다 — 5분 안에 같은 ID 면 자동 거부합니다.

어느 도구를 언제 #

경우도구
한 이벤트, 여러 받는 쪽SNS Fan-out (+ SQS 끼우기) 또는 EventBridge
작업 큐SQS
AWS 서비스 이벤트에 반응EventBridge (S3, EC2 등 자동 publish)
스케줄링EventBridge Scheduler (또는 EventBridge Rule)
컴포넌트 간 단순 메시지 (1:1)SQS
Email / SMS / Mobile PushSNS
외부 SaaS 통합EventBridge (매니지드 통합) 또는 EventBridge Pipes

EventBridge가 풍부한 룰 / 필터 / AWS 서비스 통합을 제공합니다. 단순 fan-out 만이면 SNS + SQS입니다.

비용 #

가격
SQS100만 request 당 $0.40 (Standard), $0.50 (FIFO)
SNSpublish 100만 당 $0.50 (Email / SMS / Mobile은 별도)
EventBridgepublish 100만 당 $1.00 (custom 이벤트), AWS 자체 이벤트 무료

월 1,000만 메시지의 SQS는 $4입니다. 작은 워크로드는 사실상 무시할 수준입니다.

자주 만나는 함정 #

1) 메시지 중복 처리 #

자연 멱등이 아닌 연산 (결제 / 크레딧 추가 등)을 SQS Standard에서 하면, 한 번 결제가 두 번 결제가 됩니다. 항상 멱등 패턴 또는 FIFO를 씁니다.

2) Visibility Timeout 미스 #

처리에 60초 걸리는데 Visibility Timeout이 30 초면 처리 중인 메시지가 다시 큐에 떠 다른 소비자가 받습니다 → 두 번 처리됩니다. Visibility Timeout을 처리 시간 + 여유로 둡니다.

3) DLQ 없음 #

실패한 메시지가 영원히 큐에 떠다니면 CloudWatch 알람만 시끄러워집니다. 모든 큐에 DLQ + 알람을 둡니다. DLQ 자체에도 알람을 둡니다 (DLQ에 메시지 들어옴 = 사람이 봐야 함).

4) Lambda의 SQS 폴링이 비싸 보임 #

Lambda가 비어 있는 큐를 빈도 높게 폴링하면 SQS request 비용이 듭니다. long polling (WaitTimeSeconds=20)이 기본인지 확인합니다.

5) EventBridge rule이 너무 많아짐 #

도메인 이벤트마다 룰이 늘어나면 콘솔이 카오스가 됩니다. 도메인별로 사용자 정의 Event Bus (default가 아닌)를 분리하고 IaC로 관리합니다.

6) SNS Email / SMS의 용도 #

SNS의 Email은 형식이 단조롭고 (텍스트만, From 변경 어려움) Spam으로 분류되기 쉽습니다. 트랜잭셔널 메일 (회원가입 등)은 Amazon SES가 정답입니다. SNS Email은 운영자 알림 정도에만 씁니다.

7) 비동기 처리 결과를 클라이언트에 알리는 방법 #

API → SQS → Lambda 처리 후 결과를 클라이언트에 어떻게 알리는가? 두 패턴이 있습니다.

  • 클라이언트가 polling (작업 ID로 GET 요청)
  • WebSocket (API Gateway WebSocket API)으로 push

비동기 시스템 설계 시 처음에 정해야 할 기준입니다.

연습문제 #

  1. 본인 시스템에 “한 사용자가 가입하면 환영 메일·분석 기록·관리자 알림을 동시에 보낸다"는 요구가 있다고 할 때, §“어느 도구를 언제"를 근거로 SNS·SQS·EventBridge 중 어떤 조합을 쓸지 한 단락으로 설계해 보세요(18장 API Gateway + Lambda의 동기 호출과 어디서 갈리는지도 함께 적습니다).
  2. 결제 처리를 SQS Standard + Lambda로 한다고 할 때, §“멱등성"의 세 패턴 중 어느 것을 적용할지 고르고, Visibility Timeout을 어떻게 잡아야 §“자주 만나는 함정"의 중복 처리를 막을 수 있는지 17장 Lambda 기초의 동시성과 묶어 설명해 보세요.
  3. 모든 작업 큐에 DLQ가 필요한 이유를 §“Dead Letter Queue"와 §“자주 만나는 함정"을 근거로 한 줄로 적고, DLQ에 메시지가 쌓였을 때 운영자가 무엇을 해야 하는지 적어 두세요.

한 줄 요약: 비동기 메시지 도구는 SNS(pub/sub push), SQS(queue pull), EventBridge(라우팅 룰)로 나뉜다. SQS는 백프레셔를 잡아 주고 Visibility Timeout이 가장 중요한 설정이며 모든 큐에 DLQ가 필수다. 한 이벤트를 여러 곳에 보내려면 SNS → 여러 SQS → 각 Lambda의 fan-out을 쓰고, AWS 서비스 이벤트 반응과 스케줄링은 EventBridge와 Scheduler가 맡는다. at-least-once 환경이라 자연 멱등·DB 마커·FIFO dedup으로 멱등성을 보장해야 하고, 트랜잭셔널 메일은 SNS가 아니라 SES가 정답이다.

다음 챕터 #

다음 20장 Secrets Manager / Parameter Store에서는 운영의 진지한 한 축인 비밀번호와 설정 값을 어디에 보관하는가를 다룹니다. 두 도구의 차이, 자동 회전, 코드에서 가져오기, ECS / Lambda 통합, IaC 연결, 비용 비교까지 AWS의 시크릿 관리 두 도구를 정리합니다.

X