가상 면접 사례로 배우는 대규모 시스템 설계 기초 - 10장
10. 알림 시스템 설계
- 최신 뉴스, 제품 업데이트, 이벤트, 선물 등 고객에게 중요할 만한 정보를 비동기적으로 제공
- 모바일 푸시 알림, SMS 메시지, 이메일로 분류
- 문제 이해 및 설계 범위 확정
- 어떤 종류의 알림을 지원해야 하는가?
- 푸시 알림, SMS 메시지, 이메일
- 실시간(Real-Time) 시스템인가?
- 연성 실시간(Soft Real-Time) 시스템이라고 가정
- 알림은 가능한 빨리 전달되어야 하지만, 시스템에 높은 부하가 걸렸을 때 약간의 지연 가능
- 어떤 종류의 단말을 지원해야 하는가?
- iOS, Android, 랩톱, 데스크톱
- 사용자에게 보낼 알림은 누가 만들 수 있는가?
- 클라이언트 애플리케이션 프로그램이나 서버 측 스케줄링
- 사용자가 알림을 받지 않도록(Opt-Out) 설정 할 수 있는가?
- 해당 설정을 마친 사용자는 더 이상 알림을 받지 않음
- 하루에 몇 건의 알림을 보낼 수 있어야 하는가?
- 천만 건의 모바일 푸시 알림, 백만 건의 SMS 메시지, 5백만 건의 이메일
- 어떤 종류의 알림을 지원해야 하는가?
- 개략적 설계안 제시 및 동의 구하기
- 알림 유형별 지원 방안
- iOS 푸시 알림
- 세 가지 컴포넌트 필요
- 알림 제공자(Provider)
- 알림 요청(Notification Request)을 만들어 애플 푸시 알림 서비스(APNS, Apple Push Notification Service)로 보내는 주체
- 알림 요청을 만들려면 다음과 같은 데이터 필요
- 단말 토큰(Device Token) : 알림 요청을 보내는 데 필요한 고유 식별자
- 페이로드(Payload) : 알림 내용을 담은 JSON 딕셔너리
- APNS : 애플이 제공하는 원격 서비스
- iOS 단말 : 푸시 알림을 수신하는 사용자 단말
- 안드로이드 푸시 알림
- 비슷한 절차로 전송되지만 APNS 대신 FCM(Firebase Cloud Messaging)을 사용
- SMS 메시지
- 트윌리오, 넥스모 같은 제 3사업자의 서비스를 많이 이용
- 이메일
- 센드그리드, 메일침프와 같은 상용 이메일 서비스를 이용
- iOS 푸시 알림
- 연락처 정보 수집 절차
- 알림을 보내려면 모바일 단말 토큰, 전화번호, 이메일 주소 등의 정보가 필요
- 사용자가 우리 앱을 설치하거나 처음으로 계정을 등록하면 API 서버는 해당 사용자의 정보를 수집하여 데이터베이스에 저장

- 알림 전송 및 수신 절차
- 개략적 설계안
- 1부터 N까지의 서비스
- 서비스 각각은 마이크로서비스일 수 있고, 크론잡일 수도 있고, 분산 시스템 컴포넌트일 수도 있음
- 알림 시스템
- 알림 시스템은 알림 전송·수신 처리의 핵심
- 제3자 서비스
- 사용자에게 알림을 실제로 전달하는 역할을 함
- 제3자 서비스와의 통합을 진행할 때 유의할 것은 확장성
- 쉽게 새로운 서비스를 통합하거나, 기존 서비스를 제거할 수 있어야 함
- 어떤 서비스는 다른 시장에서는 사용할 수 없을 수도 있음
- iOS, Android, SMS, 이메일 단말
- 사용자는 자기 단말에서 알림을 수신
- 설계의 문제점
- SPOF
- 알림 서비스에 서버가 하나밖에 없다는 것은 그 서버에 장애가 생기면 전체 서비스의 장애로 이어짐
- 규모 확장성
- 한 대 서비스로 푸시 알림에 관계된 모든 것을 처리하므로, 데이터베이스나 캐시 등 중요 컴포넌트의 규모를 개별적으로 늘릴 방법이 없음
- 성능 병목
- 알림을 처리하고 보내는 것은 자원을 많이 필요로 하는 작업일 수 있음
- 따라서 모든 것을 한 서버로 처리하면 사용자 트래픽이 많이 몰리는 시간에 시스템이 과부하 상태에 빠질 수 있음
- SPOF
- 1부터 N까지의 서비스
- 개략적 설계안(개선된 버전)
- 데이터베이스와 캐시를 알림 시스템의 주 서버에서 분리
- 알림 서버를 증설하고 자동으로 수평적 규모 확장이 이루어질 수 있도록 함
- 메시지 큐를 이용해 시스템 컴포넌트 사이의 강한 결합을 끊음

