← 뒤로 가기

FCM 푸시 알림 사용 가이드

앱 빌드부터 푸시 발송까지 완벽 가이드

FCM 설정 사용 방법

1. 앱 빌드

빌드 시 콘솔의 APP_ID와 푸시 서버 설정을 사용합니다. 콘솔 소유자 USER_ID를 웹 브릿지에 전달하지 않습니다.
단계 1-1: Generator에서 앱 정보 확인

1. Generator 관리 페이지 로그인

2. 앱 설정에서 APP_ID(UUID)와 푸시 서버 모드 확인

APP_ID: 22222222-2222-4222-8222-222222222222 APP_NAME: 배달앱
단계 1-2: Android 빌드
Nativify Console에서 Android 빌드 실행 앱 ID: 22222222-2222-4222-8222-222222222222 앱 이름: 배달앱 웹앱 URL: https://delivery.example.com 푸시 기능: 사용
단계 1-3: iOS 빌드
Nativify Console에서 iOS 빌드 실행 앱 ID: 22222222-2222-4222-8222-222222222222 앱 이름: 배달앱 웹앱 URL: https://delivery.example.com 푸시 기능: 사용

2. 토큰 획득과 로그인 사용자 연결

토큰 획득·익명 설치 등록은 로그인과 별개인 준비 단계입니다. 로그인한 사용자를 토큰에 연결하려면 고객 백엔드가 발급한 5분짜리 일회성 등록 증명이 필요합니다. 발송과 사용량 과금은 별도 단계입니다.

공통 등록 함수

최신 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은 브라우저·앱에 넣지 않습니다. 증명·토큰은 로그에 남기거나 재사용하지 않습니다.

프레임워크별 구현

Vanilla JavaScript

login.html 또는 로그인 성공 페이지:

// 고객 서비스의 로그인 성공 후 공통 함수를 호출합니다. async function onLoginSuccess() { if (bridge.isAvailable()) { try { await bindLoggedInPush(bridge); console.log('푸시 알림 등록 완료'); } catch { console.warn('푸시 등록에 실패했습니다. 로그인 상태를 확인해 주세요.'); } } }

Vue.js

