10장 - 알림 시스템 설계
목표
알림 시스템은 여러 정보들을 고객들에게 비동기적으로 제공한다.
모바일 푸시알림에 한정되지 않고 sms메시지, 이메일의 세 가지로 분류할 수 있다.
이러한 알림 시스템을 설계해보자.
1단계 문제 이해 및 설계 범위 확정
지원자 질문
- 어떤 종류의 알림을 지원?
- 실시간 시스템이여야 하는지?
- 어떤 종류의 단말을 지원?
- 사용자에게 보낼 알림은 누가 만들 수 있는지?
- 사용자가 알림을 받지 않도록 설정할 수 있는지?
- 하루에 몇 건의 알림을 보낼 수 있어야 하는지?
면접관 대답
- 푸시알림, sms 메시지, 이메일
- soft real-time(연성 실시간) 시스템으로 가정, 알림은 가능한 빨리 전달되어야 하지만 시스템에 높은 부하가 걸렸을 때 약간의 지연은 무방
- ios, 안드로이드, 데스크톱 지원
- 클라이언트 애플리케이션 또는 서버측 스케줄링
- 설정을 하면 알림을 받지 않게 설계
- 천만 건의 모바일, 백 만건의 sms, 5백만 건의 이메일을 보낼 수 있어야함
2단계 개략적 설계안 제시 및 동의 구하기
다음과 같은 개략적 설계안을 살펴 볼 것이다.
알림 유형별 지원 방안
ios 푸시 알림
ios에서 푸시 알림을 보내기 위해서는 세가지 컴포넌트가 필요하다
알림 제공자 ➡️ APNS ➡️ ios 단말
- 알림 제공자(provider): 알림 요청을 만들어 APNS로 보내는 주체
- 단말 토큰 : 알림 요청을 보내는데 필요한 고유 식별자
- 페이로드 : 알림 내용을 담은 JSON
- APNS(Apple Push Notification Service) : 애플이 제공하는 원격서비스
푸시 알림을 ios장치로 보내는 역할 - ios 단말 : 알림 수신
안드로이드 푸시 알림
ios와 동일하게 동작하나 APNS 대신 FCM(firebase Cloud Messaging)을 사용한다
sms메시지
제 3 사업자(Twilio, Nexmo)의 서비스를 이용하여 제공
이메일
고유 이메일 서버를 구축할 역량이 있으나, 상용 이메일 서비스(Sendgrid, Mailchimp)등을 사용한다.
➡️ 전송 성공률도 높고, 데이터 분석 서비스도 제공하기 때문

알림 유형 전부를 묶으면 다음과 같다.
연락처 정보 수집 절차
알림을 보내려면 모바일 단말 토큰, 전화번호, 이메일 주소 등의 정보가 필요하다.

앱을 처음으로 등록하면 API 서버는 해당 사용자의 정보를 수집하여 데이터베이스에 저장한다.
-
user 테이블
- user_id
- etc...
-
device 테이블
- id
- user_id
- device_token
user, device테이블을 1대다 형태로 사용하는데 한 사용자가 여러 단말을 가질 수 있고, 알림은 모든 단말에 전송되어야 한다는 점을 고려한 설계이다.
알림 전송 및 수신 절차
개략적인 설계안을 살펴보고, 점차 최적화해 나가보자
개략적 설계안

- 1부터 N까지의 서비스 : 각각 마이크로 서비스 또는 크론잡(시간 기반 잡)일 수도 있고, 분산스템 컴포넌트일 수도 있다.
- 알림 시스템 : 알림 전송/수신 처리의 핵심으로 1~N까지의 서비스에 알림 전송을 위한 API 제공 제 3자 서비스에 전달할 알림 페이로드를 만들어 내야함
- 제 3자 서비스 : 알림을 실제로 전달하는 역할
- 통합을 진행할때 확장성, 새로운 서비스와 통합,제거가 용이하는지 고려
- 다른 시장(중국 시장 등) 사용할 수 있는 서비스인지 확인해야함
이 설계에는 다음과 같은 문제가 있다.
- SPOF : 알림서비스에 서버가 하나로 서비스 장애 쉬움
- 규모 확장성 : 한 대 서비스로 푸시 알림에 관계된 모든 것을 처리하므로, 규모를 늘릴 방법이 없음
- 성능 병목 : 알림을 처리하고 보내는 것은 많은 작업을 필요로 할 수 있다.(HTML을 만들고 제3자의 응답을 기다려야하는 경우) ➡️ 병목시 모든 알림이 처리되지 않는 과부하 상태에 빠질 수 있음
개략적 설계안(개선된 버전)

