APNs 전송 전에 알림 후보를 거르는 방법
알림 후보, 미발송 규칙, outbox와 APNs 결과를 분리해 추적한 푸시 구조
푸시를 보내려면 APNs 토큰과 함께 사용자 의도, 관심 장소, 알림 종류, quiet hours, 원천 데이터 최신성, 중복 방지와 발송 감사 기록이 필요하다.
한강자리 알림은 한강 나들이에서 실패할 가능성을 줄이는 정보를 골라 보낸다. 발송 후보마다 보낼 조건과 억제할 조건을 함께 평가한다.
푸시는 앱을 열지 않은 사용자에게도 도착한다. 같은 원천 데이터 변화도 관심 장소와 알림 설정에 맞지 않으면 불필요한 알림이 되므로 APNs 전송 전에 발송 규칙을 적용했다.
푸시를 보내기 전에 남길 기록
서버에서는 발송 전후에 남길 기록을 다음처럼 나눈다.
| 영역 | 역할 |
|---|---|
| Identity | 설치 단위 신호를 저장 |
| Subscription | APNs device token과 구독 상태를 따라감 |
| Preference | 공원, 주차장, 알림 종류별 사용자 의도 |
| Notification fact | 원천 데이터에서 나온 알림 후보를 정규화한 사실 |
| Fact claim | 같은 fact를 두 번 다루지 않도록 claim |
| Delivery decision | 보내거나 막은 이유를 기록 |
| Outbox | 실제 알림 발송을 기다리는 durable queue |
| Delivery attempt | 전송 응답과 실패 이력을 기록 |
| Redis index | 빠른 후보 조회를 위한 보조 index |
Postgres에는 기준 기록과 감사 기록을 남긴다. Redis는 후보 조회와 스트림 속도를 돕는다.
후보에서 발송까지 가는 길
sequenceDiagram autonumber participant iOS as iOS 앱 participant API as 푸시 API participant PG as Postgres participant Redis as 선호 인덱스 participant Facts as 알림 fact participant Worker as 푸시 워커 participant APNs as APNs iOS->>API: 구독과 알림 설정 등록 API->>PG: 설치/구독/설정 저장 API->>Redis: 빠른 후보 조회용 인덱스 갱신 Facts->>PG: 정규화한 알림 후보 저장 Worker->>PG: 처리할 후보 선점 Worker->>Redis: 대상 구독 빠르게 찾기 Worker->>PG: 발송 규칙 평가와 결정 기록 Worker->>PG: 바로 보낼 항목을 outbox에 추가 Worker->>APNs: APNs에 전송 APNs-->>Worker: 전송 결과 반환 Worker->>PG: 시도 결과와 후속 조치 기록
delivery decision은 사용자 설정과 후보의 최신성을 평가해 발송 또는 억제 결과를 남긴다. 조건을 통과한 후보만 outbox와 APNs 전송 단계로 넘기고 나머지는 suppression reason과 함께 저장한다.
flowchart TB
Fact["알림 fact"] --> Context["fact 점유와 후보 조회<br/>Redis 우선 · Postgres 대체"]
Context --> Decision{"선호 설정 · 조용한 시간<br/>쿨다운 · 최신성 통과?"}
Decision -->|억제| Suppressed["억제 결정"]
Decision -->|push_now| Delivery["푸시 outbox<br/>APNs 전송 · 시도 기록"]
발송 전에 적용하는 억제 규칙
모든 변화를 알림으로 보내면 같은 사용자가 필요 없는 신호까지 받게 된다. 혼잡도 변화, 즐겨찾기 주차장의 급격한 감소와 관심 공원의 통제 공지는 사용자의 설정에 따라 서로 다른 발송 규칙을 적용한다.
내부 fact type은 사용자가 선택한 알림 단위로 묶어 표시한다.
- 중요한 변화.
- 주차 실패 방지.
- 관심 공원의 행사와 공지.
- 조용한 시간.
- 반복 알림 cooldown.
- 원천 데이터 최신성에 따른 발송 보류.
오래된 원천 데이터에서 만든 후보는 즉시 발송하지 않는다. 사용자의 이동 결정을 바꿀 수 있는 알림에는 더 엄격한 최신성 기준을 적용한다.
마지막 단계의 APNs 전송
APNs device token 등록 뒤에는 토큰과 구독 상태의 변화를 계속 처리해야 한다.
운영 중에는 다음 상태를 처리해야 한다.
- device token이 갱신되거나 무효화되는 경우.
- 동일 설치가 여러 구독 상태를 거치는 경우.
- 사용자가 권한을 껐다 켜는 경우.
- 발송 실패가 일시적인지 영구적인지 구분하는 경우.
- 같은 알림 후보가 worker 재시작 후 중복 발송되는 경우.
outbox와 delivery attempt는 서로 다른 기록으로 둔다. outbox는 “보내야 할 일”이고 attempt는 “보내려 했던 기록”이다. APNs 응답은 감사 기록과 device token 상태 갱신에 모두 사용된다.
device token 무효, quiet hours 억제, 오래된 원천 데이터와 APNs 일시 실패는 서로 다른 후속 조치가 필요하다. delivery decision과 attempt가 이 이유를 남긴다.
이유를 이해한 뒤의 권한 요청
한강자리는 사용자가 관심 공원이나 주차장과 알림 종류를 고른 뒤 권한을 요청한다. 시스템 팝업 전에는 앱 안에서 알림의 용도와 시점을 설명한다.
알림 설정 UI는 notification_fact_type 대신 사용자가 가려는 공원과 필요한 알림 종류를 보여준다.
발송과 억제를 함께 보는 운영 기록
Postgres에는 사용자 intent, 발송 결정, outbox와 delivery attempt를 남기고 Redis index는 후보 조회에 사용했다. 운영자는 발송 성공률과 suppression reason을 함께 확인해 토큰 정리, 재시도 또는 규칙 조정을 선택할 수 있다.
Comments
아직 댓글이 없습니다. 첫 댓글을 남겨주세요.
검토 대기 중