10. 알림 시스템 설계
뉴스, 업데이트, 이벤트, 선물 등 고객들에게 주요할 수 있는 정보들을 비동기적으로 제공하기 위해 사용하는 시스템
크게 모바일 푸시 알림, SMS 메시지, 이메일 로 알림 시스템을 분류할 수 있다.
문제 이해 및 설계 범위 확정
하루에 백만 건 이상의 알림을 처리하는 확장성 높은 시스템을 구축하는 건 쉬운 과제가 아니다.
알림 시스템이 어떻게 구현되는 지에 대한 깊은 이해가 필요하고, 모호하게 문제가 주어질 가능성이 높기 때문에 적절한 질문을 통해 요구 사항이 무엇인지 스스로 도출해야 한다.
요구사항
지원하는 알림 종류: 푸시 알림, SMS 메시지, 이메일
연성 실시간 시스템(Soft real-time system)
알림은 가능한 빨리 전달되어야 하지만 시스템에 높은 부하가 걸렸을 때, 약간의 지연은 허용됨
IOS, AOS, Laptop/Desktop 지원
알림을 만드는 생산자는 클라이언트, 서버 스케줄링
사용자는 알림 설정을 통해서 수신 거부를 할 수 있어야 한다.
알림 전송 수
모바일 푸시: 10,000,000 건 이상
SMS 메시지: 1,000,000 건 이상
이메일: 5,000,000 건 이상
개략적 설계안 제시 및 동의 구하기
알림 유형별 지원 방안
IOS 푸시 알림
알림 제공자(Provider)
알림 요청을 만들어 애플 푸시 알림 서비스로 보내는 주체
알림 요청에 필요한 데이터
단말 토큰(device token): 알림 요청을 보내는 데 필요한 고유 식별자
페이로드(payload): 알림 내용을 담은 Json 딕셔너리
애플이 제공하는 원격 서비스
푸시 알림을 IOS 장치로 보낸다.
IOS 단말(Client)
푸시 알림을 수신하는 사용자 단말
AOS 푸시 알림
SMS 메시지
이메일
연락처 정보 수집 절차
앱 설치 후 계정 등록, 구독을 위한 이메일 등록 등으로 데이터를 수집하여 DB에 저장
DB 설계 시 User 테이블에 전화번호, 이메일 등 수신 정보를 저장하고 Device 테이블에 단말 정보를 저장할 수 있도록 구성.
유저는 여러 개의 단말을 가지고 있을 수 있기 때문에 User 테이블은 Device 테이블에 1:N 관계
알림 전송 및 수신 절차
초기 설계안
1부터 N까지 서비스
마이크로서비스(Microservice), 크론잡(Cronjob), 분산 시스템 컴포넌트 등 사용자에게 알림을 보내는 목적의 서비스들
납기일을 알리는 과금 서비스, 배송 알림을 알려주는 쇼핑몰 등
알림 시스템(단일 서버)
알림 전송/수신 처리의 핵심 요소
서비스 1~N에 알림 전송을 위한 API 제공
제 3자 서비스에 전달할 알림 페이로드 생성
제 3자 서비스(Third party services)
사용자들에게 알림을 실제로 전달하는 역할
새로운 알림 서비스를 통합하거나, 기존 서비스들을 제거할 수 있도록 확장성을 고려하여 설계
서비스 별로 사용이 불가능한 경우가 있기 때문에 대체 서비스들을 추가할 수 있도록 설계해야 함
단말기(IOS, AOS, SMS, EMAIL)
초기 설계에서의 문제점
SPOF(Single-Point-Of-Failure)
알림 서비스에 서버가 하나밖에 없다는 것은 그 서버에 장애가 생기면 전체 서비스에 장애로 이어질 수 있다.
규모 확장성
한 대 서비스로 푸시 알림에 관계된 모든 것을 처리하므로, DB나 캐시 등 중요 컴포넌트의 규모를 개별적으로 늘릴 방법이 없다.
성능 병목
알림을 처리하고 보내는 것이 자원을 많이 필요로 하는 작업일 수 있다.
모든 것을 한 서버로 처리하면 사용자 트래픽이 많이 몰리는 시간에는 시스템 과부화 상태에 빠질 수 있다.
개선 포인트
DB 및 캐시를 알림 시스템의 주 서버에서 분리
알림 서버 증설 및 자동으로 수평적 규모 확장이 이루어질 수 있도록 한다. (Auto Scaling)
메시지 큐를 이용해 시스템 컴포넌트 사이의 강한 결합을 끊는다.
개선된 설계안
알림 서버
알림 전송 API
스팸 방지를 위해 사내 서비스 또는 인증된 클라이언트만 이용 가능
알림 검증
이메일 주소, 전화번호 등에 대한 검증 수행
DB or 캐시 질의
알림에 포함시킬 데이터를 가져오는 기능
알림 전송
알림 데이터를 MQ에 넣는다.
하나 이상의 MQ를 사용함으로 알림을 병렬 처리
캐시(Cache)
사용자 정보, 단말 정보, 알림 템플릿 등 캐싱
데이터베이스(Database)
사용자 알림, 설정 등 다양한 정보 저장
메시지 큐(Message Queue)
시스템 컴포넌트 간 의존성을 제거하기 위해서 사용
다량의 알림이 전송되어야 하는 경우를 대비한 버퍼 역할
알림 서버에서는 알림의 종류 별로 메시지 큐(또는 토픽)을 다르게 구성하여 사용
다른 3자 서비스에서 장애가 발생해도 다른 알림 서비스에 영향이 가지 않음
작업 서버(Workers)
메시지 큐에서 전송할 알림을 꺼내서 제 3자 서비스로 전달하는 역할 담당
알림 서버 워크플로
API를 호출하여 알림 서버로 알림 전송
알림 서버는 사용자 정보, 단말 토큰, 알림 설정 같은 메타데이터를 캐시나 DB에서 가져온다.
알림 서버는 전송할 알림에 맞는 이벤트를 만들어서 해당 이벤트를 위한 큐에 넣는다.
작업 서버는 메시지 큐에서 알림 이벤트를 꺼낸다.
작업 서버는 알림을 제 3자 서비소로 보낸다.
제 3자 서비스는 사용자 단말로 알림을 전송한다.
상세 설계
안정성
데이터 손실 방지
알림 시스템의 가장 중요한 요구사항 중 하나는 어떤 상황에서도 알람이 소실되면 안된다.
알람이 지연되거나 순서가 틀려도 상관없지만, 사라지면 상황에 따라 받지 못한 사용자가 확인해야 하는 정보를 놓칠 수 있다.
해당 요구사항을 만족하려면 알림 시스템은 데이터를 DB에 보관하고 재시도 메커니즘을 구현해야 한다.
알림 중복 전송 방지
같은 알림이 여러 번 반복되는 것을 완전히 막는 것은 가능하지 않다.
대부분의 알림은 한 번씩만 전송되겠지만, 분산 시스템 특성상 낮은 빈도로 알림이 중복되어 전송된다.
메시징 정책 중 최소한 한 번씩은 수신자에게 전송을 보장하는 At-least-once 정책으로 인해서, 메시지 유실은 되지 않지만 중복 전송이 될 수 있다.
빈도를 줄이려면 중복을 탐지하는 메커니즘을 도입하고 오류를 신중하게 처리해야 한다.
추가로 필요한 컴포넌트 및 고려사항
알림 템플릿
전달하려는 알림 메시지의 형태는 사용자 별로 크게 다르지 않기 때문에 템플릿으로 구성하여 관리한다.
템플릿의 값을 조정할 수 있도록 파라미터나 추적 링크(Tracking Link)를 추가해서 사용한다.
전송될 알림들의 형식을 일관성있게 유지할 수 있고, 오류 가능성 뿐만 아니라 알림 작성에 드는 시간도 줄일 수 있다.
알림 설정
사용자가 알림을 받을 지에 대한 설정을 상세하게 할 수 있도록 시스템에 구성하고 있다.
알림을 보내기 전에 사용자가 알림을 켜두었는 지를 확인하고 보내야 한다.
전송률 제한
사용자에게 너무 많은 알림을 보내지 않도록 하는 방법 중 하나는, 한 사용자가 받을 수 있는 알림의 빈도를 제한하는 것
너무 많은 알림을 받으면 사용자는 알림을 끄기 때문
재시도 방법
제 3자 서비스가 알림 전송에 실패하면, 해당 알림을 재시도 전용 큐에 넣는다.
같은 문제가 계속해서 발생한다면 이슈 알림 큐 등에 요청하여 개발자가 트러블 슈팅할 수 있도록 한다.
푸시 알림과 보안
알림 전송 API에는 appKey, appSecret 등을 사용하여 인증, 승인된 클라이언트만 해당 API를 사용할 수 있도록 한다.
큐 모니터링
알림 시스템을 모니터링 시 중요한 지표 중 하나는 큐에 쌓인 알림의 개수
큐가 쌓인 메시지의 개수가 많을수록 서버들이 이벤트를 빠르게 처리하고 있지 못하는 상황
서버를 증설 또는 오토스케일링하여 메시지를 처리할 수 있도록 대응
이벤트 추적
알림 확인율, 클릭율, 실제 앱 사용으로 이어지는 비율 같은 메트릭은 사용자를 이해하는데 중요하다.
알림 시스템을 제작하면 데이터 분석 서비스와 통합하여 관리해야 한다.
상세 설계 이후 수정된 설계안
알림 서버에 인증 및 전송률 제한 기능 추가
전송 실패에 대응하기 위한 재시도 기능 추가. 전송에 실패한 알림은 다시 큐에 넣고 지정된 횟수만큼 재시도
전송 탬플릿을 사용하여 알림 생성 과정을 단순화 및 알림 내용의 일관성 유지
모니터링과 추적 시스템을 추가하여 시스템 상태를 확인하고 추후 시스템을 개선하기 쉽도록 함.
Last updated