기본개념 · 12장
서버리스와 애플리케이션 통합
복원력 있는 아키텍처는 대개 서로를 직접 부르지 않는 아키텍처입니다. 구성 요소가 동기 호출로 붙어 있으면 느린 쪽이 빠른 쪽을 멈춰 세우고, 급증한 요청은 갈 곳이 없어 사라집니다. 이 장은 그 연결을 끊는 도구인 Amazon SQS · Amazon SNS · Amazon EventBridge와, 그 위에서 코드를 실행하는 AWS Lambda · Amazon API Gateway를 다룹니다.
학습 목표
- 동기 호출을 큐나 이벤트 버스로 끊는 것이 왜 안정성(Reliability, 신뢰성으로도 번역됨)을 올리는지 설명할 수 있습니다.
- AWS Lambda의 동기 호출과 비동기 호출, 이벤트 소스 매핑에서 재시도의 주체와 실패 메시지의 도착지가 어떻게 달라지는지 구분할 수 있습니다.
- 예약된 동시성과 프로비저닝된 동시성의 목적을 구분하고, 콜드 스타트와 스로틀링 중 어느 문제를 푸는지 판단할 수 있습니다.
- Amazon SQS 표준 큐와 FIFO 큐를 순서 · 중복 · 처리량 요구로 구분하고, 가시성 제한 시간과 배달 못 한 편지 큐로 장애를 격리할 수 있습니다.
- Amazon SNS · Amazon SQS · Amazon EventBridge 중 무엇을 고를지 전달 모델과 라우팅 요구로 판단할 수 있습니다.
- 트래픽 급증 시나리오에서 큐 완충이 스케일링 정책 조정보다 나은 이유를 설명할 수 있습니다.
느슨한 결합 — 왜 이것이 복원력을 만드는가 SAA 빈출
동기 호출은 장애를 전파합니다
웹 계층이 처리 계층을 직접 호출하는 구조를 생각해 봅니다. 처리 계층이 느려지면 웹 계층의 스레드가 응답을 기다리며 묶이고, 곧 웹 계층까지 응답하지 못합니다. 처리 계층이 아예 죽으면 그동안 들어온 요청은 어디에도 남지 않고 사라집니다. 장애가 한 방향으로만 번지는 것이 아니라, 두 계층의 가용성이 곱해져 전체 가용성이 됩니다.
사이에 큐를 두면 관계가 달라집니다. 웹 계층은 메시지를 넣고 즉시 응답하며, 처리 계층은 자기 속도로 꺼내 갑니다. 처리 계층이 멈춰도 메시지는 큐에 남아 있고, 복구되면 밀린 것부터 처리합니다. 두 계층이 서로의 가용 시간과 처리 속도를 알 필요가 없어지는 것이 느슨한 결합의 정의입니다.
웹 계층이 처리 API를 직접 호출하고 결과를 기다립니다. 처리 계층이 느려지면 웹 계층이 함께 느려지고, 타임아웃된 요청은 유실됩니다. 처리 계층을 배포하는 동안에도 요청을 받을 수 없습니다.
# 웹 계층이 처리 계층의 엔드포인트를 직접 호출하고 응답을 기다립니다.
curl -X POST https://internal-worker.example.internal/jobs \
--data '{"orderId":"1001"}' \
--max-time 30
웹 계층은 큐에 넣고 즉시 응답합니다. 처리 계층이 멈춰도 메시지는 보존 기간 동안 큐에 남고, 소비자를 늘리면 밀린 양을 따라잡습니다. 배포와 장애가 사용자 응답에 보이지 않습니다.
aws sqs send-message \
--queue-url https://sqs.ap-northeast-2.amazonaws.com/123456789012/orders \
--message-body '{"orderId":"1001"}'
결합을 끊는 세 가지 도구
AWS에는 결합을 끊는 서비스가 셋 있고, 전달 모델이 서로 다릅니다. 이 차이를 모르면 문항에서 셋 중 아무거나 고르게 됩니다.
| 서비스 | 전달 모델 | 소비 방식 | 이것을 고르는 신호 |
|---|---|---|---|
| Amazon SQS | 한 메시지를 한 소비자가 가져가 처리 | 소비자가 끌어온다(폴링) | "작업을 하나씩 처리한다", "급증분을 완충한다", "실패를 재시도한다" |
| Amazon SNS | 한 메시지를 모든 구독자에게 팬아웃 | SNS가 밀어 준다(푸시) | "하나의 사건을 여러 시스템이 동시에 받아야 한다" |
| Amazon EventBridge | 이벤트 내용에 따라 규칙으로 라우팅 | EventBridge가 대상으로 밀어 준다 | "이벤트 종류에 따라 다른 대상으로 보낸다", "AWS 서비스의 이벤트에 반응한다", "일정에 따라 실행한다" |
셋을 조합하는 형태가 특히 자주 나옵니다. SNS 주제에 여러 SQS 큐를 구독시키면 팬아웃과 완충을 한 번에 얻습니다. 각 구독자가 자기 큐를 갖게 되므로, 한 구독자가 느려도 다른 구독자의 처리에 영향을 주지 않습니다.
트래픽 급증을 큐로 완충한다
Auto Scaling 그룹은 지표를 보고 인스턴스를 늘리지만, 인스턴스가 준비되어 트래픽을 받기까지는 시간이 걸립니다. 스케일링 정책을 아무리 공격적으로 바꿔도 그 준비 시간은 사라지지 않습니다. 급증이 준비 시간보다 빠르면 요청은 유실됩니다.
큐를 앞에 두면 급증분이 큐에 쌓이고, 소비자는 자기 속도로 처리하면서 뒤따라 확장합니다. 요청은 늦게 처리될 뿐 사라지지 않습니다. 시나리오가 "판매 시작 직후처럼 예측 불가능한 급증에도 주문을 잃으면 안 된다"고 말하면, 정답 방향은 스케일링 정책 조정이 아니라 큐 완충입니다.
시점이 예측 가능한 급증이라면 예약 스케일링으로 미리 늘려 두는 안도 함께 검토합니다. 스케일링 정책 유형과 워밍업은 7장 로드 밸런싱과 오토스케일링에서 다룹니다.
AWS Lambda
실행 모델 — 무엇이 사라지고 무엇이 남는가
Lambda는 코드를 함수 단위로 등록해 두고, 이벤트가 올 때만 실행 환경을 띄워 실행합니다. 인스턴스 · 운영체제 · 용량 계획이 사라지고, 남는 것은 함수 코드 · 실행 역할 · 트리거 설정 셋입니다. 요청이 동시에 여러 개 오면 실행 환경도 여러 개가 만들어지며, 한 실행 환경은 한 번에 하나의 이벤트만 처리합니다.
실행이 끝나도 실행 환경은 잠시 유지되었다가 다음 호출에 재사용됩니다. 그래서 핸들러 바깥에서 초기화한 데이터베이스 연결이나 SDK 클라이언트는 재사용되지만, 어떤 이벤트가 어떤 실행 환경으로 갈지는 보장되지 않습니다. 메모리나 로컬 파일에 상태를 쌓아 두는 설계는 성립하지 않습니다.
확인된 한도 — 여기까지만 외웁니다
| 항목 | 기본값 | 한도 | 설계에 주는 함의 |
|---|---|---|---|
함수 실행 시간(Timeout) |
3초 | 최대 900초(15분) | 15분을 넘는 작업은 Lambda가 답이 아닙니다. 분할하거나 컨테이너 · 배치로 옮깁니다 |
메모리(MemorySize) |
128 MB | 최대 10,240 MB, 1 MB 단위 | 메모리를 늘리면 CPU 할당도 함께 증가합니다. 느린 함수의 첫 번째 조정 대상입니다 |
임시 스토리지(/tmp) |
512 MB | 최대 10,240 MB | 큰 파일을 다뤄야 하면 늘립니다. 실행 환경이 사라지면 내용도 사라집니다 |
| 동기 호출 페이로드 | — | 6 MB | 큰 데이터는 Amazon S3에 두고 참조만 전달합니다 |
호출 모델 세 가지 — 재시도의 주체가 다릅니다 SAA 빈출
Lambda 문항의 핵심은 기능이 아니라 실패했을 때 메시지가 어디로 가는가입니다. 호출 경로마다 재시도하는 주체와 실패 메시지의 도착지가 다릅니다.
| 호출 모델 | 대표 트리거 | 재시도 주체 | 실패 메시지의 도착지 |
|---|---|---|---|
동기(RequestResponse, 기본값) |
Amazon API Gateway, Application Load Balancer, 직접 Invoke |
호출자 — Lambda는 오류를 그대로 돌려줍니다 | 없음. 호출자가 처리하지 않으면 그대로 실패입니다 |
비동기(Event) |
Amazon S3 이벤트 알림, Amazon SNS, Amazon EventBridge | Lambda — 함수가 오류를 반환하면 기본적으로 두 번 더 재시도합니다 | 배달 못 한 편지 큐(DLQ) 또는 실패 대상(on-failure destination) |
| 이벤트 소스 매핑(폴링) | Amazon SQS, Amazon DynamoDB Streams, Amazon Kinesis, Amazon MQ, Amazon MSK | Lambda 서비스가 폴링하며 소스의 규칙을 따릅니다 | SQS는 큐의 DLQ, 스트림은 OnFailure 대상 |
비동기 호출은 Lambda가 이벤트를 내부 큐에 넣고 처리합니다. AWS 문서는 이 경우 기본적으로 두 번 재시도하며, 이벤트를 최대 6시간까지 큐에 보관한다고 명시합니다. 모든 시도가 실패하거나 큐에 너무 오래 머문 이벤트는 폐기되므로, 기록을 남기려면 DLQ나 실패 대상을 반드시 설정해야 합니다.
실패 대상으로는 Lambda 함수 · 표준 SQS 큐 · Amazon S3 버킷 · 표준 SNS 주제 · EventBridge 이벤트 버스를 지정할 수 있고, 성공(on-success)과 실패(on-failure)에 각각 다른 대상을 둘 수 있습니다. S3 버킷은 실패 대상으로만 지원됩니다.
동시성 — 예약과 프로비저닝은 다른 문제를 풉니다
동시성은 같은 순간에 실행 중인 함수 인스턴스의 수입니다. 계정과 리전 단위의 동시 실행 한도를 모든 함수가 나눠 쓰기 때문에, 한 함수가 폭주하면 같은 계정의 다른 함수가 스로틀링됩니다.
| 항목 | 예약된 동시성(reserved concurrency) | 프로비저닝된 동시성(provisioned concurrency) |
|---|---|---|
| 푸는 문제 | 다른 함수에 굶기지 않기 + 폭주 함수가 하위 시스템을 무너뜨리지 않기 | 콜드 스타트로 인한 첫 호출 지연 |
| 동작 | 계정 풀에서 그만큼을 떼어 함수 전용으로 잡아 둡니다. 보장이자 상한입니다 | 지정한 수만큼 실행 환경을 미리 초기화해 대기시킵니다 |
| 적용 대상 | 함수 전체(모든 버전과 별칭 포함) | 함수의 별칭 또는 버전 |
| 제약 | 함수별 한도를 두지 않은 함수들을 위해 최소 100개의 동시 실행은 예약하지 않고 남겨야 합니다 | 대기시켜 둔 만큼 비용이 발생합니다. 지연이 중요한 함수에만 씁니다 |
| 0으로 설정하면 | 그 함수는 호출되지 않습니다. 사고 시 즉시 차단하는 수단으로 쓰입니다 | 해당 없음 |
aws lambda put-function-concurrency \
--function-name order-processor \
--reserved-concurrent-executions 50
# 계정과 리전의 동시 실행 한도는 계정 설정에서 확인합니다.
aws lambda get-account-settings \
--query 'AccountLimit.ConcurrentExecutions'
콜드 스타트 — 무엇이 시간을 쓰는가
새 실행 환경을 만들 때는 코드를 내려받아 실행 환경을 준비하고, 런타임을 초기화하고, 핸들러 바깥의 초기화 코드를 한 번 실행합니다. 이 구간이 콜드 스타트이며, 두 번째 호출부터는 재사용되므로 나타나지 않습니다. 따라서 콜드 스타트는 호출이 뜸하거나 갑자기 늘어날 때 문제가 됩니다.
- 초기화 코드를 가볍게 하고, 필요한 것만 핸들러 바깥에서 만듭니다.
- 지연이 중요한 경로에는 프로비저닝된 동시성을 씁니다.
- 함수를 VPC에 연결하면 네트워크 인터페이스 준비가 더해집니다. 필요하지 않다면 연결하지 않습니다.
VPC 연결 — 연결하는 순간 경로가 바뀝니다
기본적으로 Lambda 함수는 우리 VPC 밖에서 실행되며 인터넷과 퍼블릭 AWS 엔드포인트에 접근할 수 있습니다. 프라이빗 서브넷의 Amazon RDS 인스턴스처럼 VPC 안의 리소스에 닿아야 하면 함수에 서브넷과 보안 그룹을 지정해 VPC에 연결합니다.
여기서 바뀌는 것이 있습니다. AWS API 문서는 "함수를 VPC에 연결하면 그 VPC를 통해서만 리소스와 인터넷에 접근할 수 있다"고 명시합니다. 즉 연결한 서브넷에 인터넷으로 나가는 경로가 없으면 외부 API 호출이 그 순간부터 실패합니다.
- 인터넷으로 나가야 하면 프라이빗 서브넷 + NAT 게이트웨이가 필요합니다. 퍼블릭 서브넷에 연결한다고 나갈 수 있는 것이 아닙니다.
- Amazon S3 · Amazon DynamoDB로만 나가면 되면 게이트웨이 엔드포인트가 더 싸고 안전합니다.
- 그 밖의 AWS 서비스는 인터페이스 엔드포인트로 VPC 안에서 호출합니다.
실행 역할과 리소스 기반 정책
Lambda의 권한은 두 방향으로 나뉩니다. 시험이 자주 섞어 놓는 지점입니다.
| 구분 | 무엇을 정하는가 | 어디에 붙는가 |
|---|---|---|
| 실행 역할(execution role) | 함수 코드가 다른 AWS 서비스를 호출할 때의 권한. 로그를 쓰고, S3를 읽고, DynamoDB에 쓰는 권한이 여기 들어갑니다 | 함수의 Role 속성. IAM 역할이며 신뢰 정책의 주체는 Lambda 서비스입니다 |
| 리소스 기반 정책 | 누가 이 함수를 호출할 수 있는가. API Gateway나 S3가 함수를 부를 수 있게 허용합니다 | 함수 자체에 붙는 정책. lambda:InvokeFunction을 특정 서비스나 계정에 허용합니다 |
이벤트 소스 매핑(SQS · DynamoDB Streams · Kinesis)은 방향이 반대입니다. Lambda가 소스를 폴링하므로 실행 역할에 큐를 읽고 삭제할 권한이 필요하고, 큐 쪽에 리소스 기반 정책을 붙일 필요는 없습니다. 역할과 신뢰 정책의 구조는 2장 IAM과 자격 증명에서 다룹니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowLambdaToAssumeRole",
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}
서버리스의 내결함성 정리
Lambda가 "알아서 확장되니까 장애가 없다"고 말할 수는 없습니다. 확장은 자동이지만 실패한 이벤트의 행방은 우리가 설계해야 합니다.
- 동시성 한도에 닿으면 스로틀링됩니다. 중요한 함수는 예약된 동시성으로 몫을 확보합니다.
- 비동기 호출의 실패는 기본 두 번 재시도 후 폐기됩니다. DLQ나 실패 대상을 반드시 둡니다.
- SQS 트리거의 실패는 큐의 배달 못 한 편지 큐 설정으로 격리합니다. 함수 쪽이 아니라 큐 쪽 설정입니다.
- 15분을 넘는 작업은 Lambda가 답이 아닙니다. 단계를 쪼개거나 컨테이너로 옮깁니다.
Amazon API Gateway
API Gateway는 HTTP 요청을 받아 Lambda 함수 · HTTP 엔드포인트 · AWS 서비스로 넘기는 관리형 진입점입니다. 인증 · 스로틀링 · 캐싱 · 로깅을 애플리케이션 코드 밖으로 빼내는 것이 존재 이유입니다.
REST API와 HTTP API
같은 서비스 안에 API 유형이 둘 있습니다. HTTP API는 기능을 줄이고 지연과 비용을 낮춘 유형이고, REST API는 기능이 더 많은 유형입니다. 선택 기준은 "REST API에만 있는 기능이 필요한가" 하나입니다.
| 항목 | REST API | HTTP API |
|---|---|---|
| 권한 부여자 | Lambda 권한 부여자(TOKEN · REQUEST), Amazon Cognito 사용자 풀(COGNITO_USER_POOLS), IAM |
Lambda 권한 부여자(REQUEST), JWT 권한 부여자, IAM |
| API 키와 사용량 계획 | 지원 — 소비자별 쿼터와 스로틀을 붙일 수 있습니다 | 해당 API 작업이 없음 |
| 응답 캐싱 | 지원 — 스테이지 단위로 캐시를 켜고 크기를 고릅니다 | 해당 API 작업이 없음 |
| 엔드포인트 유형 | REGIONAL · EDGE · PRIVATE(VPC 안에서만 접근) |
리전 단위. 프라이빗 통합은 VPC 링크로 처리합니다 |
| 요청 · 응답 변환 | 매핑 템플릿과 요청 검증기 지원 | 파라미터 매핑 중심으로 단순화 |
| WebSocket | 별도 유형이 필요 | 같은 API에서 WEBSOCKET 프로토콜 지원 |
| 고르는 신호 | "파트너에게 API 키로 쿼터를 준다", "응답을 캐시한다", "VPC 안에서만 호출한다" | "단순한 프록시", "JWT로 인증", "지연과 비용을 낮춘다" |
권한 부여 방식
- IAM — 호출자가 서명된 요청을 보냅니다. 같은 계정이나 다른 AWS 워크로드가 호출자일 때 씁니다.
- Amazon Cognito 사용자 풀(REST API) — 최종 사용자 로그인 결과 토큰을 그대로 검증합니다.
- JWT 권한 부여자(HTTP API) — 외부 자격 증명 공급자가 발급한 JWT를 검증합니다.
- Lambda 권한 부여자 — 토큰이나 요청 파라미터를 받아 우리가 만든 함수가 허용 여부와 정책을 돌려줍니다. 위 방식으로 표현할 수 없는 인가 규칙에 씁니다.
- API 키(REST API) — 인증 수단이 아니라 소비자를 식별해 사용량 계획을 적용하는 수단입니다. 이것만으로 보안을 세우지 않습니다.
스로틀링과 캐싱
API Gateway는 요청 속도를 계정 · 스테이지 · 메서드 · 사용량 계획 수준에서 제한할 수 있습니다.
한도를 넘으면 429 Too Many Requests를 돌려주므로,
백엔드가 무너지기 전에 게이트웨이가 먼저 막아 줍니다.
이것이 API Gateway를 붙이는 복원력 측면의 이유입니다.
REST API는 스테이지 단위로 응답 캐시를 켤 수 있고, 캐시 용량을 골라 지정합니다. 메서드 단위로 캐시를 켜고 끌 수 있으며, 필요하면 스테이지 캐시를 비웁니다. 같은 응답이 반복되는 읽기 위주 API에서 백엔드 호출 수와 지연을 함께 줄입니다.
Amazon SQS — 완전관리형 메시지 큐
SQS는 메시지를 저장했다가 소비자가 가져가게 하는 큐입니다. 생산자와 소비자가 서로를 알 필요가 없고, 소비자가 없어도 메시지는 보존 기간 동안 남습니다. 큐 하나의 메시지는 한 소비자만 가져갑니다.
표준 큐와 FIFO 큐 SAA 빈출
| 항목 | 표준 큐 | FIFO 큐 |
|---|---|---|
| 순서 | 최선 노력 — 보장되지 않음 | 메시지 그룹 안에서 엄격한 순서 |
| 중복 | 같은 메시지가 두 번 전달될 수 있음 | 5분 중복 제거 구간 안에서 같은 MessageDeduplicationId는 한 번만 전달 |
| 처리량 | 거의 무제한 | 배치 없이 초당 300개, 배치 사용 시 초당 3,000개. 고처리량 모드로 더 확장 |
| 필수 파라미터 | 없음 | MessageGroupId가 없으면 전송이 실패 |
| 병렬 처리 단위 | 제한 없음 | 메시지 그룹. 같은 그룹은 한 번에 하나씩, 다른 그룹은 순서가 섞일 수 있음 |
| 고르는 신호 | 처리량이 우선이고 순서가 상관없음 | "순서가 보장되어야 한다", "같은 요청을 두 번 처리하면 안 된다" |
FIFO 큐의 순서 보장 범위는 큐 전체가 아니라 메시지 그룹입니다. AWS 문서는 같은 그룹의 메시지가 "항상 한 번에 하나씩, 엄격한 순서로 처리"되며 다른 그룹의 메시지는 순서가 어긋날 수 있다고 명시합니다. 따라서 그룹 ID를 잘 나누는 것이 순서와 병렬성을 동시에 얻는 방법입니다 — 예를 들어 주문 ID를 그룹 ID로 쓰면 주문별 순서는 지키면서 서로 다른 주문은 병렬로 처리됩니다.
처리량이 더 필요하면 FIFO 고처리량 모드를 켭니다.
DeduplicationScope를 messageGroup으로, FifoThroughputLimit을
perMessageGroupId로 설정하는 두 가지를 모두 바꿔야 하며,
하나만 바꾸면 일반 처리량이 그대로 적용됩니다.
가시성 제한 시간
소비자가 메시지를 받으면 그 메시지는 큐에서 삭제되지 않고 일정 시간 동안 보이지 않게 됩니다. 이 시간이 가시성 제한 시간(visibility timeout)입니다. 소비자가 처리를 끝내고 명시적으로 삭제해야 메시지가 사라지며, 삭제 전에 시간이 지나면 메시지가 다시 보이게 되어 다른 소비자가 가져갑니다.
이 구조가 소비자 장애에 대한 방어입니다. 처리 중 소비자가 죽어도 메시지는 되살아납니다. 반대로 처리 시간보다 짧게 잡으면 같은 메시지를 두 소비자가 처리하게 됩니다. "메시지가 중복 처리된다"는 시나리오에서 가장 먼저 확인할 값입니다.
보존 기간과 배달 못 한 편지 큐
| 속성 | 범위 | 기본값 | 무엇에 쓰는가 |
|---|---|---|---|
VisibilityTimeout |
0초 – 12시간 | 30초 | 처리 중인 메시지를 감춰 두는 시간. 처리 시간보다 길게 잡습니다 |
MessageRetentionPeriod |
60초 – 14일 | 4일 | 소비자가 없어도 메시지를 보관하는 기간. 장애 복구 시간을 이 안에 넣습니다 |
DelaySeconds |
0초 – 900초 | 0초 | 큐에 넣은 메시지를 일정 시간 뒤에 보이게 합니다(지연 큐) |
MaximumMessageSize |
1 KiB – 1 MiB | 1 MiB | 메시지 본문 크기 상한. 큰 데이터는 S3에 두고 참조만 보냅니다 |
ReceiveMessageWaitTimeSeconds |
0초 – 20초 | 0초(짧은 폴링) | 롱 폴링 대기 시간. 빈 응답과 요청 수를 줄입니다 |
RedrivePolicy의 maxReceiveCount |
— | 10 | 이 횟수를 넘겨 수신된 메시지를 배달 못 한 편지 큐로 옮깁니다 |
반복해서 실패하는 메시지는 큐 앞을 계속 막습니다. 배달 못 한 편지 큐(dead-letter queue, DLQ)를 지정하고 최대 수신 횟수를 설정하면, 그 횟수를 넘긴 메시지가 DLQ로 옮겨져 정상 메시지의 처리를 방해하지 않습니다. 옮겨진 메시지는 원인을 조사한 뒤 원래 큐로 되돌릴 수 있습니다.
DLQ에는 짝 규칙이 있습니다. AWS 문서는 FIFO 큐의 DLQ는 FIFO 큐여야 하고, 표준 큐의 DLQ는 표준 큐여야 한다고 명시합니다.
{
"deadLetterTargetArn": "arn:aws:sqs:ap-northeast-2:123456789012:orders-dlq",
"maxReceiveCount": "5"
}
짧은 폴링과 롱 폴링
ReceiveMessage는 기본적으로 짧은 폴링(short polling)으로 동작합니다.
AWS 문서는 이때 서버의 일부만 표본으로 조회하므로,
큐에 메시지가 적으면 요청한 것보다 적게 받거나 아예 못 받을 수 있다고 설명합니다.
ReceiveMessageWaitTimeSeconds를 0보다 크게(최대 20초) 설정하면 롱 폴링이 켜집니다.
메시지가 도착할 때까지 기다렸다가 응답하므로 빈 응답이 줄고 요청 수가 줄며 지연도 낮아집니다.
큐를 만들 때 이 값을 20으로 두는 것이 대체로 합리적인 기본 선택입니다.
aws sqs create-queue \
--queue-name orders \
--attributes '{
"VisibilityTimeout": "180",
"MessageRetentionPeriod": "1209600",
"ReceiveMessageWaitTimeSeconds": "20"
}'
Amazon SNS — 주제 기반 팬아웃
팬아웃 구조
SNS는 주제(topic)에 발행된 메시지를 모든 구독자에게 복사해 밀어 줍니다. 생산자는 구독자가 몇 개인지 알 필요가 없고, 구독자를 추가해도 생산자 코드는 그대로입니다. 하나의 사건을 여러 시스템이 각자의 목적으로 처리해야 할 때 쓰는 구조입니다.
실무와 시험 양쪽에서 가장 자주 나오는 형태는 SNS 주제 + 여러 SQS 큐입니다. 구독자마다 자기 큐를 가지므로 팬아웃과 완충을 동시에 얻고, 한 구독자가 느려도 다른 구독자에게 영향을 주지 않습니다.
구독 유형
구독의 Protocol 값이 곧 구독 유형입니다.
AWS API 문서가 나열하는 값은 다음과 같습니다.
| 프로토콜 | 전달 대상 | 비고 |
|---|---|---|
sqs |
Amazon SQS 큐 | 팬아웃과 완충을 함께 얻는 대표 조합 |
lambda |
AWS Lambda 함수 | 비동기 호출이므로 실패 처리는 함수 쪽 설정이 담당합니다 |
http · https |
HTTP(S) 엔드포인트 | 구독 확인이 필요하고, 재시도 정책을 설정할 수 있습니다 |
email · email-json |
이메일 주소 | 운영자 알림용. 구독 확인이 필요합니다 |
sms |
문자 메시지 | 운영자 알림용 |
application |
모바일 앱 엔드포인트 | 모바일 푸시 알림 |
firehose |
Amazon Data Firehose 전송 스트림 | 구독에 IAM 역할(SubscriptionRoleArn)이 필수입니다 |
HTTP(S)와 이메일 구독, 그리고 주제와 엔드포인트가 다른 계정에 있는 경우에는 엔드포인트 소유자가 구독 확인을 해야 전달이 시작됩니다. 확인 토큰은 이틀 동안 유효합니다.
필터 정책 — 구독자마다 받을 것을 고릅니다
구독에 FilterPolicy를 붙이면 그 구독자는 주제의 모든 메시지가 아니라 일부만 받습니다.
구독자 쪽에서 걸러 내면 필요 없는 메시지까지 전달되고 처리되지만,
필터 정책을 쓰면 SNS가 전달 단계에서 걸러 냅니다.
FilterPolicyScope로 무엇을 검사할지 고릅니다.
기본값 MessageAttributes는 메시지 속성을,
MessageBody는 메시지 본문을 대상으로 삼습니다.
{
"eventType": ["order_created", "order_cancelled"],
"region": [{ "prefix": "ap-" }]
}
구독에는 RedrivePolicy로 배달 못 한 편지 큐를 붙일 수 있습니다.
엔드포인트에 닿지 못하거나 서버 오류로 전달하지 못한 메시지가 그 큐에 남아,
SNS 쪽에서도 유실을 조사할 수 있게 됩니다.
RawMessageDelivery를 켜면 SQS나 HTTP(S) 엔드포인트가 SNS 메타데이터 없이 원문만 받습니다.
Amazon EventBridge — 이벤트 버스와 규칙
이벤트 버스
EventBridge는 이벤트를 받아 규칙에 맞는 대상으로 보내는 서버리스 이벤트 버스입니다. 버스는 세 종류입니다.
- 기본 이벤트 버스 — AWS 서비스가 생성하는 이벤트가 계정마다 여기로 들어옵니다. EC2 인스턴스 상태 변경, S3 객체 생성 같은 것들입니다.
- 사용자 지정 이벤트 버스 — 우리 애플리케이션이
PutEvents로 보내는 이벤트를 받습니다. - 파트너 이벤트 버스 — SaaS 파트너가 보내는 이벤트를 받습니다.
AWS 서비스가 만드는 이벤트에 반응해야 한다는 요구가 나오면 EventBridge가 유력합니다. SNS나 SQS는 우리가 직접 발행해야 하지만, EventBridge는 AWS 서비스의 이벤트를 이미 받고 있습니다.
규칙과 패턴 매칭
규칙은 이벤트 패턴 또는 스케줄 표현식 중 최소 하나를 가져야 합니다. 이벤트 패턴이 있는 규칙은 일치하는 이벤트가 관측될 때 실행되고, 스케줄 표현식이 있는 규칙은 정해진 시각에 스스로 실행됩니다. 둘 다 지정할 수도 있습니다.
한 규칙은 하나의 이벤트 버스만 감시하며, AWS 문서는 한 규칙에 동시에 붙일 수 있는 대상이 최대 5개라고 명시합니다. 더 많은 대상이 필요하면 규칙을 나눕니다.
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"detail": {
"state": ["terminated", "stopping"]
}
}
사용자 지정 이벤트는 PutEvents로 보냅니다.
AWS 문서는 항목 하나의 크기가 256 KB 미만이어야 하고,
중첩 JSON은 1,000단계까지 처리한다고 명시합니다.
큰 데이터는 이벤트에 담지 말고 S3에 두고 참조만 보냅니다.
aws events put-events --entries '[
{
"EventBusName": "orders-bus",
"Source": "com.example.orders",
"DetailType": "OrderCreated",
"Detail": "{\"orderId\":\"1001\",\"amountTier\":\"large\"}"
}
]'
스케줄
스케줄 표현식은 cron(0 20 * * ? *) 같은 cron 식과
rate(5 minutes) 같은 rate 식 두 가지입니다.
"매일 새벽에 정리 작업을 돌린다"처럼 시각이 정해진 작업을
서버 없이 실행하는 표준 수단입니다.
정해진 시각에 Lambda를 실행하려고 EC2 인스턴스에 cron을 걸어 두는 선택지가 보이면 운영 부담이 큰 쪽이므로 소거합니다.
SNS · SQS · EventBridge — 무엇을 고를 것인가 SAA 빈출
| 문제문의 요구 | 선택 | 왜 |
|---|---|---|
| 작업을 접수해 두고 하나씩 처리한다 | Amazon SQS | 한 메시지를 한 소비자가 가져갑니다. 소비자를 늘리면 처리량이 늘어납니다 |
| 급증분을 잃지 않고 완충한다 | Amazon SQS | 메시지가 보존 기간 동안 남습니다. 소비자 속도와 생산 속도를 분리합니다 |
| 한 사건을 여러 시스템이 동시에 받는다 | Amazon SNS | 주제에 구독한 모두에게 복사해 전달합니다 |
| 여러 시스템이 받되 각자 완충도 필요하다 | SNS + SQS 팬아웃 | 구독자마다 자기 큐를 갖습니다. 한 구독자의 지연이 다른 구독자에게 번지지 않습니다 |
| 이벤트 내용에 따라 다른 대상으로 보낸다 | Amazon EventBridge | 이벤트 패턴으로 규칙을 만들고 대상을 고릅니다 |
| AWS 서비스의 상태 변화에 반응한다 | Amazon EventBridge | 기본 이벤트 버스가 AWS 서비스 이벤트를 이미 받고 있습니다 |
| 정해진 시각에 작업을 실행한다 | Amazon EventBridge | 스케줄 규칙(cron · rate)이 서버 없이 실행합니다 |
| 순서와 중복 제거가 필요하다 | SQS FIFO 큐 | 메시지 그룹 안의 순서 보장과 중복 제거는 FIFO 큐만 제공합니다 |
| 여러 단계를 순서대로 실행하고 상태를 추적한다 | AWS Step Functions | 메시지 전달이 아니라 워크플로 오케스트레이션의 문제입니다 |
| 기존 애플리케이션이 JMS · AMQP · MQTT를 쓴다 | Amazon MQ | 메시징 코드를 다시 쓰지 않고 그대로 옮기기 위한 선택입니다 |
오케스트레이션과 그 밖의 통합 서비스
AWS Step Functions
Step Functions는 여러 단계를 상태 기계(state machine)로 정의해 실행합니다.
정의는 Amazon States Language라는 JSON 기반 언어로 쓰며,
작업을 수행하는 Task, 분기하는 Choice, 병렬 실행하는 Parallel,
배열을 반복하는 Map, 기다리는 Wait 같은 상태를 조합합니다.
Lambda 함수 안에 순서와 재시도와 오류 처리를 직접 짜 넣으면 어디까지 진행했는지 알 수 없고, 실패 지점부터 다시 시작하기도 어렵습니다. Step Functions는 진행 상태와 재시도 규칙을 서비스가 관리하므로, "여러 단계를 순서대로 실행하고 각 단계의 성공 여부를 추적해야 한다"는 요구의 표준 답입니다.
| 유형 | 성격 | 고르는 신호 |
|---|---|---|
표준(STANDARD, 기본값) |
실행 이력을 남기며 오래 걸리는 워크플로에 적합합니다 | "각 단계의 결과를 감사해야 한다", "실행이 길다" |
Express(EXPRESS) |
짧고 빈도가 높은 워크플로에 적합합니다 | "초당 매우 많은 이벤트를 처리한다", "실행이 짧다" |
유형은 생성 후 변경할 수 없습니다. 큐 타입과 같은 성격의 제약입니다.
AWS AppSync
AppSync는 관리형 GraphQL API를 제공합니다. 클라이언트가 필요한 필드만 한 번의 요청으로 가져가야 하거나, 여러 데이터 소스를 한 스키마로 묶어야 할 때 씁니다. 인증 방식으로 API 키 · IAM · Amazon Cognito 사용자 풀 · OpenID Connect · Lambda 권한 부여를 지원합니다.
REST 방식의 단순한 엔드포인트라면 API Gateway가 더 단순한 선택입니다. 모바일 앱의 오프라인 동기화나 실시간 구독처럼 GraphQL의 성질이 필요한 경우에 AppSync를 고릅니다.
Amazon MQ
Amazon MQ는 Apache ActiveMQ와 RabbitMQ를 관리형으로 제공하는 메시지 브로커입니다. SQS나 SNS와 달리 표준 메시징 프로토콜을 그대로 지원하므로, 기존 온프레미스 애플리케이션이 JMS · AMQP · MQTT · STOMP로 통신하고 있을 때 애플리케이션 코드를 다시 쓰지 않고 옮길 수 있습니다.
배포 모드는 단일 인스턴스(SINGLE_INSTANCE),
가용 영역을 나눈 액티브·스탠바이(ACTIVE_STANDBY_MULTI_AZ),
다중 가용 영역 클러스터(CLUSTER_MULTI_AZ)가 있습니다.
운영 환경이라면 단일 인스턴스는 단일 장애점이므로 다중 가용 영역 모드를 고릅니다.
서버리스가 비용을 줄이는 경우와 늘리는 경우
서버리스가 언제나 싸다는 것은 사실이 아닙니다. 과금 모델이 사용량 기반이라는 것은, 사용량이 낮으면 매우 유리하고 사용량이 일정하게 높으면 불리해질 수 있다는 뜻입니다.
| 상황 | 서버리스가 유리한가 | 근거 |
|---|---|---|
| 호출이 뜸하거나 변동이 크다 | 유리 | 대기 상태에 요금이 붙지 않습니다. 유휴 인스턴스를 띄워 둘 필요가 없습니다 |
| 개발과 스테이징 환경 | 유리 | 쓰지 않는 시간이 대부분입니다 |
| 일정하게 높은 부하가 24시간 지속된다 | 불리할 수 있음 | 약정 할인을 받을 수 있는 컴퓨팅이 대체로 유리합니다. Savings Plans와 예약 인스턴스는 5장에서 다룹니다 |
| 지연에 민감해 프로비저닝된 동시성이 필요하다 | 이점이 줄어듦 | 미리 띄워 둔 만큼 요금이 발생해 "쓴 만큼만" 모델에서 벗어납니다 |
| 운영 인력이 적다 | 유리 | 패치 · 용량 계획 · 스케일링 설정이 사라집니다. 총소유비용에서 운영 비용은 큰 항목입니다 |
흔한 오해
시험 포인트 정리
확인 문제
이 장의 핵심을 확인하는 10문항입니다. 키보드만으로 완주할 수 있습니다 — 숫자키 1~5로 선택지를 고르고 Enter로 제출합니다.
학습용 유형 연결형과 순서 배열 문항이 섞여 있을 수 있습니다. 이 두 유형은 암기 확인에 효율이 좋아 기본개념 확인 문제에만 넣었으며, 실제 SAA-C03 시험에는 출제되지 않습니다.
이어서 볼 곳
- 13장 · 컨테이너 Lambda로 담기 어려운 워크로드가 가는 곳입니다. ECS와 Fargate, EKS의 선택 기준을 운영 부담으로 정리합니다.
- 7장 · 로드 밸런싱과 오토스케일링 큐 완충과 짝을 이루는 수평 확장 쪽 이야기입니다. 스케일링 정책과 워밍업이 왜 급증을 못 따라가는지 여기 있습니다.
- 복원력 있는 아키텍처 설계 (26%) 이 장의 내용이 속한 도메인입니다. 과제 진술 2.1의 판단 지점을 한 페이지로 모았습니다.
- 4장 · VPC 연결과 하이브리드 VPC에 연결한 Lambda가 밖으로 나가는 경로를 설계할 때 필요한 게이트웨이 엔드포인트와 인터페이스 엔드포인트를 다룹니다.
- 실습 7 · SQS + Lambda 비동기 처리 가시성 제한 시간과 배달 못 한 편지 큐, 배치 처리를 직접 구성해 확인합니다.
- 헷갈리는 쌍 비교 표준 큐와 FIFO 큐, SNS와 EventBridge처럼 시험이 노리는 쌍을 표 하나로 모았습니다.
공식 문서 출처
이 장의 수치와 동작 서술은 모두 아래 문서에서 확인했습니다.
- AWS Lambda 개발자 안내서 — 할당량 — 실행 시간 최대 900초, 메모리 최대 10,240 MB, 동기 호출 페이로드 6 MB
- AWS Lambda 개발자 안내서 — 함수 호출 — 동기 · 비동기 · 이벤트 소스 매핑 세 가지 호출 경로
- AWS Lambda 개발자 안내서 — 비동기 호출 — 기본 두 번 재시도, 이벤트를 최대 6시간 큐에 보관, 실패 시 폐기
- AWS Lambda 개발자 안내서 — 비동기 호출 기록 보존 — 배달 못 한 편지 큐와 성공 · 실패 대상, S3는 실패 대상으로만 지원
- AWS Lambda 개발자 안내서 — 이벤트 소스 매핑 — 폴링 기반 소스 목록과 스트림 소스의 오류 처리 옵션
- AWS Lambda 개발자 안내서 — 동시성 구성 — 예약된 동시성이 보장이자 상한이라는 점, 최소 100개를 예약하지 않고 남겨야 한다는 제약
- AWS Lambda 개발자 안내서 — 프로비저닝된 동시성 — 실행 환경을 미리 초기화해 콜드 스타트를 없앤다는 서술
- AWS Lambda 개발자 안내서 — VPC의 리소스에 접근하도록 함수 구성 — VPC에 연결하면 그 VPC를 통해서만 리소스와 인터넷에 접근한다는 서술
- AWS Lambda 개발자 안내서 — 권한 모델 — 실행 역할과 리소스 기반 정책의 구분
- Amazon API Gateway 개발자 안내서 — API 캐싱 — 스테이지 단위 캐시 활성화와 캐시 용량 지정
- Amazon API Gateway 개발자 안내서 — HTTP API의 Lambda 권한 부여자 — HTTP API가 지원하는 권한 부여 방식
- Amazon SQS API 레퍼런스 — CreateQueue — 큐 속성의 유효 범위와 기본값, 큐 타입을 생성 후 변경할 수 없다는 서술, 재생성 60초 대기
- Amazon SQS 개발자 안내서 — 가시성 제한 시간 — 기본 30초, 최대 12시간
- Amazon SQS 개발자 안내서 — 배달 못 한 편지 큐
—
maxReceiveCount의 동작과 FIFO · 표준 큐의 짝 규칙 - Amazon SQS 개발자 안내서 — 롱 폴링 — 짧은 폴링의 표본 조회 동작과 롱 폴링 대기 시간 최대 20초
- Amazon SQS 개발자 안내서 — FIFO 큐 — 메시지 그룹 안의 순서 보장, 그룹 간 순서는 보장되지 않는다는 서술
- Amazon SQS 개발자 안내서 — FIFO 큐의 고처리량 — 배치 없이 초당 300개, 배치 사용 시 초당 3,000개, 고처리량 모드를 켜는 두 속성
- Amazon SQS 개발자 안내서 — MessageDeduplicationId — 5분 중복 제거 구간과 콘텐츠 기반 중복 제거
- Amazon SNS API 레퍼런스 — Publish — 주제에 발행한 메시지가 모든 구독 엔드포인트로 전달된다는 서술
- Amazon SNS 개발자 안내서 — 메시지 필터링 — 필터 정책과 필터 정책 범위(메시지 속성 · 메시지 본문)
- Amazon SNS 개발자 안내서 — 주제 만들기 — 구독 프로토콜과 구독 확인 절차
- Amazon EventBridge API 레퍼런스 — PutTargets — 한 규칙에 붙일 수 있는 대상이 최대 5개라는 서술
- Amazon EventBridge API 레퍼런스 — PutEvents — 항목 하나의 크기가 256 KB 미만이어야 한다는 제약
- Amazon EventBridge 사용 설명서 — 스케줄 규칙 만들기
—
cron과rate표현식 - Amazon EventBridge 사용 설명서 — 이벤트 버스 만들기 — 기본 · 사용자 지정 · 파트너 이벤트 버스의 구분
- AWS Step Functions 개발자 안내서 — Task 상태 — Amazon States Language의 상태 유형
- AWS AppSync 개발자 안내서 — GraphQL 아키텍처 — GraphQL 연산 모델과 인증 방식
- Amazon MQ 개발자 안내서 — 브로커 — ActiveMQ · RabbitMQ 엔진과 배포 모드