- 1부터 N까지의 서비스 : 알림 시스템 서버의 API를 통해 알림을 보낼 서비스들
- 알림 서버
- 알림 전송 API : 스팸 방지를 위해 보통 사내 서비스 또는 인증된 클라이언트만 이용 가능
- 알림 검증 : 이메일 주소, 전화번호 등에 대한 기본적 검증을 수행
- 데이터베이스 또는 캐시 질의 : 알림에 포함시킬 데이터를 가져오는 기능
- 알림 전송 : 알림 데이터를 메시지 큐에 넣음. 하나 이상의 메시지 큐를 사용하므로 알림을 병렬적으로 처리 할 수 있음
- 캐시 : 사용자 정보, 단말 정보, 알림 템플릿 등을 캐시
- 데이터베이스 : 사용자, 알림, 설정 등 다양한 정보를 저장
- 메시지 큐
- 시스템 컴포넌트 간 의존성을 제거하기 위해 사용
- 다량의 알림이 전송되어야 하는 경우를 대비한 버퍼 역할도 함
- 제 3자 서비스 가운데 하나에 장애가 발생해도 다른 종류의 알림은 정상 동작
- 작업 서버 : 메시지 큐에서 전송할 알림을 꺼내서 제3자 서비스로 전달하는 역할
- 제3자 서비스
- iOS, Android, SMS, 이메일 단말
- 컴포넌트들이 알림을 전송하는 순서
- API를 호출하여 알림 서버로 알림을 보냄
- 알림 서버는 사용자 정보, 단말 토큰, 알림 설정 같은 메타데이터를 캐시나 데이터베이스에서 가져옴
- 알림 서버는 전송할 알림에 맞는 이벤트를 만들어서 해당 이벤트를 위한 큐에 넣음. iOS 푸시 알림 이벤트는 iOS 푸시 알림 큐에 넣어야 함
- 작업 서버는 메시지 큐에서 알림 이벤트를 꺼냄
- 작업 서버는 알림을 제3자 서비스로 보냄
- 제3자 서비스는 사용자 단말로 알림을 전송
- 개략적 설계안
- 알림 유형별 지원 방안
- 상세 설계
- 안정성
- 분산 환경에서 운영될 알림 시스템을 설계할 때는 안정성을 확보하기 위한 사항 몇 가지를 반드시 고려해야 함
- 데이터 손실 방지
- 어떠한 상황에서도 알림이 소실되면 안됨
- 알림이 지연되거나 순서가 틀려도 괜찮지만, 사라지면 곤란함
- 이 요구사항을 만족하려면 알림 시스템은 알림 데이터를 데이터베이스에 보관하고 재시도 메커니즘을 구현해야 함

