지난 12/26일부터 특정 유저를 대상으로 무료 3,000원 쿠폰을 지급하는 이벤트를 진행했습니다.
이번 이벤트의 지급 대상은 약 320만 명으로, 팬아웃 패턴 아키텍처를 도입하여 서버의 부하 없이 연말 이벤트를 성공적으로 마칠 수 있었습니다. 🎁(쿠폰함을 확인해보세요 소근소근)
팬아웃 패턴을 aws 자격증을 준비할 때 학습했는데, 실제 적용할 기회가 생겨 굉장히 뿌듯하였습니다. :)
도입 배경
이전에도 유사한 쿠폰 지급 이벤트를 여러 차례 진행했으며, 종종 서버 부하 문제에서 벗어날 수 없었습니다

- API 서버: 유저가 쿠폰 지급 대상인지 확인한 뒤, 대상자라면 SQS에 이벤트를 발행.
- Lambda: SQS에서 이벤트를 소비하여 쿠폰 지급 작업을 처리.
그 당시에도 쿠폰 지급 대상이 약 300만 명으로 추산 되었는데, 이는 SQS 1개의 최대 용량인 12만 개와 비교했을 때 훨씬 부족한 수용 능력이었습니다. 이러한 구조적 한계가 서버 부하의 주요 원인이었습니다.
팬아웃 패턴(Fan Out Pattern)?
팬아웃 패턴은 하나의 메시지를 여러 수신자에게 동시에 분배하거나, 여러 작업으로 나누는 디자인 패턴입니다. 주로 분산 시스템에서 병렬 처리와 확장성을 개선하기 위해 사용됩니다.

- 특정 이벤트가 발생하면 메시지가 SNS(Simple Notification Service)로 전달됩니다.
- SNS는 메시지를 구독하는 여러 SQS(Simple Queue Service)에 이벤트를 분배합니다.
- SNS에 Message Filtering 이 지정되어있다면, 특정 SQS로만 이벤트를 분배할 수 있습니다.
- 이 정책이 없다면 구독하고 있는 모든 sqs에 이 메시지를 전송한다.
- 각 SQS에 연결된 Lambda 함수들이 이벤트를 처리하며, 이를 통해 부하를 분산합니다.
물론 API 서버에서 여러 SQS로 직접 이벤트를 발행할 수도 있었지만, SNS를 활용함으로써 다음과 같은 이점을 얻을 수 있었습니다:
- 장애 격리 오류가 발생하더라도 API 서버와는 별도로 동작하여 장애가 격리됩니다.
- 로직 간소화 API 서버는 SNS 주제에 메시지를 게시하기만 하면 됩니다. SNS에서 특정 큐에 이벤트를 발행해주기에, 여러 큐로 메시지를 분배하는 복잡한 로직을 구현할 필요가 없어졌습니다.
쿠폰 지급 시스템 설계 with 팬아웃패턴

- API서버에서 쿠폰 지급 대상인지 확인한다.
- 지급 대상자라면, 어떤 SQS로 보낼 지 랜덤값을 부여한다.
- SNS에 이벤트를 개시한다.
- SNS에서는 랜덤값을 확인해, 메시지 필터링을 통해, 이 메시지를 어떤 SQS로 보낼지 정해준다.
- 람다는 SQS 에서 메시지를 소비하여, 쿠폰을 지급한다
이후 다음 조건을 통해 SQS 의 개수를 정하였습니다.
- 지급 대상자 추정: 하루 동안 DAU(370만명)에서 특정 조건(50만명)을 제외한 약 320만 명이 쿠폰 지급 대상자로 추정되었습니다.
- 큐 설계: 각 SQS 큐의 최대 처리 용량(12만 건)을 고려하여, 총 35개의 큐를 생성해 약 350만 건을 처리할 수 있는 구조를 설계했습니다.
D-DAY
실제로 각 큐에 최대 약 9만 건씩 총 35개의 데이터가 쌓였으며, 이를 통해 DAU 기준으로 산출한 계산이 실제 상황과 일치함을 확인할 수 있었습니다.

SQS에서 메시지를 소비하는 주체인 Lambda는 EventBridge 스케줄을 통해 인스턴스 수를 동적으로 조절할 수 있었습니다.
스케줄을 하나씩 활성화한다는 것은 곧 Lambda 인스턴스를 증가시키는 것을 의미하므로, 메시지 처리 속도를 유연하게 조정할 수 있는 구조를 제공했습니다.
모니터링을 통해, 점진적으로 이 개수를 늘렸고 안정화된 상태에서는 최종적으로 약 5개의 람다를 가동했습니다.
결국 각 큐당 1분에 300개 정도 소비하면서 1분에 10,500개씩 쿠폰을 지급할 수 있었습니다

이론으로만 알고 있던 사실을 제안하고 적용해 성공적으로 안정적인 쿠폰 지급까지 적용된것을 보니 굉장히 뿌듯합니다.
앞으로도 실무에 이론을 적용할 날이 많았으면 좋겠네요
또한 어떤 상황에서든 best practice 를 찾기 위해 꾸준한 공부도 잊지 않으려합니다.
+ 2025.03.15 수정사항
제가 [팬아웃 패턴] 설계 당시 SQS의 수신 제한이 12만 개라고 생각해서 300만 개의 데이터를 처리하기 위해 SQS 30개로 데이터를 분산해서 설계했었는데요.이건 잘못된 생각이었고, SQS Standard 기준 in-flight-message 제한만 12만 개였습니다. [공식문서]
사실상 삭제만 잘한다면 Standard 한정 어떤 상황에서는 거의 무제한으로 수신할 수 있습니다.
- in-flight message?
따라서 이후 배포 시에는, 큐 개수를 줄였고 12만개 이상의 데이터가 잘 들어가는 점 확인했었습니다. 즉 과감히 큐 1개만 사용해도 됐던 상황으로 재정리드립니다.
'회사에서 한 일' 카테고리의 다른 글
CDN DTO 1,600GB → 3GB로 비용 절감하기 (5) | 2025.03.16 |
---|---|
DynamoDB에서 Redis로: 26억 건 데이터 마이그레이션과 비용 최적화 (5) | 2024.11.10 |
docker-compose로 테스트 환경 구축하기 (4) | 2024.09.08 |
DynamoDB 인덱스 개선으로 비용 절감하기 (3) | 2024.09.01 |
멀티태넌시 SaaS 모듈 설계 썰 푼다.txt (3) | 2024.06.29 |