- 데이터베이스와 캐시를 알림 시스템의 주 서버에서 분리
- 알림 서버를 증설하고 수평적 규모 확장가능하도록
- 메시지 큐를 사용 ➡️ 시스템 컴포넌트의 강한 결합 제거
시스템 컴포넌트 설명
-
알림 서버 : 다음 기능을 제공한다
- 알림 전송 API : 스팸 방지를 위해 보통 사내 서비스 또는 인증된 클라이언트만 이용가능하다
- 알림 검증 : 이메일 주소, 전화번호 등에 대한 기본적인 검증 수행
- 데이터베이스 또는 캐시 질의 : 알림에 포함시킬 데이터를 가져옴
- 알림 전송 : 알림 데이터를 메시지 큐에 넣는다.
➡️ 하나 이상의 메시지 큐를 사용으로 병렬적으로 처리
-
캐시 : 사용자 정보, 단말 정보, 알림 템플릿 등을 캐시한다.
-
데이터베이스 : 사용자, 알림, 설정 등 다양한 정보를 저장
-
메시지 큐 : 시스템 컴포넌트 간 의존성을 제거, 다량의 알림 전송일때 버퍼 역할
-
작업 서버 : 메시지 큐에서 전송할 알림을 꺼내서 제 3자 서비스로 전달
다음과 같은 과정을 거친다.
- API 호출하여 알림 서버로 알림 보냄
- 알림 서버는 메타데이터(사용자 정보, 단말 토큰, 알림 설정)를 캐시나 데이터베이스에서 가져옴
- 알림 서버는 전송할 알림에 맞는 이벤트를 만들어 한 큐에 넣는다.
- 작업 서버는 메시지 큐에서 알림 이벤트를 꺼낸다.
- 작업 서버는 알림을 제3자 서비스로 보낸다.
3단계 상세 설계
- 안정성
- 추가로 필요한 컴포넌트 및 고려 사항
- 개선된 설계안
세가지 내용을 좀더 자세히 알아보자
안정성
데이터 손실 방지
알림 전송 시스템의 가장 중요한 요구사항 중 하나는 어떤 상황에서도 알림이 소실되면 안된다는 것이다.(지연, 순서바뀜은 가능하지만 사라지면 안됨) 이 요구사항을 만족하려면 알림 데이터를 데이터베이스에 보관하고 재시도 메커니즘을 구현해야 한다.

다음과 같이 알림 로그 데이터베이스를 유지하는 것이 한 가지 방법이다.
알림 중복 전송 방지
같은 알림이 여러번 반복되는 것을 완전히 막는 것은 가능하지 않다. 분산 시스템으로 가끔은 중복 전송되기도 한다.
그 빈도를 줄이려면
- 중복을 탐지하는 메커니즘 도입
- 오류를 신중하게 처리해야함
- 보내야할 알림이 도착, 이벤트ID를 검사하여 이전에 보낸 이벤트인지 확인
추가로 필요한 컴포넌트 및 고려사항
알림 템플릿
대형 알림 시스템은 많은 알림을 처리한다. 대부분이 형식이 비슷하다.
이러한 유사성을 고려하여 모든 부분을 처음부터 다시 만들 필요가 없도록(템플릿)한다.
오류 가능성이나 알림 작성에 드는 시간도 줄일 수 있다.
알림 설정
여러 서비스는 사용자가 알림 설정을 조정할 수 있도록 하고있다.
이러한 정보는 알림 설정 테이블에 보관되며, 특정 종류의 알림을 보내기 전에 데이터베이스를 확인한 후 보낸다.
전송률 제한
사용자에가 받을 수 있는 알림의 빈도를 제한하여 너무 많은 알림을 보내지 않도록한다.
재시도 방법
제3자 서비스가 알림 전송에 실패하면 해당알림을 재시도 전용 큐에 넣는다.
문제가 계속 발생시 개발자에게 통지한다.
푸시 알림과 보안
모바일 푸시 알림의 경우 appKey와 appSecret을 사용하여 보안을 유지한다.
따라서 인증된 혹은 승인된 클라이언트만 알림을 보낼 수 있다.
큐 모니터링
큐에 쌓인 알림의 개수가 모니터링할때 중요한 메트릭(주요사항)이다. 이 수가 너무크면 이벤트를 빠르게 처리하고 있지 못하고있다는 뜻이다.
이벤트 추적

여러 이벤트 들은 사용자를 이해하는데 중요하다.
데이터 분석 서비스를 통해 추적하게될 알림 시스템 이벤트의 사례이다.
수정된 설계안

- 알림 서버에 인증과 전송률 제한 기능이 추가
- 전송 실패 대응을 위한 재시도 기능 추가
- 전송 템플릿을 사용
- 모니터링과 추적 시스템 추가
4단계 마무리
- 안정성 : 실패율을 낮추기 위한 재시도 매커니즘 도입
- 보안 : appKey, appSecret를 이용한 알림을 보안
- 이벤트 추적 및 모니터링
- 사용자 설정 : 사용자가 알림 수신 설정
- 전송률 제한 : 사용자에게 알림을 보내는 빈도를 제한
다음과 같은 컴포넌트 구현 방버과 최적화 기법에 대해 알아보았다.