앱 빌드부터 푸시 발송까지 완벽 가이드
1. Generator 관리 페이지 로그인
2. 앱 설정에서 APP_ID(UUID)와 푸시 서버 모드 확인
APP_ID: 22222222-2222-4222-8222-222222222222
APP_NAME: 배달앱
Nativify Console에서 Android 빌드 실행
앱 ID: 22222222-2222-4222-8222-222222222222
앱 이름: 배달앱
웹앱 URL: https://delivery.example.com
푸시 기능: 사용
Nativify Console에서 iOS 빌드 실행
앱 ID: 22222222-2222-4222-8222-222222222222
앱 이름: 배달앱
웹앱 URL: https://delivery.example.com
푸시 기능: 사용
최신 web-bridge.js를 로드하고 아래 함수를 세 프레임워크에서 함께 사용합니다. APP_ID는 예시 UUID를 실제 콘솔 앱 ID로 변경합니다.
const APP_ID = '22222222-2222-4222-8222-222222222222';
const bridge = new WebBridge();
async function bindLoggedInPush(bridge, refreshedToken) {
// 토큰 획득은 사용자 등록을 수행하지 않습니다.
const token = refreshedToken || (await bridge.getFcmToken()).token;
if (!token) throw new Error('푸시 토큰을 가져오지 못했습니다.');
// 고객 서비스가 로그인 세션과 CSRF를 검증하는 endpoint입니다.
const response = await fetch('/my-account/push-proof', {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({ token })
});
if (!response.ok) throw new Error('푸시 등록 증명 발급에 실패했습니다.');
const { appId, appUserId, registrationProof } = await response.json();
if (appId !== APP_ID || !appUserId || !registrationProof) {
throw new Error('푸시 등록 대상이 올바르지 않습니다.');
}
await bridge.registerPushUser({ appId, appUserId, registrationProof });
}
// 토큰이 바뀌면 현재 로그인 세션으로 새 증명을 발급받습니다.
window.addEventListener('pushRegistrationRequired', event => {
if (event.detail.appId !== APP_ID) return;
bindLoggedInPush(bridge, event.detail.token).catch(() => {
console.warn('푸시 연결을 다시 시도해 주세요.');
});
});
/my-account/push-proof와 csrfToken은 고객 서비스에서 구현합니다. 백엔드는 appUserId를 요청값이 아니라 검증된 로그인 세션에서, appId를 서버의 허용 앱 설정에서 결정합니다. 백엔드만 POST /api/notifications/registration-proof에 토큰과 두 ID를 보내고 응답의 appId·appUserId·registrationProof를 전달합니다. nv_ API 키나 설치형 서버 shared secret은 브라우저·앱에 넣지 않습니다. 증명·토큰은 로그에 남기거나 재사용하지 않습니다.
login.html 또는 로그인 성공 페이지:
// 고객 서비스의 로그인 성공 후 공통 함수를 호출합니다.
async function onLoginSuccess() {
if (bridge.isAvailable()) {
try {
await bindLoggedInPush(bridge);
console.log('푸시 알림 등록 완료');
} catch {
console.warn('푸시 등록에 실패했습니다. 로그인 상태를 확인해 주세요.');
}
}
}
export default {
methods: {
async onLoginSuccess() {
// this.$bridge는 최신 WebBridge 인스턴스입니다.
if (this.$bridge.isAvailable()) {
try {
await bindLoggedInPush(this.$bridge);
this.$toast.success('푸시 알림이 활성화되었습니다');
} catch {
console.warn('푸시 등록에 실패했습니다. 로그인 상태를 확인해 주세요.');
}
}
}
}
}
// 고객 서비스의 로그인 성공 콜백에서 호출합니다.
const onLoginSuccess = async () => {
if (bridge.isAvailable()) {
try {
await bindLoggedInPush(bridge);
toast.success('푸시 알림이 활성화되었습니다');
} catch {
console.warn('푸시 등록에 실패했습니다. 로그인 상태를 확인해 주세요.');
}
}
};
registerPushUser(appId, appUserId)만 호출하면 로그인 사용자 연결은 거부됩니다. object target의 registrationProof를 사용하고, 토큰 갱신·증명 만료·등록 실패 시 새 증명을 발급받습니다. 고객 로그인 백엔드가 없는 정적 사이트는 익명 설치 등록만 사용합니다.
앱 선택: [배달 앱] ▼
━━━━━━━━━━━━━━━━━━━━━━━━━
제목: 🎉 50% 할인 이벤트!
내용: 오늘만 전 메뉴 반값 특가!
이미지: [파일 선택] event_banner.jpg
링크: https://delivery.example.com/events/50-off
대상: ◉전체 (1,000명)
○ Android만 (600명)
○ iOS만 (400명)
━━━━━━━━━━━━━━━━━━━━━━━━━
예상 차감: 1크레딧 (1,000건 기준)
현재 크레딧 잔액: 300크레딧
[미리보기] [발송]
앱 선택: [배달 앱] ▼
━━━━━━━━━━━━━━━━━━━━━━━━━
수신 회원 ID:
customer_001, customer_002, customer_003
또는 [회원 검색 및 선택]
제목: 주문 완료
내용: 주문이 배달 중입니다
━━━━━━━━━━━━━━━━━━━━━━━━━
선택된 회원: 3명
[발송]
필터: [전체 앱 ▼] [지난 7일 ▼] [전체 상태 ▼]
┌─────────────────────────────────┐
│ 2026-01-07 13:30 │
│ [배달 앱] 🎉 50% 할인 이벤트! │
│ 공지 | 성공: 995 / 실패: 5 │
│ [상세] [재발송] │
└─────────────────────────────────┘
┌─────────────────────────────────┐
│ 2026-01-06 18:20 │
│ [쇼핑몰 앱] 신상품 입고 안내 │
│ 공지 | 성공: 497 / 실패: 3 │
│ [상세] │
└─────────────────────────────────┘
[이전] 1 2 3 4 5 [다음]
푸시 발송 페이지 상단의 앱 선택 드롭다운에서 원하는 앱을 선택하면, 해당 앱의 사용자들에게만 푸시가 전송됩니다.
| 항목 | 차감 기준 | 예시 | 확인 위치 |
|---|---|---|---|
| 푸시 발송 | 대상 기기 1,000건당 1크레딧 | 대상 기기 1~1,000개 발송 시 1크레딧 | 푸시 발송 화면 |
| Android 빌드 | 15크레딧 | 100크레딧으로 Android 6회 | 빌드 화면 |
| iOS 빌드 | 30크레딧 | 100크레딧으로 iOS 3회 | 빌드 화면 |
| 네이티브 기능 | 조건에 따라 +30크레딧 | 카메라, 위치, 푸시 등 활성화 빌드 | 앱 생성/빌드 화면 |
registerPushUser({ appId, appUserId, registrationProof })로 연결했는지 확인--dart-define=APP_ID=xxx 확인AppConfig.appId 출력하여 확인