- 알림 시스템은 많은 프로그램에서 채택하고 있는 기능이다
- 이를 통해 최신 뉴스, 제품 업데이트, 이벤트, 선물 등 고객에게 중요할 만한 정보를 비동기적으로 제공한다
- 알림 시스템은 단순히 모바일 푸시 알림에 한정되지 않는다
- 모바일 푸시 알림, SMS 메시지 그리고 이메일 3가지로 분류할 수 있다
1. 문제 이해 및 설계 범위
- 푸시 알림, SMS 메시지, 이메일을 지원한다
- 연성 실시간(soft real-time) 시스템이라고 가정하며, 알림은 가능한 빨리 전달되어야 하지만 시스템에 높은 부하가 걸렸을 때 약간의 지연은 무방하다
- iOS, Android, laptop/desktop을 지원한다
- 알림은 클라이언트 애플리케이션 프로그램이 만들 수 있고, 서버 측에서 스케줄링을 할 수도 있다
- 사용자는 알림을 받지 않도록 설정할 수 있다
- 1000만 건의 모바일 푸시 알림, 100만 건의 SMS 메시지, 500만 건의 이메일을 보낼 수 있어야 한다
2. 개략적 설계안 제시
알림 유형별 지원 방안
iOS 푸시 알림
- 알림 제공자, 알림 서비스(APNS: Apple Push Notification Service), iOS단말까지 3가지 컴포넌트가 필요하다
- 알림 요청을 만들려면 device token, payload(알림 내용)과 같은 데이터가 필요하다
안드로이드 푸시 알림
- APNS 대신 FCM을 사용한다
SMS 메시지
- Twilio, Nexmo 같은 서드 파티 서비스를 많이 이용한다
- 한국의 경우 카카오톡 알림톡 서비스를 많이 이용한다
- 대부분 상용 서비스라서 이용요금을 내야 한다
이메일
- 많은 회사가 상용 이메일 서비스를 이용한다
- Sendgrid, Mailchimp, AWS SES와 같은 서비스가 있다
- 전송 성공률도 높고, 데이터 분석 서비스(analytics)도 제공한다
연락처 정보 수집 절차
- 알림을 보내려면 모바일 단말 토큰, 전화번호, 이메일 주소 등의 정보가 필요하다
- 앱을 설치하거나 처음으로 계정을 등록하면 API 서버는 해당 사용자의 정보를 수집하여 DB에 저장한다
- 테이블 구조로는 이메일 주소, 전화번호는 user 테이블에 저장하고 단말 토큰은 device 테이블에 저장한다
- 한 사용자가 여러 단말을 가질 수 있고, 알림은 모든 단말에 전송되어야 한다는 점을 고려하여 일대다로 구성한다
알림 전송 및 수신 절차
1부터 N까지의 서비스
- 각각 마이크로서비스, cronjob, 분산 시스템 컴포넌트일 수 있다
- 사용자에게 납기일을 알리는 과금 서비스, 배송 알림을 보내려는 쇼핑몰 웹사이트가 예다
알림 시스템
- 알림 전송/수신 처리의 핵심이다
- 한개 서버만 사용하는 시스템이라고 가정할 때, 서비스 1~N의 알림 전송을 위한 API를 제공해야하고 서드 파티 서비스에 전달할 알림 payload를 만들어 낼 수 있어야 한다
서드 파티 서비스
- 사용자에게 알림을 실제로 전달하는 역할을 한다
- 서드 파티 서비스와의 통합을 진행할 때는 확장성을 고려해야 한다
- 즉, 새로운 서비스를 통합하거나 기존 서비스를 제거할 수 있어야 한다
- 또한, 어떤 서비스는 다른 시장에서는 사용할 수 없을 수도 있다
- 예를 들어, FCM은 중국에서는 사용할 수 없다
⭐️ 위 설계의 문제점
SPOF(Single-Point-Of-Failure)
- 알림 서비스에 서버가 하나밖에 없다는 것은, 그 서버에 장애가 생기면 전체 서비스의 장애로 이어진다는 뜻이다
규모 확장성
- 한 대 서비스로 푸시 알림에 관계된 모든 것을 처리하므로, DB나 캐시 등 중요 컴포넌트의 규모를 개별적으로 늘릴 방법이 없다
성능 병목
- 알림을 처리하고 보내는 것은 자원을 많이 필요로 하는 작업일 수 있다
- 예를 들어, HTML 페이지를 만들고 서드 파티 서비스의 응답을 기다리는 일은 시간이 많이 걸릴 가능성이 있는 작업이다
- 따라서 모든 것을 한 서버로 처리하면 사용자 트래픽이 많이 몰리는 시간에는 시스템이 과부하 상태에 빠질 수 있다
개략적 설계안(개선된 버전)
- 초안의 문제점을 토대로 다음과 같은 방향으로 개선해보자
- DB와 캐시를 알림 시스템의 주 서버에서 분리한다
- 알림 서버를 증설하고 자동으로 Scale-Out이 이루어질 수 있도록 한다
- 메시지 큐를 이용해 시스템 컴포넌트 사이의 강한 결합을 끊는다
알림 서버(Notification Server) 기능
- 알림 전송 API : 스팸 방지를 위해 보통 사내 서비스 또는 인증된 클라이언트만 이용 가능하다
- 알림 검증 : 이메일 주소, 전화번호 등에 대한 기본적 검증을 수행한다
- DB 또는 캐시 쿼리 : 알림에 포함시킬 데이터를 가져오는 기능이다
- 알림 전송 : 알림 데이터를 메시지 큐에 넣는다. 위 설계의 경우 하나 이상의 메시지 큐를 사용하므로 알림을 병렬적으로 처리할 수 있다
캐시(cache)
- 사용자 정보, 단말 정보, 알림 템플릿 등을 캐시한다
DB
- 사용자, 알림, 설정 등 다양한 정보를 저장한다
메시지 큐
- 시스템 컴포넌트 간 의존성을 제거하기 위해 사용한다
- 다량의 알림이 전송되어야 하는 경우를 대비한 버퍼 역할도 한다
- 위 설계에서는 알림의 종류별로 별도 메시지 큐를 사용한다
- 따라서 서드 파티 서비스 가운데 하나에 장애가 발생해도 다른 종류의 알림은 정상 동작하게 된다
작업 서버(Workers)
- 메시지 큐에서 전송한 알림을 꺼내서 서드 파티 서비스로 전달하는 역할을 담당하는 서버다
알림 전송 단계 정리
- API를 호출하여 알림 서버로 알림을 보낸다
- 알림 서버는 사용자 정보, 단말 토큰, 알림 설정과 같은 메타데이터를 캐시나 DB에서 가져온다
- 알림 서버는 전송할 알림에 맞는 이벤트를 만들어서 해당 이벤트를 큐에 넣는다
- 작업 서버는 메시지 큐에서 알림 이벤트를 꺼낸다
- 작업 서버는 알림을 서드 파티 서비스로 보낸다
- 서드 파티 서비스는 사용자 단말로 알림을 전송한다
- 상세 설계는 다음 포스팅에서 작성하겠다