- 고객에게 중요할 만한 정보를 비동기적으로 제공하는 기능
- 모바일 푸시 알림, SMS 메시지, 이메일 세 가지로 분류할 수 있다.
문제 이해 및 설계 범위 확정
- 푸쉬 알림, SMS 메시지, 이메일 모두 지원 필요
- 연성 실시간 시스템 (가능한 빨리 필요하나, 약간의 지연은 괜찮음)
- ios, android, 데스크톱을 지원해야함
- 클라이언트 애플리케이션 프로그램 혹은 서버 측의 스케줄링
- 사용자가 알림을 받지 않도록(opt-out) 설정할 수도 있습니다.
- 하루에 천만 건의 모바일 푸시 알림, 백만 건의 SMS 메시지, 500백만 건의 이메일을 보낼 수 있어야 함.
개략적 설계안 제시 및 동의 구하기
알림 유형별 지원 방안
ios 푸시 알림
IOS 푸시 알람을 위해서는 알림 제공자, APNS, iOS 단말, 이렇게 세 가지 컴포넌트가 필요.
- 알림 제공자 (provider) : 알림 요청을 만들어 APNS로 보내는 주체
- 단말 토큰 : 기기 식별자
- 페이로드 : 알림 내용
- APNS : 애플이 제공하는 원격 서비스. 푸시 알림을 iOS로 보내는 역할
- iOS 단말
안드로이드 푸시 알림
APNS 대신 FCM(Firebase Cloud Messaging)을 사용한다는 점만 iOS와 다름.
SMS 메시지
트윌리오, 넥스모 같은 서드파티를 많이 사용.
이메일
메일 침프, 센드그리드 같은 서드파티 많이 사용
정리
연락처 정보 수집 절차
알림을 보내기 위한 사용자 정보가 필요하다. 앱 설치 혹은 계정 등록시 사용자 정보를 수집하여 데이터베이스에 저장한다.
필수 정보를 담은 개략적 테이블 설계안. 이메일 주소와 전화번호는 개인정보 처리방침 작성도 해야한다.
알림 전송 및 수신 절차
개략적 설계안 (초안)
- 서비스: 서비스 각각은 마이크로서비스, 크론잡 어떤 것이든 된다. 납기일 안내, 배송 알림 등
- 알림 시스템: 우선 1개 서버만 사용하는 시스템이라고 가정한다. 이 시스템은 알림 전송을 위한 API를 제공해야 하고, 서드파티 전달을 위한 페이로드를 만들 수 있어야 한다.
- 서드파티 : 사용자에게 알림을 실제로 전달한다. 확장성을 고려해야한다. 쉽게 새로운 서비스를 통합하고나 기존 서비스를 제거할 수 있어야 한다.
- iOS, 안드로이드, SMS, 이메일 단말 : 사용자는 자기 단말에서 알림을 수신한다.
개략적 설계안 문제점
- SPOF : 알림 서비스에 서버가 하나밖에 없어서 장애 대응이 불가능하다.
- 규모 확장성 : 한 대 서비스로 DB, 캐시 등 중요 컴포넌트의 규모를 개별적으로 늘릴 수 없다.
- 성능 병목 : 사용자 트래픽이 많ㄷ이 몰리는 시간에는 과부하가 있을 수 있다.
개략적 설계안 (개선된 버전)
- 데이터베이스와 캐시를 알림 시스템의 주 서버에서 분리
- 알림 서버 증설, 규모 확장 가능하도록 구현
- 메시지 큐를 이용해 시스템 컴포넌트 사이의 강한 결합을 끊는다.
알림 서버는 다음과 같은 기능을 제공한다.
- 알림 전송 API: 스팸 방지를 위해 보통 사내 서비스 또는 인증된 클라이언트만 이용 가능하다.
- 알림 검증(validation): 이메일 주소, 전화번호 등에 대한 기본적 검증을 수행한다.
- 데이터베이스 또는 캐시 질의: 알림에 포함시킬 데이터를 가져오는 기능
- 알림 전송: 알림 데이터를 메시지 큐에 넣는다. 본 설계안은 하나 이상의 메시지 큐를 사용하므로 알림을 병렬적으로 처리할 수 있다.
- API를 호출하여 알림 서버로 알림을 보낸다.
- 알림 서버는 사용자 정보, 단말 토큰, 알림 설정 같은 메타데이터(metadata)를 캐시나 데이터베이스에서 가져온다.
- 알림 서버는 전송할 알림에 맞는 이벤트를 만들어서 해당 이벤트를 위한 큐에 넣는다.
- 작업 서버는 메시지 큐에서 알림 이벤트를 꺼낸다.
- 작업 서버는 알림을 서드파티로 보낸다.
- 서드파티는 사용자 단말로 알림을 전송한다.
상세 설계
안정성
데이터 손실 방지
- 알림이 지연되거나 순서가 틀려도 되지만 소실되면 안된다.
- 알림 데이터를 데이터베이스에 보관하고 재시도 메커니즘을 구현해야 한다.
알림 중복 전송 방지
- 같은 알림이 여러 번 반족되는 것을 막는 것은 불가능
- 중복 전송 빈도를 줄이기 위해 중복 탐지 메커니즘을 도입. 오류를 신중하게 처리.
- 간단한 중복 방지 로직
- 보내야 할 알림이 도착하면 이벤트 ID를 검사하여 이전에 본 적이 있는 이벤트인지 살핀다. 중복된 이벤트라면 버리고, 그렇지 않으면 알림을 발송한다.
추가로 필요한 컴포넌트 및 고려사항
알림 템플릿
알림은 대부분 형식이 비슷하다. 이런 유사성을 고려하여 알림 메시지의 모든 부분을 처음부터 만들 필요가 없도록 한다. 알림 인자, 스타일, 추적 링크를 조정하기만 하면 필요한 알림을 만들어 낼 수 있도록 한다. 형식을 일관성 있게 유지할 수 있고, 오류 가능성 및 알림 작성에 드는 시간도 줄일 수 있다.
알림 설정
사용자는 이미 너무 많은 알림을 받고 있어서 쉽게 피곤함을 느낀다. 따라서 많은 서비스에서 사용자가 알림 설정을 상세히 조정할 수 있도록 하고 있다.
user_id bigint
channel varchar 알림이 전송될 채널.푸시, 이메일, SMS 등
opt_in boolean 해당 채널로 알림을 받을 것인지의 여부
전송률 제한
너무 많이 보내면 사용자가 알림 기능을 꺼 버릴 수 있기 때문에 한 사용자가 받을 수 있는 알림의 빈도를 제한한다.
재시도 방법
제 3자 서비스가 알림 전송에 실패하면 해당 알림을 재시도 전용 큐에 넣고 같은 문제가 계속해서 발생하면 개발자에게 통지한다.
푸시 알림과 보안
iOS, 안드로이드 알림 전송 API는 appKey와 appSecret을 사용하여 보안을 유지한다.
큐 모니터링
큐에 쌓인 알림 개수를 모니터링하여 서버 증설을 고려한다.
이벤트 추적
알림 확인율, 클릭율, 실제 앱 사용으로 이어지는 비율 같은 메트릭은 사용자를 이해하는데 중요하다.
수정된 설계안
본 포스트는 알렉스 쉬 저자의 가상 면접 사례로 배우는 대규모 시스템 설계 기초를 기반으로 스터디하며 정리한 내용들입니다.