개요문제 이해 및 설계 범위 확정개략적 설계안 제시 및 동의 구하기알림 유형별 지원 방안iOS 푸시 알림안드로이드 푸시 알림SMS 메시지이메일연락처 정보 수집 절차알림 전송 및 수신 절차개략적 설계안설계의 문제점개략절 설계안(개선된 버전)컴포넌트별 설명알림 전송 순서상세 설계안정성데이터 손실 방지알림 중복 전송 방지추가로 필요한 컴포넌트 및 고려사항알림 템플릿알림 설정전송률 제한재시도 방법푸시 알림과 보안큐 모니터링이벤트 추적개선된 설계안마무리참고문헌
개요
- 이 기능을 갖춘 애플리케이션 프로그램은 최신 뉴스, 제품 업데이트, 이벤트, 선물 등 고객에게 중요할 만한 정보를 비동기적으로 제공한다.
- 알림 시스템은 단순히 모바일 푸시 알림에 한정되지 않는다. 사실 알림 시스템은
모바일 푸시 알림
,SMS 메시지
, 그리고이메일
의 세 가지로 분류할 수 있다.
문제 이해 및 설계 범위 확정
하루에 백만 건 이상의 알림을 처리하는 확장성 높은 시스템을 구축하는 게 쉬운 과제는 아니다.
알림 시스템이 어떻게 구현되는 지에 대한 깊은 이해가 필요한 작업임
- 어떤 종류의 알림을 지원해야 하나요?
- 푸시 알림, SMS 메시지, 그리고 이메일
- 실시간 시스템이어야 하나요?
- soft real-time 시스템이라고 가정.알림은 가능한 한 빨리 전달되어야 하지만 시스템에 높은 부하가 걸렸을 때 약간의 지연은 무방
- 어떤 종류의 단말을 지원?
- iOS 단말, 안드로이드 단말, 랩톱/데스크톱 지원
- 사용자에게 보낼 알람은 누가 만들 수 있나요?
- 클라이언트 애플리케이션 프로그램 or 서버 측에서 스케줄링 할 수 있음
- 사용자가 알림을 받지 않도록(opt-out) 설정할 수 있어야 하나요?
- Yes
- 천만 건의 모바일 푸시 알림, 백만 건의 SMS 메시지, 5백만 건의 이메일을 보낼 수 있어야 함
개략적 설계안 제시 및 동의 구하기
알림 유형별 지원 방안
iOS 푸시 알림

- 알림 제공자 : 알람 요청을 만들어 애플 푸시 알림 서비스(Apple Push Notification Service)로 보내는 주체. 알림 요청을 만들려면 다음과 같은 데이터가 필요
- 단말 토큰(device token): 알림 요청을 보내는 데 필요한 고유 식별자
- 페이로드(payload): 알림 내용을 담을 수 있는 JSON 딕셔너리
- APNS : 애플이 제공하는 원격 서비스. 푸시 알림을 iOS 장치로 보내는 역할을 담당
- iOS 단말 : 푸시 알림을 수신하는 사용자 단말
안드로이드 푸시 알림

- APNS 대신 FCM(Firebase Cloud Messaging)을 사용한다는 점만 다름
SMS 메시지

이메일
Sendgrid, Mailchimp 와 같은 유명한 상용 이메일 서비스가 있음. 전송 성공률도 높고 데이터 분석 서비스(analytics)도 제공
연락처 정보 수집 절차
알림을 보내려면 모바일 단말 토큰, 전화번호, 이메일 주소 등의 정보가 필요함.
사용자가 우리 앱을 설치하거나 처음으로 계정을 등록하면 api 서버는 해당 사용자의 정보를 수집하여 데이터베이스에 저장함
알림 전송 및 수신 절차
개략적 설계안

