AWS 기술 블로그
알리는사람들의 서버리스 기반 현대화 여정 – DynamoDB 최적화 사례
알리는사람들 소개
알리는사람들은 기업의 원활한 커뮤니케이션을 돕는 메시징 솔루션을 개발하는 스타트업 입니다. 다양한 메시징 채널을 통합하여 고객에게 메시지가 효과적으로 도달할 수 있도록 지원하며, 현재 다수의 기업이 알리는사람들의 솔루션을 활용해 고객 알림, 인증, 마케팅 메시지 등을 효율적으로 운영하고 있습니다.
Sendon 서비스 소개
센드온(Sendon)은 기업을 위한 클라우드 네이티브 메시징 서비스입니다. 개발자가 쉽게 활용할 수 있도록 강력한 API와 SDK를 제공하며, 대량의 메시지를 빠르고 안정적으로 전송할 수 있습니다. 문자, 알림톡, 친구톡 등 다양한 채널을 지원해 고객과의 커뮤니케이션을 더욱 효과적으로 만들고, 현재 다양한 기업이 Sendon을 활용해 고객 알림, 인증, 마케팅 메시지를 효율적으로 운영하고 있습니다.
배경: ALIGO 경험과 Sendon의 새로운 도전
8년 전, Aligo 라는 비즈메시징 서비스를 선보인 이후, 약 20만명의 개인 또는 사업자 회원을 누적 확보하였고, 하루 500만건, 월 1억 5천만건 이상의 메시징 트래픽이 지속적으로 유입되고 있습니다. 짧은 시간 요청 당 수십만~수백만 건의 메시지를 발송하는 트래픽 스파이크 상황을 빈번히 경험해왔고, 이 경험을 토대로 개발 중인 신규 비즈 메시징 플랫폼 “Sendon”에서도 대규모 메시지 트래픽 스파이크가 더욱 빈번히 발생할 것으로 예상하고, 이에 대응할 수 있는 아키텍처 수준의 고민을 진행했습니다.
전통적인 RDB 기반 아키텍처에서는 대규모 트래픽 처리 시 인덱스 관리, 스키마 변경, 샤딩, 조인 최적화 등 많은 리소스가 필요하고, 트래픽 변동성에 유연하게 대응하기도 쉽지 않았습니다. 반면 Amazon DynamoDB는 서버리스 특성과 자동 확장성, 일관된 저지연 성능을 바탕으로 대규모 트래픽 환경에도 비교적 손쉽게 대응할 수 있다는 것을 확인했습니다. 이 점을 활용하고자 DynamoDB를 도입했으나, 초기에는 RDB와 유사한 사고방식을 그대로 적용한 탓에 다음과 같은 문제가 발생했습니다.
- 특정 파티션 키에 과도한 부하가 몰리는 “핫 파티션(Hot Partition)” 문제
- 파티션 처리 한계 초과에 따른 “쓰로틀링(Throttling)” 발생
- GSI(Global Secondary Index) 파티션 처리 이슈
- 단건 쓰기에 따른 높은 네트워크 왕복 횟수로 인한 비용·성능 비효율
이 글에서는 알리는사람들의 현대화 여정에서 겪었던 고민 사항들을 중심으로, DynamoDB 및 Lambda 도입 초기의 시행 착오부터 최적화 된 설계 패턴 적용까지의 과정을 다룹니다.
특히 DynamoDB의 특성을 활용한 설계 패턴 적용, Lambda Fan-Out 도입, 그리고 AWS의 DCAD (Database Clinic in A Day) 프로그램을 통해 얻은 새로운 시각과 교훈도 함께 공유하고자 합니다.
초기 문제: 단순 파티션 키 설계의 한계
메시지 발송 시 “메시지 그룹”과 그 그룹에 속한 다수의 “메시지 아이템”이라는 1:N 구조가 기본 패턴입니다. 이를 DynamoDB에 단순히 파티션 키=그룹ID, 정렬 키=메시지ID
형태로 매핑하면 하나의 파티션 키에 수십만~수백만 아이템이 몰릴 수 있습니다. DynamoDB는 파티션 별 초당 3,000 RCU, 1,000 WCU라는 제약사항을 갖고 있으며, 이를 초과하면 쓰로틀링이 발생합니다.
또한 단 건 PutItem API 호출을 반복할 경우 네트워크 왕복 횟수가 크게 늘어나 비용과 성능 면에서 모두 비효율적입니다. 일반적인 네트워크 설정에서 초당 1,000 WCU 제한에 한참 못 미치는 처리량을 보이며, 대규모 트래픽 상황에서 지연과 실패율이 급격히 증가하는 문제가 발생했습니다.
첫 번째 개선: BatchWriteItem API 호출을 통한 Bulk Write 도입
대량 데이터 저장 성능을 개선하기 위해 가장 먼저 적용한 방안은 단건 쓰기 대신 BatchWriteItem API를 사용하는 것이었습니다. BatchWriteItem은 한 번의 요청에 최대 25개 아이템을 저장할 수 있어 네트워크 오버헤드를 줄이고 처리량을 향상시킬 수 있습니다. 수백~수천 건 수준의 비교적 작은 규모 트래픽에 대해서는 처리 속도 개선을 얻을 수 있었습니다.
아래 그래프에서 볼 수 있듯이, BatchWriteItem 도입으로 단일 파티션에 대한 처리량이 초당 1,000건까지 증가하면서 DynamoDB의 파티션당 WCU 제약에 도달하여 쓰로틀링이 발생하기 시작했습니다. 이는 특정 파티션 키에 과도한 쓰기 요청이 집중되는 문제를 해결하기 위한 추가적인 전략이 필요함을 의미했습니다.
두 번째 개선: 파티션 키 샤딩 (Sharding)을 통한 부하 분산
핫 파티션 문제를 해결하기 위해 파티션 키를 샤딩(Sharding)하는 방법을 적용했습니다.
기존에는 하나의 파티션 키에 여러 그룹의 아이템이 모두 저장되던 방식에서, 메시지 ID를 이용해 일정 크기 단위로 샤드를 나누고 파티션 키를 그룹ID#샤드ID
형태로 재구성했습니다.
예를 들어 메시지가 1,000,000건이고, 샤드 크기를 200개로 설정한다면 1,000,000 ÷ 200 = 5,000개 샤드가 형성됩니다. messageId // shardSize를 통해 해당 메시지가 어느 샤드에 속할지를 결정할 수 있습니다.
이렇게 하면 단일 파티션에 몰리던 부하를 수천 개 파티션으로 분산할 수 있어 파티션 처리 한계를 뛰어넘는 대규모 트래픽에도 대응할 수 있습니다. 이를 통해 쓰로틀링 빈도를 크게 감소시키고, 대규모 발송 시 처리 시간도 안정화될 것으로 기대했습니다.
하지만 실제 적용 결과, 여전히 쓰로틀링이 발생했으며 기대했던 만큼의 성능 개선 효과를 얻지 못했습니다.
세 번째 개선: 삽입 순서 셔플링 (Shuffling)을 통한 롤링 핫 파티션 완화
샤딩을 도입했음에도 불구하고, 메시지 ID가 순차적으로 증가하는 특성으로 인해 여전히 특정 시점에 특정 샤드에 부하가 집중되는 현상이 발생했습니다. 이는 대량의 메시지가 순차적으로 처리되면서 앞쪽 샤드부터 차례대로 부하가 이동하는 “롤링 핫 파티션” 문제를 야기했습니다.
이 문제를 해결하기 위해 데이터 삽입 전에 전체 메시지의 순서를 무작위로 뒤섞는 방식(셔플링)을 도입했습니다. 이렇게 메시지들이 무작위로 재배열되면서 샤드들에 균등하게 분산되어, 특정 샤드에 부하가 집중되는 현상을 효과적으로 방지할 수 있었습니다. 이러한 최적화 적용 결과, 쓰로틀링 발생 빈도가 크게 감소했으며 전체적인 처리 성능도 향상되었습니다. 특히 대규모 메시지 발송 시에도 안정적인 처리가 가능해 졌습니다.
네 번째 개선: 테이블 처리량 향상을 위한 Warm Throughput 설정
샤딩과 셔플링을 통해 파티션 제약은 해결했으나, 일정 수준 이상으로 쓰기 속도가 증가하지 않는 현상이 발생했습니다. DynamoDB는 온디맨드 처리량 모드로 테이블을 생성하면 최대 4,000 WCU의 처리량을 제공할 수 있는 상태로 생성되며, 이를 초과하는 요청에 대해서는 쓰로틀링이 발생할 수 있습니다. 아래 그래프에서 볼 수 있듯이, 병렬도를 높여도 아이템 처리 속도가 4,000 WCU 정도로 수렴하는 것을 확인할 수 있습니다.
대규모 메시지 발송에 대비하여 테이블의 Warm Throughput을 높게 설정하면, 테이블의 필요한 읽기/쓰기 처리량을 쉽게 확보할 수 있습니다. 실제로 아래 그래프에서 볼 수 있듯이, Warm Throughput을 40,000으로 설정한 후에는 초당 4만 건에 가까운 쓰기 요청에도 쓰로틀링 없이 안정적으로 처리할 수 있었습니다.
결론 및 향후 계획
위 그래프에서 볼 수 있듯이, 단계별 최적화를 거치면서 처리 성능이 크게 향상되었습니다. 초기 단건 쓰기 방식에서 배치 쓰기, 논리적 샤딩, 셔플링을 순차적으로 적용하면서 초당 처리량이 16배 이상 증가했고, 특히 샤딩과 셔플링을 함께 적용했을 때 가장 안정적인 성능을 보여주었습니다. 이를 통해 DynamoDB의 파티션 키 제약 사항을 이해하고 이에 맞는 효과적인 키 디자인을 구현하는 방법을 터득할 수 있었습니다. 또한 Warm Throughput 설정을 통해 언제든 원하는 만큼 처리 성능을 높일 수 있음을 확인했습니다.
이번 글에서는 RDB에서 DynamoDB로 전환하는 과정에서 겪은 시행착오를 바탕으로 단계별 아키텍처 개선 경험을 공유했습니다. 이 과정에서 AWS Database Clinic in a Day(DCAD) 프로그램을 통해 DynamoDB 의 가이드를 받으며, RDB 중심 사고방식에서 벗어나 액세스 패턴 중심 모델링, 싱글 테이블 디자인, BatchWriteItem, 샤딩, 셔플링, Warm Throughput 등 DynamoDB의 다양한 개념과 모범 사례를 습득할 수 있었습니다. 또한 AWS Well-Architected Framework의 원칙을 참고해 의사결정 방향성을 명확히 잡는 데 도움을 받았습니다.
알리는사람들은 앞으로도 Sendon 서비스의 지속적인 개선에 집중할 것입니다. 운영 데이터를 기반으로 성능 지표를 재검토하고, 트래픽 변화에 따라 동적으로 샤드 크기와 테이블의 Capacities를 자동 조정하도록 시스템을 구축할 예정입니다. 또한, 메시지 본문을 S3에 보관하는 하이브리드 구조로 전환하여 비용 효율성을 높이는 등, 트래픽 변동성이 큰 환경에서도 안정적인 대규모 메시지 처리와 장기적인 비용 효율, 그리고 높은 품질의 서비스를 제공하기 위한 고도화를 이어나갈 계획입니다.