업무 사건과 멱등 키로 intent를 만들고, 채널은 정책이 고릅니다.
알림 시스템
설계
공급자가 요청을 받았다고 사용자가 알림을 본 것은 아닙니다. 동의·현재 시간·채널 실패를 다시 확인하고, 재시도에도 같은 사건이 중복 표시되지 않게 만드는 전달 시스템입니다.
provider accepted, 기기 표시 가능 신호, 사용자 열람은 서로 다른 상태입니다. intent를 정본으로 두고 전송 직전 선호를 다시 확인하며, timeout 재시도에도 같은 알림 카드는 한 번만 보이게 합니다.
누구에게, 어떤 이유로, 언제 보낼지 분리한다
수신자가 같은 메시지를 모든 채널에서 원한다는 가정은 위험합니다. 카테고리와 선호 정책을 먼저 모델링하면 발신 서비스가 공급자·토큰·규제를 직접 알 필요가 없습니다.
동의, 조용한 시간, 언어, frequency cap, suppression을 적용합니다.
APNs/FCM, 이메일, SMS의 속도·실패·자격 증명을 worker로 분리합니다.
accepted, suppressed, provider accepted, failed를 하나의 성공으로 합치지 않습니다.
의도·정책·전달 시도를 다른 수명으로 둔다
outbox는 업무 트랜잭션과 알림 발행의 틈을 줄이고, 채널 worker는 공급자 장애를 서로 격리합니다. 전달은 at-least-once일 수 있으므로 사용자 노출 중복 방지는 별도 데이터 제약으로 다룹니다.
intent_id와 inbox의 고유 제약으로 사용자에게 같은 업무 알림이 여러 번 쌓이지 않게 설계합니다.공급자 수락·기기 표시·사용자 열람을 어떤 상태로 구분할 것인가?
Intent 중심 다단계 배송 사건 + 전송 직전 정책 확인
provider accepted, 가능한 device receipt, opened, inbox read를 별도 상태와 시각으로 기록합니다. 예약·마케팅 알림은 전송 직전에 동의와 조용한 시간을 다시 확인합니다.
선택 이유
- 공급자 성공률을 사용자 도달률로 과장하지 않습니다.
- 기기 오프라인·권한 거부·앱 문제를 공급자 장애와 구분할 수 있습니다.
- timeout 재시도에도 안정된 intent ID로 사용자 중복 노출을 제한합니다.
provider accepted를 delivered로 확정
운영체제 권한·집중 모드·오프라인 상태 때문에 공급자 수락 뒤에도 사용자 화면 표시와 열람은 확인되지 않을 수 있습니다.
감수한 단점
- 채널마다 제공하는 receipt 수준이 달라 공통 상태가 부분적입니다.
- 전송 직전 정책 조회는 지연과 의존성을 추가합니다.
- opened는 알림 품질의 대리 지표일 뿐 사용자 만족을 직접 증명하지 않습니다.
정책 판단과 공급자 수락을 한 단계씩 남긴다
실패 뒤에 무엇을 다시 해야 하는지 알려면 intent, 정책 결정, 채널 attempt, 사용자 상호작용을 별도 상태로 기록해야 합니다.
업무 이벤트와 멱등 키를 API·outbox에 원자적으로 남깁니다.
동의, quiet hours, suppression, cap을 전송 직전에 확인합니다.
endpoint마다 push·email·SMS의 독립 attempt를 예약합니다.
timeout과 영구 실패를 나누고 backoff·jitter·만료를 적용합니다.
provider 수락, 실패, inbox 표시, 읽음 신호를 분리해 저장합니다.
도달률을 높이는 선택은 동의·중복·비용을 함께 바꾼다
채널 fan-out은 도달률을 높이지만 비용과 중복 노출도 함께 늘립니다. 중요한 사건과 마케팅 알림의 정책·queue를 나누고, 최신 동의를 확인할 수 있는 범위에서만 재시도합니다.
| 선택 | 장점 | 제약 | 권장 판단 |
|---|---|---|---|
| Intent + channel worker | 공급자 장애 격리, 재시도·감사 가능 | 상태 모델·운영 구성 증가 | 여러 채널 또는 중요 알림에 기본 구조 |
| enqueue 시 정책 고정 | 낮은 지연, 재현 쉬움 | 나중의 해지·quiet 변경을 놓칠 수 있음 | 즉시성 우선 category만 제한적으로 |
| 전송 직전 재검사 | 현재 동의에 더 가까움 | 예약·cache·순서 복잡도 | 마케팅과 예약 알림의 기본 |
| SMS 자동 fallback | 긴급 도달률 보완 가능 | 단가·중복·동의 위험 | 명시된 severity와 동의가 있을 때만 |
| provider accepted = 성공 | 집계가 단순 | 표시·열람을 과장 | 수락·표시·읽음 지표를 분리 |
여섯 가지 실패를 사용자 영향과 복구 검증으로 다룬다
업무는 완료됐지만 알림 intent가 큐로 가지 않아 사용자에게 아무것도 도착하지 않습니다.
공급자는 수락했지만 worker는 응답을 못 받아 재시도하고, 사용자는 중복을 볼 수 있습니다.
APNs/FCM 오류가 backlog를 늘리고 다른 채널 또는 API 수락을 밀어낼 수 있습니다.
바뀐 기기 토큰·반송 주소에 계속 시도해 비용과 실패율이 커집니다.
사용자가 해지했는데 예약 작업이 오래된 정책을 보고 발송할 수 있습니다.
대량 발송이 보안·거래 알림의 queue와 provider quota를 잠식할 수 있습니다.
보안·관측·비용을 채널 호출 밖에서 관리한다
기기 토큰·이메일·전화번호·메시지 본문을 로그에서 분리하고, APNs·FCM·SMTP 자격 증명은 비밀 저장소에서 최소 권한으로 주입합니다.
intent 수락, policy suppression, provider 수락, queue age, retry, invalid endpoint, inbox dedupe를 stage별로 관측합니다.
SMS·email·push 연동 비용뿐 아니라 재시도, endpoint 보관, 템플릿 렌더링, 분석 로그, 수동 반송 대응까지 채널별로 계산합니다.
답변 구조 보기 5단계
- 알림 종류를 거래·보안·마케팅으로 나누고, 채널별 동의·조용한 시간·fallback 조건을 먼저 확인한다.
- 업무 서비스가 intent와 outbox를 기록하고 큐로 비동기 전달한다는 기본 경로를 설명한다.
- 선호 오케스트레이터와 채널 worker를 분리해 APNs/FCM, 이메일, SMS의 실패와 quota를 격리한다고 말한다.
- at-least-once 전달과 사용자에게 정확히 한 번 보이는 효과의 차이를 설명한다. idempotency key, attempt 이력, inbox unique 제약을 함께 제시한다.
- 공급자 수락·표시·열람을 구분한 지표와, opt-out·토큰 폐기·캠페인 폭주·provider 장애의 복구 검증을 덧붙인다. 이번 선택: 수락·표시 가능 신호·열람을 서로 다른 배송 사건으로 저장한다. 깨지는 신호: accepted를 delivered로 표시하거나 timeout attempt가 무한 재시도된다. 다음 검증: 오프라인·권한 거부·중복 웹훅을 조합해 상태가 과장되지 않는지 확인한다.
배송 완료 알림의 수락·표시 가능 신호·열람을 분리하기
한 delivered 상태 대신 관찰 가능한 사건을 순서대로 답합니다.
- intent와 채널별 attempt를 분리합니다.
- provider accepted와 opened를 같은 성공으로 합치지 않습니다.
- timeout은 결과 불명으로 두고 중복 표시를 제한합니다.
오프라인·권한 거부·중복 콜백을 조합해 상태를 검증합니다.
- accepted와 open의 급격한 차이를 채널별로 관측합니다.
- 오래된 미확정 attempt와 중복 노출률을 추적합니다.
- 전송 직전 opt-out과 quiet hours를 다시 확인합니다.
기술 규격·공식 문서
- Apple Developer — Setting up a remote notification server: APNs provider 서버와 원격 알림 설정.
- Firebase — Firebase Cloud Messaging: FCM 전달 모델과 플랫폼별 문서.
- IETF RFC 5321 — Simple Mail Transfer Protocol: SMTP 전송과 응답 모델.
- IETF RFC 9110 — HTTP Semantics: API·webhook의 HTTP 계약 해석.
채널별 수락·전달 상태를 구체화합니다.
문의·정정
사실 오류·출처 정정은 문의·정정 페이지로 알려 주세요.