SQS에서 Lambda vs API
Source: Dev.to
번역을 진행하려면 번역이 필요한 전체 텍스트를 제공해 주세요. 텍스트를 주시면 요청하신 대로 한국어로 번역해 드리겠습니다.
개요
API 서비스가 Lambda 함수를 프록시로 사용하는 대신 DynamoDB 스트림 이벤트를 직접 처리하도록 할지 평가하고 있습니다. 목표는 구축하고 유지해야 하는 “glue” Lambda의 수를 줄이는 것입니다.
현재 아키텍처
- Client request –
DELETE /account/:accountId가accounts-resource-api로 전송됩니다. - API가 DynamoDB에 기록합니다.
- DynamoDB 스트림이 EventBridge를 통해 Lambda를 트리거합니다.
- Lambda가 메시지를 SQS 큐에 푸시합니다.
- 워커(다른 Lambda)가 큐에서 읽고 각 하위 계정에 대해
DELETE /account/:accountId를 호출합니다.
제안된 아키텍처
- 중간 Lambda를 제거합니다.
accounts-resource-api가 DynamoDB 스트림에 구독하도록 하고 (EventBridge → SQS), 삭제 작업을 직접 처리하도록 합니다.- API 내부에서 SQS 폴링 및 메시지 처리를 위해 sqs‑consumer와 같은 npm 라이브러리(Node.js)를 사용합니다.
장단점
| 항목 | Lambda 기반 워커 | API 직접 처리 |
|---|---|---|
| 운영 오버헤드 | 별도의 배포 단위; 추가 IAM 권한; 추가 모니터링. | Lambda 함수 수 감소; “글루” 코드 감소. |
| 확장성 | Lambda는 SQS 백로그에 따라 자동으로 확장되며; 각 호출은 격리됩니다. | API가 폴링 및 동시 처리를 담당해야 하며; 확장은 API의 자동 확장 설정에 따라 달라집니다. |
| 콜드 스타트 지연 | 첫 호출 시 지연이 발생할 수 있지만, 짧은 작업에서는 보통 무시할 정도입니다. | API 자체에는 콜드 스타트가 없지만, 폴링 루프가 지속적으로 실행되어 리소스를 따뜻하게 유지할 수 있습니다. |
| 오류 처리 및 DLQ | SQS → Lambda 통합을 통해 DLQ와 재시도 정책에 대한 기본 지원이 제공됩니다. | API 코드에서 DLQ 처리, 재시도 및 백오프 로직을 직접 구현해야 합니다. |
| 리소스 소비 | Lambda는 메시지가 있을 때만 실행되며; 비용은 호출당 부과됩니다. | API 인스턴스는 폴링 중에 유휴 상태일 수 있어 작업이 없어도 컴퓨팅 비용이 발생합니다. |
| 가시성 | Lambda 호출당 CloudWatch 로그; 추적이 용이합니다. | API의 소비자 루프 내에 로깅, 메트릭 및 추적을 추가해야 합니다. |
| 보안 표면 | Lambda에 대해 최소 권한 역할을 별도로 사용합니다. | API 서비스는 SQS를 읽고 필요에 따라 DLQ에 쓰기 위한 추가 권한이 필요합니다. |
구체적인 우려 사항
데드‑레터 큐(DLQ) 관리
- Lambda: Lambda 트리거를 구성하여 재시도 횟수가 설정 가능하도록 지정된 수 만큼 실패한 메시지를 자동으로 DLQ로 이동시킬 수 있습니다.
- API: 처리 오류를 포착하고, 재큐 시점을 결정하며, 메시지를 명시적으로 DLQ에 전송하는 코드를 작성해야 합니다. 이는 복잡성을 증가시키고 버그 발생 가능성을 높입니다.
API에 추가되는 부하(폴링)
- API 내부에서 SQS를 폴링하면 서비스가 SQS와 장기 연결을 유지하게 됩니다.
- 특히 폴링 간격이 짧으면 CPU와 메모리 사용량이 증가할 수 있습니다.
- 자동 스케일링 정책은 요청 트래픽뿐만 아니라 소비자 루프의 기본 부하도 고려해야 합니다.
유지보수 오버헤드
- API 엔드포인트로 단순히 전달하는 Lambda는 가볍지만 여전히 배포, 버전 관리 및 모니터링이 필요합니다.
- 로직을 API에 통합하면 배포 가능한 단위 수는 줄어들지만, 신뢰성, 스케일링 및 오류 처리에 대한 책임이 API 코드베이스로 이전됩니다.
권장 사항
-
Lambda부터 시작해야 하는 경우:
- 간단하고 즉시 사용할 수 있는 DLQ 처리.
- 큐 깊이에 따라 자동 스케일링.
- 관심사의 명확한 분리 (API는 HTTP 요청을 처리하고; Lambda는 백그라운드 처리를 담당).
-
API‑direct 처리를 고려해야 하는 경우:
- API가 이미 수평 확장이 가능한 플랫폼(ECS, EKS, Fargate 등)에서 실행되고 추가 폴링 부하를 충분히 감당할 수 있는 경우.
- 서비스에 견고한 재시도, 백‑오프 및 DLQ 로직을 구현할 준비가 된 경우.
- Lambda 함수 수를 줄이는 것이 비용, 배포 복잡성 등 측면에서 실질적인 운영 이점을 제공하는 경우.
-
하이브리드 접근법 – 공용 API 대신 전용 워커 서비스(예: 컨테이너화된 컨슈머)로 전달하는 얇은 Lambda를 유지합니다. 이렇게 하면 별도 워커의 스케일링 이점을 얻으면서 동일한 API 엔드포인트를 호출하는 “접착제” Lambda를 피할 수 있습니다.
요약
- Lambda를 DynamoDB 스트림과 SQS 사이의 브리지로 사용하는 것은 강력한 내장 신뢰성 기능을 갖춘 잘 확립된 패턴입니다.
- API에 SQS 소비를 직접 포함하는 것도 가능하지만 DLQ, 재시도 및 스케일링을 신중하게 다루어야 합니다.
- 팀의 운영 성숙도, 비용 모델, 그리고 예상되는 자식 계정 삭제량을 고려하여 트레이드오프를 평가하십시오.
두 패턴 중 어느 것이든 사용해 본 경험이 있다면, 특히 장기 실행 폴러, DLQ 처리, 전체 시스템 신뢰성 등에 관한 이야기를 자유롭게 공유해 주세요.