- 알림 시스템은 비동기적으로 사용자에게 정보를 제공할 때 유용하게 쓰인다.
문제 이해 및 설계 범위 확정
- 하루에 수백만 건의 알림을 보내는 확장성 있는 시스템을 구축하는 것은 쉽지 않기 때문에 구현에 대한 깊은 이해가 필요하다.
질문
- 어떤 종류의 알림을 지원해야 하나? 푸시, SMS, 이메일
- 실시간이어야 되나요? soft-real-time, 가능한 빨리 하지만 부하가 있을 땐 늦어도 된다.
- 어떤 종류의 단말을 지원해야 되나요? iOS, AOS, 데스크탑, 랩탑
- 알림은 누가 만드나요? 클라이언트 프로그램, 서버 스케줄
- 알림을 받지 않을 수 있게 설정할 수 있나요? 네
- 하루에 몇 건까지 보내야 되나요? 천만 건의 푸시, 백만 건의 SMS, 5백만 건의 이메일
개략적 규모 추정
- QPS : 10,000,000 / 24 / 60 / 60초 = 115/초
- 하지만 알림의 특성 상 특정 시간에 몰리는 경우가 많다.
개략적 설계안 제시 및 동의 구하기
알림 유형별 지원 방안
iOS 푸시 알림
- 알림 provider
- notification request를 만들어 APNS에 보내는 주체
- device token : 알림 요청을 보내는 데 필요한 고유 식별자
- payload : 알림 내용을 담은 객체
{
"aps" : {
"alert" : {
"title" : "game request",
"body" : "hello world",
}
"badge" : 5
}
}
- APNS (Apple Push Notification Service)
- 애플이 제공하는 원격 서비스, 푸시 알림을 단말로 전달한다.
- iOS device
AOS 푸시 알림
- APN 대신 FCM(Firebase Cloud Messaging)을 사용한다.
SMS
- KT surem 등의 상용 서비스를 이용한다.
이메일
연락처 정보 수집 절차
- 앱을 설치하여 계정을 등록할 때, 이메일이나 전화번호, 기기의 단말 고유 번호(단말 토큰) 등을 수집하여 DB에 저장한다.
알림 전송 및 수신 절차
무지성 설계
- N개의 서비스
- 마이크로서비스
- 크론잡
- 분산 시스템 컴포넌트
- 과금서비스 / 배송알림 등
- 알림 시스템
- N개 서비스에 알림 전송을 위한 API 제공
-3자 서비스에 전달할 payload도 만들어 내야한다.
- 3자 서비스
- 사용자에게 알림을 전달하는 역할
- 확장성, 서비스 통합이나 제거가 쉬워야 한다.
- 중국같은 곳에서는 FCM을 쓸 수 없다.
- 단말
- SPOF
- 알림 서비스가 하나 밖에 없으면 그 서버에 장애가 생기면 전체 서비스에 장애가 생긴다.
- 규모 확장성
- 한 대 서비스로 푸시 알림에 관계된 모든것을 처리하므로 DB나 캐시 등 컴포넌트의 규모를 개별적으로 늘릴 수 없다.
- 성능 병목
- 알림을 처리하고 보내는 것이 자원을 많이 사용하는 작업일 경우 트래픽이 모려 과부하 상태에 빠질 수 있다.
지성 설계
-
DB와 캐시를 알림 시스템 서버에서 분리한다.
-
알림 서버를 증설하고 scale out이 이루어질 수 있게 한다.
-
MQ를 사용하여 coupling을 줄인다. (pub-sub pattern)
-
알림 시스템
- 알림 전송 API : 인증된 클라이언트만 알림을 전송한다.
- 알림 검증 : target에 대한 검증을 수행한다.
- DB/Cache query : 알림 데이터에 포함될 데이터를 가져온다.
- 알림 전송 : MQ에 알림 데이터를 넣는다.
-
cache : 알림에 보낼 데이터를 캐싱한다.
-
DB : 알림에 대한 정보를 저장한다.
-
MQ : 시스템 간 의존성을 제거하고 버퍼 역할을 한다.
-
worker server : MQ에서 알림을 꺼내어 발송한다.
-
3rd party service
-
단말
발송 flow
- API를 호출하여 알림 서버로 알림을 보낸다.
- 알림 서버는 사용자 정보, 단말 토큰, 알림 설정 같은 메타데이터를 캐시나 데이터베이스에서 가져온다.
- 알림 서버는 전송할 알림에 맞는 이벤트를 만들어서 해당 이벤트를 위한 큐에 넣는다.
- 작업 서버는 MQ에서 알림 이벤트를 꺼낸다.
- 작업 서버는 알림을 3rd party로 보낸다.
- 3rd party는 사용자 단말로 알림을 전송한다.
상세 설계
안정성
데이터 손실 방지
- 지연이나 순서의 변경은 괜찮지만 소실은 허용되지 않는다.
- 재시도 메커니즘을 구현해야 된다.
- 알림 로그 DB를 유지하여 발송 여부를 저장한다.
알림 중복 전송 방지
- 분산 시스템의 특성상 완벽하게 중복을 제거할 수는 없다.
- 보내야할 알림이 도착하면 그 이벤트를 검사하여 중복 여부를 체크한다. 중복이 아니라면 발송한다.
추가로 필요한 컴포넌트 및 고려사항
알림 템플릿
알림 설정
- 사용자는 알림으로부터 피곤함을 느낄 수 있다.
- 따라서 사용자가 알림을 받을지 설정할 수 있도록 제공해야된다.
전송률 제한
- 알림으로부터 피곤함을 줄이기 위해서 사용자별로 빈도를 제한하는 방법이 있다.
재시도 방법
- 발송이 실패하면 재시도 전용 MQ에 넣고 계속 실패한다면 개발자에게 통지한다.
푸시알림과 보안
- 인증된 클라이언트만 푸시를 보낼수 있도록 한다.
큐 모니터링
- 큐에 쌓이는 알림의 개수를 모니터링함으로서 작업 서버의 scaling을 결정한다.
이벤트 추적
- 알림을 보낸 후에 알림에 대한 metric을 집계하는 것도 중요하다.
수정된 설계안
마무리
참조
알렉스 쉬, 가상 면접 사례로 배우는 대규모 시스템 설계 기초, 인사이트, 2021, 165p-181p