1부터 N까지의 서비스
: 서비스 각각은 마이크로서비스 일수도 있고, 크론잡(cronjob)일 수도 있고, 분산 시스템 컴포넌트 일수도 있다.- 사용자에게 납기일을 알리고자 하는 과금 서비스(billing service), 배송 알림을 보내려는 쇼핑몰 웹사이트 등
알림 시스템
(notification system) : 알림 시스템은 알림 전송/수신 처리의 핵심- 처음엔 1개 서버만 사용하는 시스템이라 가정
- 서비스 1-N 에 알림 전송을 위한 API 제공
- 제3자 서비스에 전달할 알림 Payload 만들어 낼 수 있어야 함
제3자 서비스
: 이 서비스들은 사용자에게 알림을 실제로 전달하는 역할을 함- 제 3자 서비스와의 통합을 진행할 때 유의할 것은 확장성(extensibility)임
- 쉽게 새로운 서비스를 통합하거나 기존 서비스를 제거할 수 있어야 한다는 뜻
- 또 고려해야 할 점은 어떤 서비스는 다른 시장에서는 사용할 수 없을 수도 있다는 것
- FCM은 중국에서는 사용할 수 없다.
- 중국 시장에서는 제이푸시(Jpush), 푸시와이(PushY) 같은 서비스를 사용해야 함
- iOS, 안드로이드, sms ,이메일 단말
설계의 문제점
- SPOF (Single Point of Failure) : 알림 서비스에 서버가 하나밖에 없으면 서버 장애 생기면 전체 서비스에 장애 발생
- 규모 확장성 : 한 대 서비스로 푸시 알림에 관계된 모든 것을 처리하여, 데이터베이스나 캐시 등 중요 컴포넌트의 규모를 개별적으로 늘릴 방법이 없음
- 성능 병목 : 알림을 처리하고 보내는 것은 자원을 많이 필요로 하는 작업일 수 있고, 모든 것을 한 서버로 처리하면 사용자 트래픽이 많이 몰리는 시간에는 시스템 과부하 상태에 빠질 수 있음
개략절 설계안(개선된 버전)

개선점
- 데이터베이스와 캐시를 알림 시스템의 주 서버에서 분리
- 알림 서버를 증설하고 자동으로 수평적 규모 확장이 이루어질 수 있도록 함
- 메시지 큐를 이용해 시스템 컴포넌트 사이의 강한 결합을 끊음
컴포넌트별 설명
- 1부터 N까지의 서비스 : 알림 시스템 서버의 API를 통해 알림을 보낼 서비스들
- 알림 서버(notification server)
- 알림 전송 API : 스팸 방지를 위해 보통 사내 서비스 또는 인증된 클라이언트만 이용 가능
- 알림 검증 : 이메일 주소, 전화번호 등에 대한 기본적 검증을 수행함
- 데이터베이스 또는 캐시 질의 : 알림에 포함시킬 데이터를 가져오는 기능
- 알림 전송 : 알림 데이터를 메시지 큐에 넣음. 위 설계안의 경우 하나 이상의 메시지 큐를 사용하므로 알림을 병렬적으로 처리할 수 있다.
- 캐시 : 사용자 정보, 단말 정보, 알림 템플릿 등 캐시
- DB : 사용자, 알림, 설정 등 다양한 정보 저장
- 메시지 큐 : 시스템 컴포넌트 간 의존성을 제거하기 위해 사용. 다량의 알림이 전송되어야 하는 경우를 대비한 버퍼 역할도 함. 위 설계에서는 제3자 서비스 별로 큐를 사용하기에, 3자 서비스 하나에 장애가 발생해도 다른 알림은 정상동작함
- 작업 서버(workers) : 메시지 큐에서 전송할 알림을 꺼내서 제3자 서비스로 전달하는 역할
알림 전송 순서
- API 호출하여 알림 서버로 알림 전송
- 알림 서버는 사용자 정보, 단말 토큰, 알림 설정 같은 메타데이터를 캐시나 데이터베이스에서 가져옴
- 알림 서버는 전송할 알림에 맞는 이벤트를 만들어서 해당 이벤트를 위한 큐에 넣음. iOS 푸시 알림 이벤트는 iOS 푸시 알림 큐에 넣어야 한다.
- 작업 서버는 메시지 큐에서 알림 이벤트를 꺼낸다.
- 작업 서버는 알림을 제3자 서비스로 보낸다.
- 제 3자 서비스는 사용자 단말로 알림을 전송
상세 설계
안정성
데이터 손실 방지
- 알림 전송 시스템의 가장 중요한 요구사항 가운데 하나는 어떤 상황에서도 알람이 소실되면 안 된다는 것이다.
- 알림이 지연되거나 순서가 틀려도 괜찮지만, 사라지면 곤란하다는 것
- 이 요구사항을 만족하려면 알림 시스템은 알림 데이터를 데이터베이스에 보관하고 재시도 메커니즘을 구현해야 함
- 아래 그림과 같이 알림 로그 데이터베이스를 유지하는 것이 한 가지 방법

