AWS 고급 #5 EventBridge / SQS / SNS

8 분 소요

#3 Lambda, #4 API Gateway가 동기 호출의 영역이었다면, 이번엔 비동기 / 이벤트 주도 방식입니다. 호출자가 결과를 기다리지 않고, 컴포넌트 사이가 메시지로 느슨하게 연결되는 패턴입니다.

AWS에는 이 영역의 도구가 셋, SNS / SQS / EventBridge. 비슷해 보이지만 강조점이 다릅니다. 이 글에서 그 차이를 정확히 나누고, fan-out 패턴, DLQ, 멱등성 같은 운영 포인트까지 한 번에 정리합니다.

셋의 차이: 한 줄 비교 #

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,000 msg/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

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

작업 큐 #

SQS

AWS 서비스 이벤트에 반응 #

EventBridge (S3, EC2 등 자동 publish)

스케줄링 #

EventBridge Scheduler (또는 EventBridge Rule)

컴포넌트 간 단순 메시지 (1:1) #

SQS

Email / SMS / Mobile Push #

SNS

외부 SaaS 통합 #

EventBridge (매니지드 통합) 또는 EventBridge Pipes

비용: 짧게 #

가격
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

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

정리 #

이번 글에서 잡은 것:

  • 셋의 차이. SNS (pub/sub), SQS (queue), EventBridge (라우팅 룰)
  • SNS. Topic에 publish, 여러 구독자에 즉시 push. Email / SMS / Mobile Push 통합
  • SQS. Queue + polling. Visibility Timeout이 가장 중요한 설정
  • DLQ. 모든 큐에 필수. maxReceiveCount 회 실패 후 이송
  • Standard vs FIFO. Standard는 at-least-once / 무한 처리량. FIFO는 순서 + 중복 제거 + 처리량 제한
  • EventBridge. AWS 서비스 이벤트 + custom 이벤트. 룰 패턴으로 라우팅. Scheduler로 cron
  • Fan-out 패턴. SNS → 여러 SQS → 각 Lambda. 백프레셔 / retry / DLQ가 받는 쪽마다 독립
  • 멱등성. at-least-once 환경에선 필수. 자연 멱등 / DB 마커 / FIFO dedup
  • 선택 가이드. 한 이벤트 N 받기 (SNS / EventBridge), 작업 큐 (SQS), AWS 이벤트 반응 (EventBridge), 스케줄 (EventBridge Scheduler), Email (SES, SNS 아님)
  • 비용. 모두 매우 저렴. 작은 워크로드는 무시
  • 함정. 중복 처리, Visibility Timeout 미스, DLQ 누락, polling 비용 (long polling), 룰 폭주, SNS Email의 용도, 결과 알림 패턴

다음: 비밀 / 설정 #

다음 주제는 운영의 진지한 한 축, 비밀번호와 설정 값을 어디에 보관하느냐입니다.

#6 Secrets Manager / Parameter Store에서는 둘의 차이, 자동 회전, 코드에서 가져오기, IaC와의 연결, 비용 비교까지, AWS의 시크릿 관리 두 도구를 한 번에 정리하겠습니다.

X