요구사항
기능 요구사항
시스템이 무엇을 해야 하는 지에 대한 요구사항
- 여러 종류의 알림을 제공해야 함
- 알림 종류: 푸시 알림, SMS 메시지, 이메일
- 알림 유형에 따라 템플릿/전송 로직 분리 필요
- 여러 주체(시스템)로부터 알림 요청을 받아야 함
- 클라이언트 애플리케이션 프로그램이 만들 수도 있고, 서버 측에서 스케줄링 할 수도 있음
- 공통 API 제공을 통한 통합 처리
- 사용자가 알림을 받지 않도록 설정하면 더 이상 알림을 보내면 안됨
- 알림 전송 전 사용자 설정 확인 필요
비기능 요구사항
시스템이 어떻게 동작해야 하는지에 대한 요구사항
- 연성 실시간 시스템(soft real-time)으로 동작해야 함
- 가능한 빨리 알림이 전달되어야 하지만, 시스템에 부하가 있을 때 약간의 지연 가능
- 고가용성과 안정성
- 장애가 나도 알림 시스템 사용이 가능하도록 이중화 필요
- 확장성과 유연성 보장
- 신규 알림 채널이 쉽게 추가 가능해야 하며, 기존 서비스 제거가 유연해야 함
개략적 설계안
알림 유형별 지원 방안
iOS 푸시 알림
- 알림 제공자(Provider): 알림 요청을 만들어 애플 푸시 알림 서비스(APNS: Apple Push Notification Service)로 보내는 주체
- APNS: 애플이 제공하는 원격 서비스로 푸시 알림을 iOS 장치로 보내는 역할을 담당함
- iOS 단말: 푸시 알림을 수신하는 사용자 단말
알림 제공자가 알림 요청을 만들 때엔 아래와 같은 데이터가 필요함
- 단말 토큰(device token): 알림 요청을 보내는 데 필요한 고유 식별자
- 페이로드(payload): 알림 내용을 담은 JSON 딕셔너리
{
"app": {
"alert": {
"title": "Notification Title",
"body": "Notification context",
}
}
}
안드로이드 푸시 알림
안드로이드 푸시 알람은 iOS와 유사하지만, APNS 대신 FCM(Firebase Cloud Messaging)을 사용한다는 점만 다름
SMS 메시지
SMS 메시지를 보낼 때는 제3의 사업자의 서비스를 주로 이용하며, 대부분 이용 요금을 내야 함
국내 주요 SMS 발송 서비스
- Naver Cloud SENS(Simple & Easy Notification Service)
- NHN Cloud Notification
- 과거에 NHN 클라우드 서비스 브랜드를 toast라 사용하여 toast sms로 알려져있음
- KT 스마트메시지플러스
- SKT 비즈메시징
- LG U+ 기업메시징
이메일
많은 회사가 상용 이메일 서비스를 이용하며, 그 중 유명한 서비스로는 센드그리드(Sendgrid), 메일침프(Mailchimp) 등이 있음
연락처 정보 수집 절차
알림을 보내려면 모바일 단말 토큰, 전화번호, 이메일 주소 등의 정보가 필요함
위 그림처럼 단말에 앱을 설치하거나 계정 등록하면 사용자 정보를 수집해 데이터베이스에 저장함
이 데이터베이스에 저장할 테이블 구조는 아래와 유사함
iOS 단말 토큰 만료

- iOS는 앱이 삭제되기 전까지는 디바이스 토큰이 만료되지 않음
- 앱이 삭제되면, 알림이 1번 전달되고 not in use 표시가 된채로 410 status code와 함께 반환되어 더이상 사용하지 못하는 토큰임을 알림
안드로이드 단말 토큰 만료