알림 중복 전송 방지
- 같은 알림이 여러 번 반복되는 것을 완전히 막는 것은 가능하지 않다.
- 대부분의 경우 알림은 딱 한 번만 전송되겠지만, 분산 시스템의 특성상 가끔은 같은 알림이 중복되어 전송되기도 함
- 그 빈도를 줄이려면 중복을 탐지하는 메커니즘을 도입하고, 오류를 신중하게 처리해야 한다.
- 중복 방지 로직의 사례
- 보내야 할 알림이 도착하면 그 이벤트 ID를 검사하여 이전에 본 적이 있는 이벤트인지 살핀다. 중복된 이벤트라면 버리고, 그렇지 않으면 알림을 발송
추가로 필요한 컴포넌트 및 고려사항
알림 템플릿
알림 템플릿은 인자(parameter)나 스타일, 추적 링크(tracking link)를 조정하기만 하면 사전에 지정한 형식에 맞춰 알림을 만들어 내는 틀
알림 설정
사용자가 알림 설정을 상세히 조정하여, 알람을 받지 않을 수 있게 설정할 수 있다.
이 정보는 알림 설정 테이블에 보관되며 이 테이블에는 아마 다음과 같은 필드가 필요할 것
- user_id bigint
- channel varchar. : 알림이 전송될 채널. 푸시알림, 이메일, SMS 등
- opt_in boolean : 해당 채널로 알림을 받을 것인지의 여부
전송률 제한
사용자에게 너무 많은 알림을 보내지 않도록 하는 한 가지 방법은 한 사용자가 받을 수 있는 알림의 빈도를 제한하는 것
재시도 방법
제3자 서비스가 알림 전송에 실패하면, 해당 알림을 재시도 전용 큐에 넣는다. 같은 문제가 계속해서 발생하면 개발자에게 통지(alert)
푸시 알림과 보안
iOS와 안드로이드 앱의 경우, 알림 전송 api는 appKey와 appSecret을 사용하여 보안을 유지함. 따라서 인증된, 혹은 승인된 클라이언트만 해당 API를 사용하여 알림을 보낼 수 있다.
큐 모니터링
알림 시스템을 모니터링 할 때 중요한 메트릭 하나는 큐에 쌓인 알림의 개수이다.
이 수가 너무 크면 작업 서버들이 이벤트를 빠르게 처리하고 있지 못하다는 뜻. 그런 경우에는 작업 서버를 증설하는게 바람직함
이벤트 추적
알람 확인율, 클릭율, 실제 앱 사용으로 이어지는 비율 같은 메트릭은 사용자를 이해하는 데 중요하다. 데이터 분석 서비스(analytics)는 보통 이벤트 추적기능도 제공함. 따라서 보통 알림 시스템을 만들려면 데이터 분석 서비스와도 통합해야 한다.

개선된 설계안

추가점
- 알림 서버에 Authentication과 rate-limiting 기능이 추가
- 전송 실패에 대응하기 위한 재시도 기능이 추가. 전송에 실패한 알림은 다시 큐에 넣고 지정된 횟수만큼 재시도
- 전송 템플릿을 사용하여 알림 생성 과정을 단순화하고 알림 내용의 일관성을 유지
- 모니터링과 추적 시스템을 추가하여 시스템 상태를 확인하고 추후 시스템을 개선하기 쉽도록 함
마무리
이 장에서는 개략적 설계안과 더불어 각 컴포넌트의 구현 방법과 최적화 기법에 대해 심도 있게 알아보았음. 특히 아래 주제에 집중함
- 안정성 : 메시지 전송 실패율을 낮추기 위해 안정적인 재시도 메커니즘을 도입
- 보안 : 인증된 클라이언트만이 알림을 보낼 수 있도록 appKey와 appSecret 등의 메커니즘 이용
- 이벤트 추적 및 모니터링 : 알림이 만들어진 후 성공적으로 전송되기까지의 과정을 추적하고 시스템 상태를 모니터링하기 위해 알림 전송의 각 단계마다 이벤트 추적, 모니터링할 수 있는 시스템을 통합함
- 사용자 설정 : 사용자가 알림 수신 설정을 조정할 수 있도록 함. 알림을 보내기 전에 반드시 해당 설정을 확인하도록 시스템 설계를 변경함
- 전송율 제한 : 사용자에게 알림을 보내는 빈도를 제한할 수 있도록 함