[Part 7] 개인정보 없이 매주 알림 보내기 (웹 푸시)
TL;DR
- 매주 월요일 오전 10시에 이번 주 TOP 10을 웹 푸시로 알린다. 구독 정보만 저장하고 개인정보는 받지 않는다.
- 끊긴 구독(404·410)은 보낼 때 자동으로 지운다.
- 아이폰은 iOS 16.4 이상 + 홈 화면에 추가한 경우만 된다. 그래서 아이폰에는 버튼 대신 안내 문구를 보여 준다.
문제
프롬피드는 한 번 들어와서 프롬프트 하나 복사하고 나가기 쉬운 사이트다. 다시 올 이유가 필요했다. 매주 순위가 바뀌는 TOP 10이 그 이유가 될 수 있다. 문제는 바뀐 걸 어떻게 알리느냐다.
선택지
| 방법 | 문제 |
|---|---|
| 이메일 뉴스레터 | 이메일 주소를 받아야 한다. 개인정보를 최소로 한다는 원칙과 맞지 않는다 |
| 웹 푸시 | 브라우저가 주는 구독 정보만 있으면 된다. 이름·전화번호·이메일이 필요 없다 |
웹 푸시를 골랐다.
구조
- 방문자가 알림 받기를 누르면, 브라우저가 구독 정보(푸시를 보낼 주소와 암호화 키)를 만든다. 이것만 DB에 저장한다.
- 매주 월요일 10시(한국 시간)에 Vercel Cron이 알림 경로를 부른다.
- 서버는 이번 주 상위 3개 제목으로 알림을 만들어 구독자에게 보낸다. 서버를 인증하는 키는 VAPID 키 쌍이고, 개인 키는 Vercel 환경변수에만 둔다.
- 방문자 브라우저의 서비스 워커가 알림을 받아 띄우고, 누르면 TOP 10 페이지를 연다.
서비스 워커
js
// public/sw.js — 주간 TOP 10 알림만 처리한다 (페이지 캐시는 하지 않음)
self.addEventListener("push", (event) => {
const data = event.data ? event.data.json() : {};
event.waitUntil(
self.registration.showNotification(data.title || "프롬피드", {
body: data.body || "이번 주 TOP 10이 나왔어요",
icon: "/icons/icon-192.png",
data: { url: data.url || "/top" },
}),
);
});
self.addEventListener("notificationclick", (event) => {
event.notification.close();
const url = new URL(event.notification.data?.url || "/top", self.location.origin).href;
// 이미 열린 탭이 있으면 그 탭을 쓰고, 없으면 새로 연다
event.waitUntil(
self.clients.matchAll({ type: "window" }).then((list) => {
const open = list.find((c) => c.url.startsWith(self.location.origin));
return open ? open.navigate(url).then((c) => c && c.focus()) : self.clients.openWindow(url);
}),
);
});서비스 워커는 알림만 처리한다. 페이지 캐시는 하지 않는다.
끊긴 구독은 지운다
알림을 끈 사람이나 브라우저 데이터를 지운 사람의 구독은 더 이상 유효하지 않다. 이런 구독으로 보내면 푸시 서버가 404나 410을 돌려준다. 보낼 때 이 응답을 받은 구독은 바로 지운다. 그래서 구독 목록이 쌓이기만 하지 않는다.
아이폰의 제약
아이폰 사파리의 웹 푸시는 조건이 있다.
- iOS 16.4 이상이어야 한다.
- 사이트를 홈 화면에 추가해서 앱처럼 연 경우에만 된다.
그냥 사파리로 들어온 아이폰 사용자에게 알림 버튼을 보여 주면, 눌러도 아무 일이 안 일어난다. 그래서 이 경우에는 버튼 대신 안내 문구를 보여 준다. 홈 화면에 추가하는 방법은 공지사항에 따로 정리해 뒀다.
결과
- 개인정보 없이 매주 알림을 보낸다. 저장하는 건 구독 정보뿐이다.
- 끊긴 구독은 자동으로 정리된다.
- 아이폰 사용자는 눌러도 안 되는 버튼 대신 방법을 안내받는다.
배운 점
- 다시 오게 만드는 장치에도 개인정보 원칙을 지킬 방법이 있다. 웹 푸시는 이름도 이메일도 필요 없다.
- 플랫폼 제약은 기능을 숨기기보다 왜 안 되는지와 어떻게 하면 되는지를 알려 주는 쪽이 낫다.
프롬피드 개발기
- 개요. SNS에서 유행하는 AI 프롬프트, 빈칸만 채워 바로 쓰게 만들었다
- 1편. 방문자가 늘어도 DB 조회는 그대로다
- 2편. AI 없이 유행 프롬프트 자동 수집기 만들었다
- 3편. 유튜브 API 무료 한도, 10,000번이 아니었다
- 4편. 복사해도 숫자가 안 올라가던 이유
- 5편. 이미지가 깨져 보였던 이유 3가지
- 6편. Lighthouse 모바일 63점을 98점으로 올렸다
- 7편. 개인정보 없이 매주 알림 보내기 (웹 푸시) (지금 읽는 글)
- 8편. 테스트가 깨지면 배포가 안 되게 막았다
- 9편. 프롬피드 회고: 잘한 것과 아쉬운 것
프롬피드: promfeed.solfany.com