- 알림 로그 데이터베이스를 유지하는 것이 한 가지 방법
- 알림 중복 전송 방지
- 같은 알림이 여러 번 반복되는 것을 완전히 막는 것은 가능하지 않음
- 빈도를 줄이려면 중복을 탐지하는 메커니즘을 도입하고, 오류를 신중하게 처리해야 함
- 간단한 중복 방지 로직
- 보내야 할 알림이 도착하면 이벤트 ID를 검사하여 이전에 본 적이 있는 이벤트인지 살핌
- 중복된 이벤트라면 버리고, 그렇지 않으면 알림 발송
- 추가로 필요한 컴포넌트 및 고려사항
- 알림 템플릿
- 대형 알림 시스템은 하루에도 수백만 건 이상의 알림을 처리
- 알림 메시지 대부분은 형식이 비슷함
- 이런 유사성을 고려하여 알림 메시지의 모든 부분을 처음부터 다시 만들 필요 없도록 해 줌
- 인자(Parameter)나 스타일, 추적 링크(Tracking Link)를 조정하기만 하면 사전에 지정한 형식에 맞춰 알람을 만들어 내는 틀
- 알림 설정
- 사용자는 너무 많은 알림을 받고 있어서 쉽게 피곤함을 느낌
- 사용자가 알림 설정을 상세히 조정할 수 있도록 하고 있음
- 이 정보는 알림 설정 테이블에 보관
- 전송률 제한
- 사용자에게 너무 많은 알림을 보내지 않도록 하는 한 가지 방법은, 한 사용자가 받을 수 있는 알림의 빈도를 제한하는 것
- 알림을 너무 많이 보내기 시작하면 사용자가 알림 기능을 아예 꺼버릴 수 있음
- 재시도 방법
- 제3자 서비스가 알림 전송에 실패하면 해당 알림을 재시도 전용 큐에 넣음
- 같은 문제가 계속해서 발생하면 개발자에게 통지
- 푸시 알림과 보안
- iOS와 Android 앱의 경우, 알림 전송 API는 appKey와 appSecret을 사용하여 보안을 유지
- 따라서 인증된, 혹은 승인된 클라이언트만 해당 API를 사용하여 알림을 보낼 수 있음
- 큐 모니터링
- 알림 시스템을 모니터링 할 때 중요한 메트릭(Metric) 하나는 큐에 쌓인 알림의 개수
- 이 수가 너무 크면 작업 서버들이 이벤트를 빠르게 처리하고 있지 못하다는 뜻
- 그런 경우에는 작업 서버를 증설하는 것이 바람직
- 이벤트 추적
- 알림 확인율, 클릭율, 실제 앱 사용으로 이어지는 비율 같은 메트릭은 사용자를 이해하는데 중요
- 데이터 분석 서비스는 보통 이벤트 추적 기능도 제공
- 알림 템플릿
- 수정된 설계안
- 알림 서버에 인증과 전송률 제한 기능 추가
- 전송 실패에 대응하기 위한 재시도 기능 추가 → 전송에 실패한 알림은 다시 큐에 넣고 지정된 횟수만큼 재시도
- 전송 템플릿을 사용하여 알림 생성 과정을 단순화하고 알림 내용의 일관성을 유지
- 모니터링과 추적 시스템을 추가하여 시스템 상태를 확인하고 추후 시스템을 개선하기 쉽도록 함
- 안정성
- 마무리
- 심도있게 알아본 내용
- 안정성(Reliability) : 메시지 전송 실패율을 낮추기 위해 안정적인 재시도 메커니즘을 도입
- 보안(Security) : 인증된 클라이언트만이 알림을 보낼 수 있도록 appKey, appSecret 등의 메커니즘을 이용
- 이벤트 추적 및 모니터링 : 알림이 만들어진 후 성공적으로 전송되기까지의 과정을 추적하고 시스템 상태를 모니터링하기 위해 알림 전송의 각 단계마다 이벤트를 추적하고 모니터링할 수 있는 시스템을 통합
- 사용자 설정 : 사용자가 알림 수신 설정을 조정할 수 있도록 함. 따라서 알림을 보내기 전 해당 설정을 확인하도록 시스템 설정을 변경
- 심도있게 알아본 내용