Amazon SAA-C03: 애플리케이션 통합, 메시징 및 스트리밍 — 학습 가이드
다음의 일부입니다: AWS SAA-C03 — 완벽 학습 가이드. 검증된 답안으로 연습하기: Amazon 시험 허브, 또는 다음에서 시간 제한 모의고사 풀기: ExamRoll.io.
Amazon SQS: 디커플링, 순서 지정 및 전송 시맨틱
Amazon SQS는 완전 관리형 풀(pull) 기반 메시지 큐로, 주요 아키텍처 역할은 생산자(producer)와 소비자(consumer)를 분리(디커플링)하는 것입니다. 동기식 호출 체인은 생산자의 지연 시간과 가용성을 모든 다운스트림 종속성에 묶지만, SQS 큐를 삽입하면 이를 비동기식 핸드오프로 전환할 수 있습니다. 생산자는 트래픽이 도착하는 속도에 맞춰 메시지를 큐에 넣고, 소비자는 안전하게 처리할 수 있는 속도로 메시지를 큐에서 꺼냅니다. 이는 RDS 인스턴스를 압도할 수 있는 쓰기 버스트(write burst)에 대한 표준적인 해결책입니다. 즉, 큐가 버스트를 흡수하고, 제한된 수의 소비자 플릿이 제어된 동시성으로 큐를 처리하여 데이터베이스 연결 수를 통제합니다.
큐 유형은 두 가지가 있으며, 어떤 것을 선택하느냐에 따라 처리량과 전송 보증 수준이 결정됩니다.
| 기능 | 표준(Standard) | FIFO |
|---|---|---|
| 순서 지정 | 최선 노력(Best-effort) | MessageGroupId별 엄격한 순서 |
| 전송 | 최소 한 번(중복 가능) | 5분 중복 제거 기간 내 정확히 한 번 |
| 처리량 | 거의 무제한 | 300 TPS (배치 처리 시 3,000); 높은 처리량 모드 사용 시 70,000 |
| 큐 이름 | 모두 가능 | 반드시 .fifo로 끝나야 함 |
표준(Standard) 큐는 최선 노력(best-effort) 순서 지정과 함께 최소 한 번 전송을 보장합니다. 소비자가 가시성 제한 시간(visibility timeout)이 만료되기 전에 메시지를 삭제하지 못하거나, 분산된 백엔드가 샤드 간에 메시지를 재전송할 때 중복이 발생할 수 있습니다. 테스트 중에 중복을 발견하지 못하더라도, 이 서비스는 아키텍처상 특히 브로커 장애 조치 중에 메시지를 재전송할 수 있습니다. 표준 큐가 “보통은” 한 번만 전송할 것이라고 가정하는 것은 운영상의 위험이 아니라 설계 결함입니다. 대규모 환경에서는 결국 중복이 발생하게 되어 있습니다. 따라서 소비자 로직은 반드시 **멱등성(idempotent)**을 가져야 합니다. 즉, DynamoDB에서 조건부 쓰기(conditional write)를 사용하여 MessageId나 비즈니스 키를 추적하거나, 다운스트림 API 호출에 멱등성 키를 사용하거나, 업서트(upsert) 시맨틱에 의존해야 합니다.
FIFO 큐는 MessageGroupId 내에서 엄격한 순서 지정을 제공하며, MessageDeduplicationId(명시적으로 지정하거나 메시지 본문의 SHA-256 해시값 사용)를 통해 5분 동안 중복을 억제하여 정확히 한 번 처리를 보장합니다. MessageGroupId는 핵심 개념입니다. 동일한 그룹 ID를 공유하는 모든 메시지는 한 번에 하나의 소비자에게 엄격한 순서로 전달되며, 다른 그룹 ID는 병렬로 처리될 수 있습니다. 각 고객의 이벤트는 순차적으로 처리되어야 하지만 다른 고객 간에는 독립적인 주문 처리 시스템의 경우, MessageGroupId = customerId를 사용합니다. 모든 메시지에 단일 그룹 ID를 사용하면 전체 워크로드가 직렬화되어 처리량이 저하됩니다. 중복 제거 ID는 사용자가 중단된 결제를 다시 제출할 때 중복 주문 생성을 방지하는 데 적합한 기본 요소입니다. 클라이언트는 결정론적 멱등성 토큰(결제 세션에 연결된 UUID)을 생성하고, SQS는 해당 기간 내에 도착하는 모든 중복 제출을 폐기합니다.
PaymentsQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: payments.fifo
FifoQueue: true
ContentBasedDeduplication: true
DeduplicationScope: messageGroup
FifoThroughputLimit: perMessageGroupId
VisibilityTimeout: 60
RedrivePolicy:
deadLetterTargetArn: !GetAtt PaymentsDLQ.Arn
maxReceiveCount: 5
요구사항에 “순서 보장"이나 “중복 없음"이 명시되어 있는데도 표준 큐를 선택하는 것은 전형적인 오류입니다. 큐가 순서를 보존하지 않았기 때문에 애플리케이션 로직으로는 그 순서를 복원할 수 없습니다. 서로 다른 백엔드 호스트에서 온 메시지들이 뒤섞여 도착하기 때문입니다. 워크로드가 순서 지정(트랜잭션 원장, 상태 머신 전환)이나 정확히 한 번 시맨틱(결제 처리, 재고 감소)을 요구할 때는 항상 FIFO를 선택해야 합니다.
가시성 제한 시간, 포이즌 메시지 및 페이로드 한도
소비자가 메시지를 수신하면 SQS는 가시성 제한 시간(기본값 30초, 최대 12시간) 동안 다른 소비자가 해당 메시지를 볼 수 없게 만듭니다. 소비자가 제한 시간 만료 전에 메시지를 삭제하면 메시지는 사라집니다. 하지만 소비자가 충돌하거나 처리가 너무 오래 걸려 삭제하지 못하면 메시지는 다시 나타나 다른 소비자에게 전달됩니다. 가시성 제한 시간을 실제 처리 시간보다 짧게 설정하는 것은 중복 처리의 주요 원인입니다. 기본 30초 제한 시간의 큐에 대해 45초가 걸리는 Lambda는 모든 메시지를 최소 두 번 다시 처리하게 됩니다. 제한 시간은 최소 p99 처리 시간으로 설정하고(Lambda 기반 큐에 대한 AWS 가이드는 함수 제한 시간의 최소 6배), 처리 시간이 예측 불가능한 작업의 경우 제한 시간을 동적으로 연장해야 합니다.
sqs.change_message_visibility(
QueueUrl=queue_url,
ReceiptHandle=handle,
VisibilityTimeout=300 # extend by 5 minutes
)
**Dead-letter queue(DLQ)**는 포이즌 필(poison-pill) 메시지를 수집합니다. 원본 큐의 RedrivePolicy에 maxReceiveCount(일반적으로 3~5)를 지정하면, 이 횟수를 초과한 메시지는 SQS에 의해 오프라인 검사를 위해 DLQ로 이동됩니다. DLQ는 원본 큐 유형과 일치해야 합니다(FIFO ↔ FIFO). DLQ가 없으면 잘못된 형식의 메시지가 무한정 반복되며, 특히 FIFO 큐에서는 치명적입니다. 순서 지정 원칙에 따라 문제가 되는 메시지가 처리될 때까지 동일한 그룹의 후속 메시지 전달이 막히므로, 잘못된 메시지 하나가 전체 그룹을 중단시킵니다.
SQS 메시지는 256KB로 제한됩니다. 렌더링된 문서와 같은 더 큰 페이로드를 처리하려면 SQS Extended Client Library를 사용해야 합니다. 이 라이브러리는 페이로드를 S3에 쓰고 버킷/키 참조만 큐에 넣습니다. 소비자 측 라이브러리는 메시지를 수신할 때 투명하게 S3에서 페이로드를 가져옵니다. 페이로드를 여러 메시지로 분할하지 마십시오(원자성과 순서 보장을 잃게 됩니다). 또한 2MB 크기의 블롭을 base64로 인코딩하여 용량에 맞추려고 시도하지 마십시오.
큐 기반 오토스케일링
SQS 큐 뒤에 있는 EC2 또는 ECS의 소비자 플릿에 대한 올바른 스케일링 신호는 CPU가 아니라 큐 백로그입니다. CPU는 도착률보다 뒤처지며, 포화 상태의 소비자를 “바쁘지만 감당하고 있는” 상태로 잘못 판단합니다. 표준적인 스케일링 지표는 ApproximateNumberOfMessagesVisible이지만, 원시 큐 깊이에 직접 기반하여 스케일링하는 것은 조잡합니다. 권장되는 접근 방식은 인스턴스당 백로그 사용자 지정 지표입니다.
backlogPerInstance = ApproximateNumberOfMessagesVisible / RunningInstances
이 지표를 CloudWatch에 게시하고 Auto Scaling 그룹이나 ECS 서비스의 대상 추적 정책(target-tracking policy)을 구동하여 각 워커가 제한된 백로그(예: 10개 메시지)를 유지하도록 합니다. 이렇게 하면 버스트 발생 시 부드럽게 스케일 아웃(확장)되고, 큐 깊이가 작지만 소비자가 이미 포화 상태일 때 발생하는 진동(oscillation)을 방지할 수 있습니다. 스케일 인(축소) 시에는 ApproximateAgeOfOldestMessage 지표와 함께 사용하여 오래된 메시지가 남아 있는 동안 용량이 종료되는 것을 방지합니다.
Amazon SNS: 팬아웃, 필터링, 교차 계정 전송
SNS는 푸시 기반의 게시/구독 서비스입니다. 게시자(Publisher)는 주제(topic)에 메시지를 쓰고, SNS는 SQS 대기열, Lambda 함수, HTTP(S) 엔드포인트, 이메일, SMS, Kinesis Data Firehose, 모바일 푸시 등 모든 구독(subscription)으로 푸시합니다. 가장 일반적인 내구성 패턴은 SNS → SQS 팬아웃입니다. 하나의 주제에 여러 SQS 대기열이 구독되어 있어, 각 다운스트림 서비스는 자체적인 영구 버퍼, 재시도 정책, DLQ를 가질 수 있습니다. 반면 게시자는 주제에 대해서만 알면 됩니다. 만약 소비자 서비스가 몇 시간 동안 다운되면, 해당 서비스의 대기열은 메시지를 축적했다가 복구 시 처리합니다. SNS 단독으로는 이러한 버퍼링 기능이 부족하여 재시도 정책을 모두 소진하게 됩니다.
Producer ──▶ SNS topic ──┬──▶ SQS Queue A ──▶ Service A
├──▶ SQS Queue B ──▶ Service B
└──▶ SQS Queue C ──▶ Service C
**메시지 필터링(Message filtering)**을 사용하면 각 구독이 JSON 필터 정책을 선언하여 SNS가 일치하는 메시지만 전송하도록 할 수 있습니다. 이를 통해 모든 소비자가 모든 메시지를 수신한 후 클라이언트 측에서 필터링하는 안티패턴을 방지할 수 있습니다.
{
"eventType": ["order_placed", "order_cancelled"],
"region": ["us-east-1", "us-west-2"]
}
두 가지 동작 특성이 중요합니다. 첫째, 표준(standard) SNS 주제는 메시지 순서를 보장하지 않습니다. 구독별 재시도 타이머와 독립적인 네트워크 경로로 인해 순서 변경이 일상적으로 발생합니다. 순서가 중요하다면 SQS FIFO 대기열을 구독하는 SNS FIFO 주제를 사용해야 합니다. 이 경우 메시지 그룹 ID가 엔드투엔드(end-to-end)로 전파됩니다. 그렇지 않다면 구독자는 멱등성(idempotent)을 가지며 메시지 순서 변경을 허용해야 합니다. 둘째, HTTP(S) 구독은 전송 정책(delivery policy)에 따라 재시도합니다(기본값: 즉시 3회 재시도 후, 최대 1시간까지 지수 백오프(exponential backoff), 그 후 폐기). 구독자는 15초 이내에 2xx 응답을 보내고, x-amz-sns-message-type 서명을 검증해야 합니다. 신뢰할 수 없는 엔드포인트의 경우, 전송되지 않은 메시지가 조용히 유실되지 않고 캡처되도록 항상 SNS DLQ(SQS로 리드라이브)를 설정해야 합니다.
교차 계정 호출은 자주 발생하는 함정입니다. 계정 A가 계정 B의 Lambda로 팬아웃되는 주제에 메시지를 게시할 때 두 가지 정책이 필요합니다. SNS 주제 정책(또는 구독 방향)이 구독을 허용해야 하고, Lambda **리소스 기반 정책(resource-based policy)**이 sns.amazonaws.com으로부터의 lambda:InvokeFunction을 허용하되 SourceArn 조건이 해당 주제와 일치해야 합니다. Lambda 리소스 정책 누락이 가장 흔한 실패 원인입니다. 이 경우 구독은 정상으로 보이지만 호출은 403으로 거부됩니다. 주제가 고객 관리형 KMS 키로 암호화된 경우, 키 정책은 게시하는 보안 주체(principal)와 sns.amazonaws.com에 kms:Decrypt 및 kms:GenerateDataKey 권한도 부여해야 합니다.
{
"Effect": "Allow",
"Principal": {"Service": "sns.amazonaws.com"},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:222222222222:function:ProcessOrder",
"Condition": {"ArnLike": {"AWS:SourceArn": "arn:aws:sns:us-east-1:111111111111:orders"}}
}
Amazon EventBridge: 라우팅된 이벤트 버스
EventBridge(이전 CloudWatch Events)는 콘텐츠 기반 라우팅, 스키마 검색, SaaS 파트너 이벤트 소스, 아카이브/재생 기능으로 게시/구독 모델을 확장합니다. 이벤트는 이벤트 버스(기본, 사용자 지정 또는 파트너)를 통해 흐르며, JSON 구조를 필터링하는 이벤트 패턴을 가진 **규칙(rule)**과 매칭됩니다. 규칙은 입력 경로(input path)와 입력 템플릿(input template)을 통해 페이로드를 변환하고, 데드-레터 대상을 연결하며, Lambda, Step Functions, ECS 작업, SQS, SNS, Kinesis, API 대상 등 20개 이상의 네이티브 대상으로 이벤트를 전송할 수 있습니다.
{
"source": ["com.acme.orders"],
"detail-type": ["OrderPlaced"],
"detail": {"amount": [{"numeric": [">", 500]}]}
}
SNS와의 차이점은 아키텍처에 있습니다. SNS는 간단한 속성 필터링을 사용하여 동일한 유형의 구독자들에게 낮은 지연 시간으로 높은 처리량의 브로드캐스트를 하는 데 최적화되어 있습니다. EventBridge는 이기종(heterogeneous) 이벤트 기반 아키텍처에 최적화되어 있습니다. 즉, 많은 생산자가 서로 다른 이벤트 스키마를 생성하고, 소비자는 주제가 아닌 패턴으로 구독합니다. 마이크로서비스로 분해되는 모놀리스(monolith)의 경우, 특히 생산자에 SaaS 파트너나 이벤트를 네이티브로 생성하는 AWS 서비스(Config, GuardDuty, CodePipeline, CloudTrail)가 포함될 때 EventBridge가 일반적으로 더 적합합니다. 매우 높은 볼륨과 낮은 지연 시간으로 동일한 구독자에게 팬아웃해야 하는 경우에는 EventBridge의 이벤트당 지연 시간이 약간 더 높고 기본 처리량 상한이 더 낮기 때문에 여전히 SNS가 유리합니다.
Amazon MQ: 기존 프로토콜을 위한 브로커 메시징
Amazon MQ는 ActiveMQ 또는 RabbitMQ를 실행하는 관리형 브로커입니다. 이 서비스는 AMQP 0-9-1, AMQP 1.0, MQTT, STOMP, OpenWire, 또는 JMS에 의존하는 온프레미스 워크로드를 애플리케이션을 재작성하지 않고 마이그레이션하기 위해 존재합니다. 만약 결제 시스템이 트랜잭션 기반의 정확히 한 번(exactly-once) 전송 시맨틱을 가진 서드파티 JMS 브로커를 사용한다면, 이를 Amazon MQ로 리프트(lift)하면 인프라 관리를 없애면서 와이어 프로토콜과 전송 보장을 그대로 유지할 수 있습니다. 새로운(greenfield) AWS 네이티브 설계에는 SQS/SNS/EventBridge를 선택하고, 프로토콜 호환성이 제약 조건일 때만 Amazon MQ를 선택해야 합니다.
Kinesis Data Streams
**Kinesis Data Streams (KDS)**는 클릭스트림, IoT 텔레메트리, 로그 집계와 같은 높은 처리량의 스트리밍 수집을 위한 내구성 있고, 순서가 보장되며, 파티셔닝된 로그입니다. 레코드는 PartitionKey에 따라 샤드(shard)에 배치됩니다. 순서는 스트림 전체가 아닌 샤드 내에서만 보장됩니다. 각 샤드는 초당 1MB 또는 1,000개 레코드의 쓰기와 초당 2MB의 읽기를 지원하며, 향상된 팬아웃(Enhanced Fan-Out)을 사용하면 더 높은 읽기 처리량을 얻을 수 있습니다. 레코드는 기본적으로 24시간 동안 보존되며 최대 365일까지 연장할 수 있습니다. 따라서 여러 독립적인 소비자가 동일한 기록을 재생(replay)할 수 있습니다. 이는 SQS가 확인(ack) 시 메시지를 삭제하기 때문에 불가능한 기능입니다.
온디맨드 모드는 스트림당 최대 200MiB/s의 쓰기 용량까지 자동으로 확장하여 샤드 계산을 할 필요가 없게 하므로 예측 불가능한 트래픽에 이상적입니다. 프로비저닝 모드는 용량이 알려진 안정적인 상태에서 더 저렴합니다.
워크로드가 FIFO가 처리할 수 없는 처리량(KDS는 초당 수백만 개의 레코드를 처리할 수 있음)으로 순서가 보장되고 재생 가능한 수집을 요구할 때, 여러 독립적인 소비자가 동일한 스트림을 읽어야 할 때, 또는 “처리 전반에 걸쳐 원래 순서 유지"라는 문구가 높은 볼륨과 결합될 때 SQS FIFO 대신 KDS를 선택해야 합니다.
Kinesis Data Firehose
Kinesis Data Firehose는 완전 관리형 전송 서비스입니다. Kinesis 스트림 또는 직접 PUT에서 데이터를 읽고, 크기(1–128MB) 또는 시간(60–900초, 먼저 도달하는 조건)에 따라 버퍼링합니다. 선택적으로 Lambda를 호출하여 레코드별 변환(PII 스크러빙, 형식 정규화)을 수행할 수 있으며, Glue 스키마를 사용하여 즉석에서 JSON을 Parquet 또는 ORC로 변환할 수 있습니다. KMS로 암호화하고 S3, Redshift, OpenSearch 또는 Splunk로 전송합니다. 샤드나 실행해야 할 소비자가 없으며, GB당 요금(pay-per-GB) 체계를 따릅니다.
데이터 레이크로의 확장 가능한 수집을 위한 표준 패턴은 내구성 있는 버퍼 역할을 하는 Data Streams(온디맨드)와 S3로 전송하는 Firehose를 결합하는 것입니다:
Producers → Kinesis Data Streams (on-demand) → Firehose (60s buffer, Parquet) → S3 → Athena/Glue
수백만 개의 모바일 이벤트를 수집하고, 암호화하여 S3에 Parquet 형식으로 저장해야 하는 경우, 정답은 Parquet 변환과 KMS 키를 사용하는 Firehose입니다. 이는 KDS에 커스텀 소비자와 직접 작성한 Parquet 라이터를 더한 방식보다 코드와 인프라가 훨씬 적게 필요합니다. Firehose는 거의 실시간(near-real-time)이며 소비자 측의 재실행(replay)을 지원하지 않습니다. 재실행이 필요한 경우에는 KDS를 경로에 유지해야 합니다.
Kinesis Data Analytics(현재 Managed Service for Apache Flink)는 스트림에 대해 SQL 또는 Flink 작업을 실행하여 윈도우 기반 집계(windowed aggregation)를 수행합니다.
Lambda 통합 및 재시도 의미 체계
Lambda는 다음과 같은 서비스들과 통합될 때 재시도 동작 방식에 있어 실질적인 차이가 있습니다:
| 소스 | 배치 처리 | 순서 | 실패 시 |
|---|---|---|---|
| SQS Standard | 최대 10,000개 메시지 | 없음 | 표시 제한 시간(visibility timeout) 초과 후 반환; maxReceiveCount 이후 DLQ로 이동 |
| SQS FIFO | 그룹별 | 그룹별 | 성공하거나 DLQ로 이동할 때까지 그룹이 차단됨 |
| Kinesis Streams | 최대 10,000개 레코드 | 샤드별 | 성공, 레코드 만료, 또는 MaximumRetryAttempts/OnFailure 대상으로 이동할 때까지 재시도가 샤드를 차단함 |
| Firehose | 해당 없음 (변환) | 해당 없음 | 실패한 레코드는 S3 오류 접두사(error prefix)에 저장됨 |
SQS의 경우, Lambda 함수 제한 시간을 대기열 표시 제한 시간(visibility timeout) 이하로 유지하고, 표시 제한 시간은 함수 제한 시간의 최소 6배로 설정하십시오. Kinesis의 경우, 단일 포이즌 레코드(poison record)가 전체 샤드를 무기한 중단시키지 않도록 BisectBatchOnFunctionError를 활성화하고 OnFailure 대상(SQS 또는 SNS)을 구성하십시오.
서비스 선택 결정 테이블
| 요구사항 | 올바른 선택 | 대안이 실패하는 이유 |
|---|---|---|
| 순서 보장, 정확히 한 번(exactly-once) 앱 메시징, 최소한의 운영 | SQS FIFO | Standard SQS는 순서 보장/중복 제거 기능이 없음; MQ는 브로커 관리 부담이 추가됨 |
| 기존 AMQP/JMS/MQTT 클라이언트 유지 | Amazon MQ | SQS/SNS는 독점적인 API를 사용함 |
| 하나의 이벤트를 여러 AWS 소비자에게 내구성 있게 팬아웃 | SNS → 다수의 SQS | 생산자-소비자 직접 연결은 모놀리스 구조로 회귀하게 됨; SNS만 사용하면 소비자가 다운되었을 때 메시지가 유실됨 |
| 필터/변환을 사용하여 이기종 이벤트 라우팅 | EventBridge | SNS 필터 정책에는 변환, 파트너 소스, 스키마 레지스트리 기능이 없음 |
| 동일한 구독자들에게 매우 높은 처리량으로 팬아웃 | SNS | EventBridge는 지연 시간이 더 길고 기본 처리량이 더 낮음 |
| 대용량의 순서가 보장된 스트림을 수집하고 재실행(replay) | Kinesis Data Streams | SQS는 보존 기간이 최대 14일이며 오프셋 기반 재실행을 지원하지 않음 |
| 코드 없이 스트림을 S3/Redshift/OpenSearch로 전송 | Firehose | Data Streams만 사용하면 소비자 애플리케이션이 필요함 |
| 스트리밍 JSON을 S3에서 Parquet으로 변환 | Glue 스키마를 사용하는 Firehose | 커스텀 KDS 소비자는 Parquet 라이터를 직접 작성하고 운영해야 함 |
이 문제 연습하기 → · ExamRoll.io에서 시간 제한 연습 →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
시험 합격하기 →