분류 Nodejs

Firebase Cloud Messaging : Node.js로 토큰 및 알림 처리

컨텐츠 정보

  • 조회 311 (작성일 )

본문

MongoDB로 토큰 저장 및 알림 주제 및 일괄 처리


이 게시물에서 Node.js 프레임 워크에 대해 논의하고 클라이언트로부터받은 토큰을 처리 한 다음 해당 토큰을 사용하여 클라이언트에게 알림을 다시 보내는 방법을 배웁니다. 그러나 이 게시물에서 설명한 설정은 클라이언트와 무관하며 모든 Firebase 클라이언트 (Android, Web 또는 iOS)에 사용할 수 있습니다.


Node.js를 시작하려면 먼저 필요한 종속성을 설치해야 합니다. Express 프레임 워크를 기본 node.js 프레임 워크 및 BodyParser 모듈로 사용하여 게시 요청에서 본문을 구문 분석합니다. MongoDB는 클라이언트 토큰의 기본 데이터 저장소로 사용됩니다. 또한 외부 URL 요청, 가져 오기 또는 게시를 위해 요청 모듈을 사용할 것입니다. 다음 명령은 네 개의 모듈을 모두 설치하고 프로젝트의 package.json에 저장합니다.


https://contextneutral.com/story/firebase-cloud-messaging-handling-tokens-and-notifications-with-nodejs 

sudo npm i express body-parser mongodb request --save

모듈을 올바르게 설치 한 후 express as app 인스턴스를 생성하고 bodyparser 미들웨어를 추가해야 합니다. 아래의 예는 그렇게 합니다.


'use strict'
const app = require('express')(),
request = require('request'),
mongo = require('mongodb'),
bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: false
}))
const MongoClient = mongo.MongoClient
const url = 'mongodb://localhost:27017/myDatabase'


또한 데이터베이스 (myDatabase)에 연결하기 위해 MongoDB 클라이언트 인스턴스를 만들었습니다. URL을 사용하여 MongoClient에 데이터베이스 위치를 제공합니다. URL의 형식은 매우 간단합니다. 프로토콜 이름 MongoDB (예 : HTTP 또는 RTSP)로 시작하고 그 뒤에 MongoDB 데이터베이스의 위치 주소 및 포트 번호가 옵니다. 데이터베이스 (mongod 데몬)가 동일한 서버 (컴퓨터)에서 실행중인 경우 주소는 localhost 또는 127.0.0.1이어야 합니다. 다른 위치에서 실행 중인 경우 해당 서버의 IP 주소가 주소로 필요합니다. MongoDB가 실행되는 기본 포트 번호는 27017입니다. 다른 포트 번호를 사용하는 경우 해당 포트 번호를 지정해야 합니다. URL의 마지막 부분은 데이터베이스 이름이며,이 경우에는 myDatabase입니다.