export default { methods: { async onLoginSuccess() { // this.$bridge는 최신 WebBridge 인스턴스입니다. if (this.$bridge.isAvailable()) { try { await bindLoggedInPush(this.$bridge); this.$toast.success('푸시 알림이 활성화되었습니다'); } catch { console.warn('푸시 등록에 실패했습니다. 로그인 상태를 확인해 주세요.'); } } } } }

React

// 고객 서비스의 로그인 성공 콜백에서 호출합니다. const onLoginSuccess = async () => { if (bridge.isAvailable()) { try { await bindLoggedInPush(bridge); toast.success('푸시 알림이 활성화되었습니다'); } catch { console.warn('푸시 등록에 실패했습니다. 로그인 상태를 확인해 주세요.'); } } };
기존 registerPushUser(appId, appUserId)만 호출하면 로그인 사용자 연결은 거부됩니다. object target의 registrationProof를 사용하고, 토큰 갱신·증명 만료·등록 실패 시 새 증명을 발급받습니다. 고객 로그인 백엔드가 없는 정적 사이트는 익명 설치 등록만 사용합니다.

3. 푸시 발송하기

3-1. 공지 발송 (전체 사용자)

Generator 관리 페이지 → 푸시 관리 → 공지 발송
앱 선택: [배달 앱] ▼ ━━━━━━━━━━━━━━━━━━━━━━━━━ 제목: 🎉 50% 할인 이벤트! 내용: 오늘만 전 메뉴 반값 특가! 이미지: [파일 선택] event_banner.jpg 링크: https://delivery.example.com/events/50-off 대상: ◉전체 (1,000명) ○ Android만 (600명) ○ iOS만 (400명) ━━━━━━━━━━━━━━━━━━━━━━━━━ 예상 차감: 1크레딧 (1,000건 기준) 현재 크레딧 잔액: 300크레딧 [미리보기] [발송]
발송 버튼 클릭 시 선택한 앱의 모든 사용자에게 푸시가 전송됩니다!

3-2. 개인별 발송 (특정 사용자)

Generator 관리 페이지 → 푸시 관리 → 개인별 발송
앱 선택: [배달 앱] ▼ ━━━━━━━━━━━━━━━━━━━━━━━━━ 수신 회원 ID: customer_001, customer_002, customer_003 또는 [회원 검색 및 선택] 제목: 주문 완료 내용: 주문이 배달 중입니다 ━━━━━━━━━━━━━━━━━━━━━━━━━ 선택된 회원: 3명 [발송]

4. 발송 이력 조회

Generator 관리 페이지 → 푸시 관리 → 발송 이력
필터: [전체 앱 ▼] [지난 7일 ▼] [전체 상태 ▼] ┌─────────────────────────────────┐ │ 2026-01-07 13:30 │ │ [배달 앱] 🎉 50% 할인 이벤트! │ │ 공지 | 성공: 995 / 실패: 5 │ │ [상세] [재발송] │ └─────────────────────────────────┘ ┌─────────────────────────────────┐ │ 2026-01-06 18:20 │ │ [쇼핑몰 앱] 신상품 입고 안내 │ │ 공지 | 성공: 497 / 실패: 3 │ │ [상세] │ └─────────────────────────────────┘ [이전] 1 2 3 4 5 [다음]
[상세] 버튼을 클릭하면 개별 발송 결과를 확인할 수 있습니다.

5. 멀티 앱 관리

앱별 Firebase 프로젝트와 APP_ID를 분리하면 여러 앱을 독립적으로 관리할 수 있습니다.

시나리오 예시

김개발님의 앱 포트폴리오:
  • 앱 1: 배달 앱 (delivery_app_001) - 사용자 1,000명
  • 앱 2: 쇼핑몰 앱 (shopping_app_002) - 사용자 500명
  • 앱 3: 예약앱 (booking_app_003) - 사용자 300명
각 앱마다 별도의 Firebase 프로젝트가 필요합니다!

앱별 푸시 발송

푸시 발송 페이지 상단의 앱 선택 드롭다운에서 원하는 앱을 선택하면, 해당 앱의 사용자들에게만 푸시가 전송됩니다.

6. 크레딧 사용량

항목 차감 기준 예시 확인 위치
푸시 발송 대상 기기 1,000건당 1크레딧 대상 기기 1~1,000개 발송 시 1크레딧 푸시 발송 화면
Android 빌드 15크레딧 100크레딧으로 Android 6회 빌드 화면
iOS 빌드 30크레딧 100크레딧으로 iOS 3회 빌드 화면
네이티브 기능 조건에 따라 +30크레딧 카메라, 위치, 푸시 등 활성화 빌드 앱 생성/빌드 화면
크레딧 잔액 확인: 발송 전에 예상 차감량과 현재 잔액을 확인하세요.

예: 세 앱에 푸시를 나눠 보내는 경우
  • 배달 앱: 1,000명 → 1크레딧
  • 쇼핑몰 앱: 500명 → 1크레딧
  • 예약앱: 300명 → 1크레딧
  • 합계: 3크레딧 차감

7. 문제 해결

Q: 푸시가 도착하지 않아요

확인 사항:
  1. FCM 설정이 올바른지 확인 (Generator → 푸시 관리 → FCM 설정)
  2. 로그인 후 token-bound proof를 발급받아 registerPushUser({ appId, appUserId, registrationProof })로 연결했는지 확인
  3. 디바이스 토큰이 등록되었는지 Supabase 콘솔에서 확인
  4. Firebase Console에서 발송 로그 확인
  5. iOS의 경우 실제 기기에서 테스트 (시뮬레이터는 푸시 미지원)

Q: 다른 앱의 푸시가 같이 도착해요

원인: 앱 빌드 시 APP_ID가 제대로 주입되지 않았을 가능성이 있습니다.

해결:
  1. 빌드 시 --dart-define=APP_ID=xxx 확인
  2. 앱 실행 후 AppConfig.appId 출력하여 확인

Q: 크레딧이 부족하다고 나와요

확인:
  • 푸시 발송 화면의 예상 차감 크레딧 확인
  • 현재 크레딧 잔액 확인
  • 필요시 크레딧 패키지 또는 Top-up 구매

준비 완료!

이제 푸시 알림으로 사용자와 소통할 수 있습니다.

← FCM 설정 가이드 API 문서 보기 →