단일 서버 구조는 SPOF(단일 장애점)가 되고, 확장도 어렵다. 세 가지로 해결한다.
| 문제 | 개선 |
|---|---|
| DB·캐시가 서버에 묶여 있음 | 분리해서 독립적으로 확장 |
| 서버 한 대에 부하 집중 | 다중화 + 오토스케일링 |
| 컴포넌트 간 강한 결합 | 메시지 큐로 비동기 처리 |

알림 서버
API를 열어 알림 요청을 받는다. 하는 일은 네 가지.
POST /v1/sms/send
{
"to": [{ "user_id": 123456 }],
"from": { "email": "noreply@example.com" },
"subject": "Hello, World!",
"content": [{ "type": "text/plain", "value": "Hello, World!" }]
}
캐시
사용자 정보, 디바이스 토큰, 알림 템플릿처럼 자주 읽히는 데이터를 올려둔다.
DB
사용자, 알림 이력, 알림 설정을 저장한다.
메시지 큐
컴포넌트 간 의존성을 끊고, 트래픽이 몰릴 때 버퍼 역할을 한다.
핵심은 알림 종류별로 큐를 따로 두는 것. iOS 푸시가 죽어도 SMS·이메일은 정상 동작한다.
작업 서버(Worker)
메시지 큐에서 알림을 꺼내 제3자 서비스로 전달한다.
제3자 서비스
APNs, FCM, SMS 게이트웨이, 이메일 발송 서비스 등 실제 전달을 담당.

서비스 → 알림 서버 → (캐시/DB 조회)
→ 종류별 큐 → 작업 서버
→ 제3자 서비스 → 사용자 단말
이제 다음 내용을 좀 더 자세히 알아보자
분산 환경에서 돌아가는 알림 시스템은 다음 두 가지를 반드시 짚고 넘어가야 한다.
알림은 지연되거나 순서가 뒤바뀌어도 괜찮지만, 사라지면 안 된다. 이게 알림 시스템의 가장 중요한 요구사항이다.
이를 보장하려면 두 가지가 필요하다.
작업 서버가 제3자 서비스로 보내다 실패해도, 로그에 남아 있으니 복구할 수 있다.

같은 알림이 두 번 가는 것을 100% 막는 건 불가능하다. 분산 시스템에서는 네트워크 단절이나 재시도 과정에서 중복이 발생할 수밖에 없다.
대신 빈도를 줄이는 방법은 있다.
완벽한 중복 제거가 왜 불가능한지는 exactly-once delivery 문제를 찾아보면 된다.
여기까지가 알림을 보내고 받는 기본 흐름이다. 실제 시스템은 여기에 여러 컴포넌트가 더 붙는다.
대형 시스템은 하루에 수백만 건을 처리하는데, 그 메시지들은 대부분 형식이 같다. 매번 처음부터 만들 이유가 없다.
템플릿은 인자, 스타일, 추적 링크만 바꿔 끼우면 정해진 형식대로 알림을 찍어내는 틀이다.
본문:
찾으시던 [item_name]이 다시 입고되었습니다.
[date]까지 주문 가능합니다.
타이틀(CTA: Call to Action):
지금 [item_name] 주문하기
템플릿을 사용하면..
대부분의 서비스가 채널별로 켜고 끌 수 있게 해준다.
알림 설정 테이블은 대략 이런 모양이다.
user_id bigint
channel varchar -- 푸시, 이메일, SMS 등
opt_in boolean -- 해당 채널 수신 여부
알림을 보내기 전에 반드시 이 설정을 확인하자!
한 사용자가 받을 수 있는 알림 빈도에 상한을 둔다.너무 많이 보내면 사용자가 알림을 통째로 꺼버리기 때문이다.
제3자 서비스 전송이 실패하면 해당 알림을 재시도 전용 큐에 넣는다. 같은 실패가 반복되면 개발자에게 알린다(alert).
iOS·안드로이드 앱의 알림 전송 API는 appKey와 appSecret으로 보호한다. 인증된 클라이언트만 알림을 보낼 수 있다.
가장 중요한 지표는 큐에 쌓인 알림 개수다.
이 수가 계속 늘어난다면 작업 서버가 처리 속도를 못 따라가고 있다는 뜻이다. 이때는 작업 서버를 증설한다.
알림 확인율, 클릭율, 실제 앱 사용으로 이어진 비율 등은 사용자를 이해하는 데 필요한 지표다. 데이터 분석 서비스와 통합해 이런 이벤트를 추적한다.
지금까지의 논의를 모두 반영하면 초기 설계안에 없던 컴포넌트들이 추가된다.

알림 서버
인증(authentication)과 전송률 제한(rate limiting)이 주된 역할로 자리잡았다.
재시도
전송에 실패한 알림은 다시 큐에 넣고 지정된 횟수만큼 재시도한다.
알림 템플릿
전송 템플릿을 사용하여 알림 생성 과정을 단순화하고, 발송되는 내용의 일관성을 유지한다.
모니터링과 이벤트 추적
시스템 상태를 실시간으로 확인하고, 수집한 지표로 이후 개선하기 쉽게 한다.
알림은 사용자에게 중요한 정보를 전달하는 필수 기능이다. 새 콘텐츠 출시 소식, 할인 쿠폰 이메일, 결제 완료 메시지 — 모두 알림 시스템을 통해 나간다.
푸시 알림, SMS, 이메일을 모두 지원하면서 규모 확장이 가능한 알림 시스템을 설계했다. 핵심은 메시지 큐로 컴포넌트 간 결합도를 낮춘 것이다.
상세 설계에서 다룬 것들은 다음과 같다.
| 주제 | 해결 방법 |
|---|---|
| 안정성 | 재시도 메커니즘 + 알림 로그 DB로 전송 실패에 대응 |
| 보안 | appKey, appSecret으로 인증된 클라이언트만 API 사용 |
| 이벤트 추적·모니터링 | 전송 단계마다 이벤트를 남기고 분석 서비스와 통합 |
| 사용자 설정 | 발송 전 사용자의 채널별 수신 설정을 확인 |
| 전송률 제한 | 사용자당 알림 빈도에 상한을 둠 |
제목이 점점 짧아져요