app.get('/notifications', (reqres=> {
res.sendFile(__dirname + '/notifcenter.html')
})
app.post('/store', (reqres=> {
MongoClient.connect(url, (errdb=> {
if (err) throw err
else {
db.collection('tokens').insertOne(req.body, (errbody=> {
if (err) throw err
res.sendStatus(200)
})
}
db.close()
})
})


토큰을 보낼 엔드 포인트를 선언합니다. 요청 본문에서 토큰을 가져오고 MongoClient를 사용하여 POST 엔드 포인트 인 store를 추가하여 mymybase의 토큰 컬렉션에 저장합니다. 앞서 선언 한 URL로 데이터베이스에 연결하려고 합니다. 연결되면 connect 메소드는 콜백과 같은 예외 객체뿐만 아니라 데이터베이스 (db)를 필요로합니다. 예외가 발생하지 않으면 collection의 insertOne 메소드를 사용하여 토큰을 tokens 컬렉션에 삽입합니다. 위의 예에서 요청에서 구문 분석 된 포스트 본문 req.body는 토큰 만 포함하므로 삽입 할 데이터로 직접 전달됩니다. 키-값 쌍이 더 있으면 본문에서 토큰 값을 가져온 다음 삽입 데이터로 넣을 수 있습니다.


let tokenValue = req.body.token
let data = { token: tokenValue }

오류 없이 데이터가 삽입되면 상태 코드 200으로 응답 확인을 보내는 콜백을 다시 받습니다. 그 후 데이터베이스를 닫습니다.


이제 토큰 저장을 마쳤습니다. 이제 이 토큰을 사용하여 알림을 보냅니다. 메시지 데이터를 받아들이는“sendNotification”이라는 새로운 함수를 선언하자.


const sendNotifications = (data=> {
const dataString = JSON.stringify(data)
const headers = {
'Authorization': 'key=<your firebase legacy server key>',
'Content-Type': 'application/json',
'Content-Length': dataString.length
}
const options = {
uri: 'https://fcm.googleapis.com/fcm/send',
method: 'POST',
headers: headers,
json: data
}
request(options, function (errresbody) {
if (err) throw err
else console.log(body)
})
}


sendNotifications 함수가 받는 데이터는 순수한 JSON입니다. FCM 끝점으로 보내려면 JSON.stringify (...)를 사용하여 해당 문자열로 변경해야 합니다.


const headers = {
 'Authorization': 'key=<your firebase legacy server key>',
 'Content-Type': 'application/json',
 'Content-Length': dataString.length 
}

데이터 이외의 FCM 엔드 포인트에는 요청 헤더 중 하나로 레거시 서버 키가 필요합니다. Firebase 콘솔> 설정 (오른쪽 상단의 아이콘)> 클라우드 메시징에서 기존 서버 키를 얻을 수 있습니다. 위에서 선언 된 헤더 객체에는 인증 키가 있습니다. 바로 이 키에는 Firebase 콘솔에서 방금 수집 한 서버 키가 있습니다. 그러나 캐치가 있습니다. 인증 키를 처음으로 사용하는 대부분의 사람들은 서버 키에 key =를 포함하는 것을 종종 무시합니다. 하지마! 또한 FCM 서버가 헤더와 키를 구문 분석 할 수 있도록 헤더 오브젝트에 Content-Type 및 Content-Length 헤더를 추가합니다. 두 헤더는 모두 설명이 필요합니다.


FirebaseCloudMessaging-Key323.png 


헤더가 준비되면 요청을 사용하여 헤더 및 메시지 데이터와 함께 POST 요청을 FCM 서버에 전송하고,이를 위해서는 FCM 엔드 포인트 (URI), 헤더, 요청 방법, POST, 물론 JSON (데이터). 이해하는 데 문제가 있으면 fcm3.js로 이동하여 코드를 살펴보십시오. 매우 간단합니다.


const sendToTopics = (msgtitletopicresponse=> {
const data = {
"data": {
"body": msg,
"title": title
}
}
data['to'= '/topics/' + topic
sendNotifications(data)
response.sendStatus(200)
}


기본 알림 전송 기능이 준비되었습니다. 이제 알림 유형을 식별하고 그에 따라 데이터 메시지를 준비해야 합니다. 먼저 주제별 알림으로 시작합니다. 주제 기반 알림은 사용자가 특정 주제를 구독 한 다음 해당 주제에 대해서만 알림을받을 수 있는 도구 인 GCMPubSub와 함께 사용됩니다. 우리는 언젠가 GCMPubSub에 대해 이야기 할 것입니다. 위의 예제 (fcm4.js)는 생성해야 하는 데이터 객체에 대한 세부 정보입니다. 데이터 객체에 명확한 본문과 제목이 포함되어 있음을 알 수 있습니다. 더 많은 데이터를 추가하십시오.


주제 기반 알림과 일반 알림의 유일한 차이점은 대상 독자입니다. 주제 기반 알림은 관심 있는 주제에 대한 키를 기대합니다. 데이터 객체에 주제를 추가했으면 sendNotifications (..)를 호출 한 다음 NotificationCenter에 응답 (상태 코드 200, 확인)을 다시 보냅니다 (잠시 이야기하겠습니다).


주제 기반 알림에는 주제가 필요하지만 일반 알림에는 토큰이 필요합니다. 데이터 객체는 토픽 기반과 동일하지만 토큰 배열을 보유하려면 registration_ids가 필요합니다.



const sendToAll = (msgtitleregIdArrayresponse=> {
const data = {
"data": {
"body": msg,
"title": title
}
}
const folds = regIdArray.length % 1000
for (let i = 0; i < folds; i++) {
let start = i * 1000,
end = (i + 1* 1000
data['registration_ids'= regIdArray.slice(start, end).map((item=> {
return item['token']
})
sendNotifications(data)
}
response.sendStatus(200)
}


토큰 기반 알림을 보내는 데 사용하는 sendToAll (...) 함수는 일반적인 메시지, 제목 및 응답 이외의 regIdArray도 허용합니다. regIdArray는 데이터베이스에 저장 한 모든 토큰 객체의 배열입니다. 힌트는 아래 (fcm6.js)를 참조하십시오. 문자열이 아닌 객체의 배열이므로 객체에서 일반 문자열 배열로 매핑해야 합니다. 이를 위해 Array의 map 메소드를 사용할 것입니다. 위의 예에서 등록 ID (토큰)를 1000의 작은 배열로 일괄 처리하려고 시도했음을 알 수 있습니다. 그 이유는 한 번에 1000 개 이상의 ID에 알림을 보낼 수 없기 때문입니다. 배열의 슬라이스 방법을 사용하여 길이가 1000 인 더 작은 배열을 만듭니다.

data['registration_ids'] = regIdArray.slice(start, end).map((item) => { 
                return item['token'] 
})

다음 코드는 토큰 값의 키가 토큰이라고 가정하여 수행합니다. 1000 개의 등록 ID마다 for 루프가 배치 ID를 일괄 처리하고 매번 sendNotification (...) 함수를 호출합니다. 마지막으로, 확인 응답이 다시 전송됩니다.


app.post('/notify', (reqres=> {
let msg = req.body.message,
title = req.body.title,
type = req.body.type,
topic = req.body.topic
if (type === 'topic') {
sendToTopics(msg, title, topic, res)
else {
MongoClient.connect(url, function (errdb) {
if (err) throw err
else {
db.collection('tokens').find({}).toArray((errdocs=> {
sendToAll(msg, title, docs, res)
})
}
db.close()
})
}
})
app.listen(8000)


이제 알림 유형을 식별 할 차례입니다. 통지 엔드 포인트에서 통지 센터 (알림 메시지가 준비된)에 대해 선언합니다. 아래에 선언 된 HTML 페이지를 보십시오. 두 개의 라디오 버튼이 있습니다. 하나는 sendToAll, 다른 하나는 주제 기반입니다. 또한 주제 기반 단일 선택 단추가 선택된 경우 주제를 선택할 수 있는 선택 (드롭 다운) 메뉴가 있습니다. 양식은 선택에 따라 적절한 데이터를 선택하여 통지 엔드 포인트 (POST)로 보냅니다. 메시지, 제목, 알림 유형 및 가능한 경우 주제가 표시됩니다.


유형이 주제 인 경우 sendToTopics (...)를 호출하여 메시지, 제목, 주제 및 응답 객체를 전달합니다. 그렇지 않으면 MongoClient를 사용하여 데이터베이스에 연결하고 sendToAll (...)을 호출합니다. 전달 된 매개 변수는 하나를 제외하고 동일하게 유지됩니다. 주제는 데이터베이스 호출 (find?)에서 수신 한 토큰 배열로 대체됩니다.


<!DOCTYPE html>
<html>
<head>
<title>Notification Center</title>
<style>
body {
text-aligncenter;
}
h1 {
font-size40px;
font-familyVerdana, Geneva, Tahomasans-serif;
color#444;
}
input[type=text] {
width300px;
margin0 auto;
displayblock;
}
.border {
padding15px;
border-color#7a7a7a;
border-stylesolid;
font-familyVerdana, Geneva, Tahomasans-serif;
border-width2px;
border-radius3px;
}
textarea {
width300px;
margin0 auto;
height200px;
displayblock;
margin-top20px;
}
button {
background#444;
margin-top20px;
colorwhite;
displayblock;
margin20px auto;
}
input[type=radio] {
margin20px 10px;
}
select {
displayblock;
width200px;
displaynone;
margin10px auto;
}
</style>
</head>
<body>
<h1>Notification Center</h1>
<form method="post" action="http://localhost:8000/notify">
<input class="border" type="text" name="title" placeholder="notiification title">
<textarea class="border" name="message" placeholder="message"></textarea>
<input type="radio" name="type" value="all">Send to all
<input type="radio" name="type" value="topic">Send to topic subscribers only
<select class="border" name="topic">
<option value="topic1">Topic 1</option>
<option value="topic2">Topic 2</option>
<option value="topic3">Topic 3</option>
</select>
<button class="border">Send Notification</button>
</form>
<script>
var all = document.getElementsByName('type')[0]
var topic = document.getElementsByName('type')[1]
var select = document.getElementsByTagName('select')[0]
console.log(all, topic, select)
topic.onclick = function () {
select.style.display = 'block'
all.checked = false
}
all.onclick = function () {
select.style.display = 'none'
topic.checked = false
}
</script>
</body>
</html>


하나는 토큰을 저장하고 다른 하나는 주제를 사용하여 알림을 보내는 두 개의 엔드 포인트를 작성했습니다. 또한 HTML, CSS 및 작은 자바 스크립트를 사용하여 알림 본문을 만들고 유형을 선택할 수 있도록 알림 센터 (notifcenter.html)를 만들었습니다. 알림 센터는 '/ 알림'(fcm1.js 참조)에서 요청으로 제공됩니다. 아래 의견에 문제 나 경험을 공유하십시오.