알림 시스템 개략적 설계안
- 메시지 큐를 이용해 시스템 컴포넌트 사이의 강한 결합을 끊음
- 제3자 제공 서비스(Third Party Services)에 장애가 발생했을 때, 다른 알림 서비스에는 영향을 주지 않도록 알림 서버(Notification servers)와 각 작업 서버(Workers) 사이에 큐를 둠
- 알림 서버를 증설하고 자동으로 수평적 규모 확장이 이루어질 수 있도록 데이터베이스와 캐시를 알림 시스템의 주 서버에서 분리함
위 그림의 각각의 요소가 의미하는 바는 아래와 같음
- Service 1 ~ N: 알림 시스템 서버의 API를 통해 알림을 보낼 서비스들
- 알림 서버(Notification servers) 제공 기능
- 알림 전송 API: 사내 서비스 또는 인증된 클라이언트만 이용 가능한 알림 전송 API로, 여러 시스템에서 알림 서비스를 이용할 수 있도록 구조화된 API 제공
- 알림 겅증(validation): 이메일 주소, 전화번호 등 기본적 검증 수행
- 데이터베이스 또는 캐시 질의: 알림에 포함시킬 데이터를 가져오는 기능
- 알림 전송: 알림 데이터를 각 메시지 큐에 넣음
- 캐시(cache): 사용자 정보, 단말 정보, 알림 템플릿 등을 캐시함
- 데이터베이스(DB): 사용자, 알림, 설정 등 다양한 정보 저장
- 메시지 큐(message queue):
- 시스템 컴포넌트 간 의존성 제거하기 위해 사용하며, 다량의 알림 전송을 위한 버퍼 역할
- 제3자 제공 서비스 각각에 대해 큐를 분리하여 특정 서비스 장애가 다른 종류 알림에 영향을 주지 않도록 함
- 작업 서버(workers): 메시지 큐에서 전송할 알림을 꺼내서 제3자 서비스로 전달하는 역할
상세 설계
개략적 설계에서는 기본적인 기능에 대한 설계였으므로, 아래와 같은 내용을 고려하여 설계를 완성함
안정성
데이터 손실 방지(At-least-once 보장)
알림 시스템은 지연이 되더라도, 누락 없이 알림이 전송되는 것이 중요함
- 예: 상품 약관 변경 알림이 누군가에게 누락되었다면?
데이터 손실 방지 방안
- 메시지 저장소 이중화(위 사진)
- 최초 알림 생성 시, 알림 로그를 큐 뿐 아니라 데이터베이스에도 저장해 추후 복원할 수 있도록 함
- DLT(Dead Letter Topic) 도입
- 작업 서버(Workers)에서 큐의 데이터를 소비할 때, 성공적으로 알림 전송을 일정 횟수 이상 실패했을 때 별도 토픽으로 옮겨서 분석 및 재전송할 수 있음
알림 중복 전송 방지(Idempotency)
메시지 큐로 카프카를 사용한다면, 작업 서버(workers)에서 중복 전송 방지 로직을 구현해야 함
- 기본적으로 각 알림별로 유니크한 key로 보내면 같은 key에 대해 여러번 처리되지 않겠지만, 알림 전송은 성공했는데 offset을 commit하지 못하는 상황이 발생하는 등의 오류가 발생하면 같은 메시지를 다시 한 번 처리하게 될 수 있기 때문
알림 중복 전송 방지 방안
- 고유 메시지 ID 기준으로 중복 전송 체크
전송률 제한
제3자 서비스가 받아줄 수 있는 전송률 제한도 따져봐야 하며, 실제 사용자가 한번에 다량의 알림을 받으면 알림 기능 자체를 OFF할 수 있어 전송률 제한을 고려해야 함
추가 고려사항
알림 템플릿
알림 메시지 대부분은 형식이 비슷하므로, 알림 템플릿을 통해 유사한 메시지 전체를 매번 새로 만들지 않도록 할 수 있음
- 어드민을 통해 각 알림 템플릿을 저장하고 실제 알림 전송 요청 서비스에서 알림 API를 호출할 때 필요한 템플릿 ID를 지정하는 식으로 사용할 수 있음
알림 설정
사용자가 알림 허용을 OFF로 했을 때는 알림을 더 이상 전송하지 않도록 할 수 있음
알림 허용 여부 확인 시점
알림을 전송하기 전 알림 서버에서 사용자가 알림 유형을 수신할 대상인지 체크하는 것이 실용적인 방안
왜 서버에서 확인을 할까?
- 트래픽 낭비 방지
- 이미 알림을 OFF한 사용자에게 전송 요청을 하면 제3자 서비스까지 트래픽이 흘러가므로 낭비임
- 비용 절감
- SMS 전송 등은 수수료를 내고 제3자 서비스에 요청하는 것이므로 비용이 발생함
- 사용자 설정 반영
- 앱 자체에 대한 설정을 끄는게 아닌, 특정 설정만 끌 수 있다면 그것을 컨트롤하기 위해서는 서버에서 하는게 유리함
앱에서 알림 권한 상태 변화 시 서버 업데이트 과정
- 사용자가 앱에서 푸시 권한 업데이트
- 클라이언트가 서버에 알림 권한 변경 반영 요청
- 서버는 디바이스 토큰과 알림 권한 값을 업데이트함
모니터링
알림 요청이 오면 큐에 쌓였다가 각각의 작업 서버(Workers)가 소비하는 형태로 알림이 전송됨
이때, 큐에 너무 많은 알림이 쌓이면 알림 전송이 늦어지게 되므로 큐를 모니터링하여 작업 서버(Workers)를 수평 확장 여부를 결정하는 등이 필요할 수 있음
- 메시지 큐가 Kafka라면, 각 토픽별로 consumer group당 LAG을 모니터링할 수 있음
이벤트 추적
알림을 전송할 때 일반적으로 기대하는 바는 매출 성장이므로, 알림 확인율/클릭율/실제 앱 사용으로 이어지는 비율 같은 메트릭을 분석이 필요함
최종 설계안
최종 설계안은 아래와 같으며, 아래 예시는 특정 알림 큐(iOS PN)만 넣어둔 형태로 각 알림 종류별로 큐가 따로따로 생기는 구조임
- 위 설계안을 좀 더 발전시켜보면, 각 알림유형(SMS, 메일, 앱푸시)별로 하나의 제3자 제공 서비스에 연결하지 않고 여러 제3자를 연결하여 특정 제3자가 장애가 발생했을 때 대처할 수 있도록 하면 좋음
- 예) SMS 전송 시 사용할 제3자를 KT와 LG를 넣어두고 기본값은 KT를 사용하고, circuit이 열리면 LG를 사용하는 식으로 로직을 구성해볼 수 있음
- 알림 서버로 알림을 요청할 서비스는 지속적으로 늘어날 수 있으므로, 알림 서버를 수평 확장하는 것도 좋지만 이 경우 비용이 증가하므로 조금 알림이 늦어져도 괜찮은 것이라면 알림 요청 서비스와 알림 서버 사이에 큐를 두어 처리해볼 수도 있을 것 같음
참고 자료
'TECH BOOK' 카테고리의 다른 글
[대규모 시스템 설계 기초] 실험 플랫폼 (0) | 2025.07.05 |
---|---|
[대규모 시스템 설계 기초] 검색어 자동완성 시스템 (0) | 2025.06.22 |
[대규모 시스템 설계 기초] 뉴스 피드 시스템 설계 (0) | 2025.05.31 |