이 튜토리얼에서는 Messenger 경험을 처음으로 빌드하기 위해 알아야 하는 모든 내용을 설명합니다. 시작하기 전에 스타터 프로젝트의 옵션 중 하나를 선택하여 시작하는 데 필요한 코드를 가져온 다음, 시작하기 아래의 단계에 따라 설정을 완료합니다.
완성된 코드를 바로 보고 싶으신가요? 문제없습니다! GitHub에서 포크하면 됩니다.이 빠른 시작을 진행하기 전에 다음 중 하나를 완료하여 필요한 스타터 코드를 준비하세요. 스타터 코드는 Messenger 경험의 기반으로 사용할 기본 Webhooks를 제공합니다.
Webhooks 설정 가이드에서는 처음부터 끝까지 이 빠른 시작으로 사용할 수 있는 첫 Webhooks를 빌드하는 방법을 단계별로 설명합니다.
Webhooks 빌드하기GitHub에서 Webhooks 스타터 코드를 다운로드하고 원하는 서버에 배포합니다.
코드 다운로드Webhooks를 배포할 서버가 없다면 Glitch에서 스타터 Webhooks 프로젝트를 리믹스할 수 있습니다. 그러면 Webhooks용으로 HTTPS를 통해 서비스되는 공개 URL을 얻게 됩니다.
Glitch에서 자체 Webhooks를 만드는 방법은 다음과 같습니다.
/webhook
를 덧붙인 Glitch URL이 됩니다.
https://
첫 Messenger 경험을 빌드하기 전에 먼저 앱의 자격 증명을 설정합니다.
Messenger 플랫폼에서 사용할 Facebook 앱을 아직 설정하지 않았다면 앱 설정 가이드에 따라 설정합니다.
Messenger에서 공개적으로 사용하기 위해 앱을 제출하고 승인을 받을 때까지 페이지 토큰은 앱에서 관리자, 개발자 또는 테스트 역할이 부여된 Facebook 계정과만 페이지가 상호작용하도록 허용합니다.
다른 Facebook 계정에 이러한 역할을 부여하려면 앱 설정의 '역할' 탭으로 이동합니다.
Messenger 플랫폼 API에 대한 모든 요청은 쿼리 문자열의 access_token
매개변수에 페이지 수준 액세스 토큰을 포함하여 인증됩니다.
Facebook 앱을 설정할 때 페이지 액세스 토큰을 생성하지 않았다면 다음을 수행합니다.
페이지 액세스 토큰과 같은 민감한 정보는 Webhooks에 하드코딩하지 않고 보호하는 것이 좋습니다.
이를 위해서는 다음을 환경 변수에 추가합니다. 여기에서 <PAGE_ACCESS_TOKEN>
은 방금 생성한 액세스 토큰이고 <VERIFY_TOKEN>
은 Webhooks를 인증하기 위해 설정한 무작위 문자열입니다.
PAGE_ACCESS_TOKEN="
Glitch를 사용할 경우 제공된 .env
파일에 있는 환경 변수를 설정하여 다른 Glitch 사용자에게 보이지 않도록 합니다.
이제 페이지 액세스 토큰을 추가하고 Webhooks 로직에 사용할 수 있도록 app.js
파일의 상단에서 토큰을 인증합니다.
const PAGE_ACCESS_TOKEN = process.env.PAGE_ACCESS_TOKEN;
const VERIFY_TOKEN = process.env.VERIFY_TOKEN;
이 튜토리얼에서는 다음과 같은 기능이 있는 간단한 Messenger 경험을 빌드합니다.
수신되는 Webhooks 이벤트에서 메시지와 보내는 사람의 페이지 범위 ID를 파싱합니다.
messages
및 messaging_postbacks
Webhooks 이벤트를 처리합니다.
보내기 API를 통해 메시지를 전송합니다.
문자 메시지로 문자 메시지에 응답합니다.
수신된 이미지를 사용하는 일반 템플릿으로 이미지 첨부 파일에 응답합니다.
Postback 페이로드에 조건부로 응답합니다.
먼저 지원하려는 수신 Webhooks 이벤트 유형을 처리하고 보내기 API를 통해 응답할 함수 3개를 간략히 작성할 것입니다. 이를 위해서는 다음을 app.js
파일에 첨부합니다.
// Handles messages events
function handleMessage(sender_psid, received_message) {
}
// Handles messaging_postbacks events
function handlePostback(sender_psid, received_postback) {
}
// Sends response messages via the Send API
function callSendAPI(sender_psid, response) {
}
Messenger에서 사용자에게 응답하려면 먼저 그 사용자가 누구인지 알아야 합니다. 이를 위해 Messenger에서 수신되는 Webhooks 이벤트로부터 메시지를 보내는 사람의 페이지 범위 ID(PSID)를 받으면 됩니다.
사용자는 대화를 시작하는 각 Facebook 페이지에 대해 고유한 페이지 범위 ID(PSID)를 할당받습니다. PSID는 메시지를 전송할 때 사용자를 식별하는 데 사용됩니다.
위의 스타터 프로젝트 섹션에서 옵션 중 하나를 완료한 경우, POST
요청을 수신하고 다음과 같은 수신된 Webhooks 이벤트 본문을 로깅하는 기본 /webhook
엔드포인트가 생겼을 것입니다.
app.post('/webhook', (req, res) => {
// Parse the request body from the POST
let body = req.body;
// Check the webhook event is from a Page subscription
if (body.object === 'page') {
// Iterate over each entry - there may be multiple if batched
body.entry.forEach(function(entry) {
// Get the webhook event. entry.messaging is an array, but
// will only ever contain one event, so we get index 0
let webhook_event = entry.messaging[0];
console.log(webhook_event);
});
// Return a '200 OK' response to all events
res.status(200).send('EVENT_RECEIVED');
} else {
// Return a '404 Not Found' if event is not from a page subscription
res.sendStatus(404);
}
});
보내는 사람의 PSID를 얻으려면 다음의 코드로 body.entry.forEach
블록을 업데이트하여 이벤트의 sender.id
속성으로부터 PSID를 추출합니다.
body.entry.forEach(function(entry) {
// Gets the body of the webhook event
let webhook_event = entry.messaging[0];
console.log(webhook_event);
// Get the sender PSID
let sender_psid = webhook_event.sender.id;
console.log('Sender PSID: ' + sender_psid);
});
Sender PSID: 1254938275682919
Messenger 경험은 messages
와 messaging_postback
, 이렇게 두 가지 유형의 Webhooks 이벤트를 처리할 수 있어야 합니다. 이벤트 유형의 이름은 이벤트 본문에 포함되지 않지만, 특정 개체 속성을 검사하면 이를 알 수 있습니다.
Messenger 플랫폼은 Webhooks 이벤트를 보내어 Messenger에서 발생하는 행동에 대해 알립니다. 이벤트는 JSON 형식의 POST
요청으로 Webhooks에 전송됩니다. 자세한 내용은 Webhooks 이벤트를 참조하세요.
이를 위해서는 수신된 이벤트에 message
또는 postback
속성이 있는지 검사하는 조건으로 Webhooks의 body.entry.forEach
블록을 업데이트합니다. 또한 앞서 간략히 작성한 handleMessage()
및 handlePostback()
함수에 대한 호출도 추가합니다.
body.entry.forEach(function(entry) {
// Gets the body of the webhook event
let webhook_event = entry.messaging[0];
console.log(webhook_event);
// Get the sender PSID
let sender_psid = webhook_event.sender.id;
console.log('Sender PSID: ' + sender_psid);
// Check if the event is a message or postback and
// pass the event to the appropriate handler function
if (webhook_event.message) {
handleMessage(sender_psid, webhook_event.message);
} else if (webhook_event.postback) {
handlePostback(sender_psid, webhook_event.postback);
}
});
수신되는 메시지가 적절한 핸들러 함수로 라우팅되고 있으므로 이제 handleMessage()
를 업데이트하여 기본 문자 메시지를 처리하고 이에 응답할 것입니다. 이를 위해서는 코드를 업데이트하여 응답의 메시지 페이로드를 정의한 다음, 해당 페이로드를 callSendAPI()
로 전달합니다. 기본 문자 메시지로 응답할 것이므로 "text"
속성으로 JSON 개체를 정의합니다.
function handleMessage(sender_psid, received_message) {
let response;
// Check if the message contains text
if (received_message.text) {
// Create the payload for a basic text message
response = {
"text": `You sent the message: "${received_message.text}". Now send me an image!`
}
}
// Sends the response message
callSendAPI(sender_psid, response);
}
이제 Messenger 플랫폼의 보내기 API로 첫 메시지를 보내보세요!
handleMessage()
에서 callSendAPI()
를 호출하므로 전체 요청 본문을 생성하여 Messenger 플랫폼으로 전송하도록 업데이트해야 합니다. 보내기 API에 대한 요청에는 다음 두 가지 속성이 있습니다.
recipient
: 원하는 메시지 수신인을 설정합니다. 이 경우에는 받는 사람을 PSID로 식별합니다.message
: 전송할 메시지의 상세 정보를 설정합니다. 여기에서는 handleMessage()
함수에서 전달한 메시지 개체로 설정합니다.요청 본문을 생성하려면 callSendAPI()
의 스텁을 다음과 같이 업데이트합니다.
function callSendAPI(sender_psid, response) {
// Construct the message body
let request_body = {
"recipient": {
"id": sender_psid
},
"message": response
}
}
이제 보내기 API에 대한 POST
요청을 https://graph.facebook.com/v2.6/me/messages
에 제출하여 메시지를 전송하면 됩니다.
URL 쿼리 문자열의 access_token
매개변수에 PAGE_ACCESS_TOKEN
을 첨부해야 합니다.
이 빠른 시작에서는 HTTP 요청을 Messenger 플랫폼으로 다시 보내는 데 Node.js 요청 모듈을 사용하지만 원하는 HTTP 클라이언트를 사용하셔도 됩니다.
요청 모듈을 설치하려면 명령줄에서 npm install request --save
를 실행하고 나서, 이를 가져오기 위해 다음을 app.js
상단에 추가합니다.
const request = require('request');
function callSendAPI(sender_psid, response) {
// Construct the message body
let request_body = {
"recipient": {
"id": sender_psid
},
"message": response
}
// Send the HTTP request to the Messenger Platform
request({
"uri": "https://graph.facebook.com/v2.6/me/messages",
"qs": { "access_token": process.env.PAGE_ACCESS_TOKEN },
"method": "POST",
"json": request_body
}, (err, res, body) => {
if (!err) {
console.log('message sent!')
} else {
console.error("Unable to send message:" + err);
}
});
}
응답을 통해 메시지 수신인에게 이미지를 전송하도록 요청했으므로, 다음 단계에서는 첨부 파일을 처리하도록 코드를 업데이트해야 합니다. 전송된 첨부 파일은 Messenger 플랫폼에서 자동으로 저장하고 attachments
배열에서 각 색인의 payload.url
속성에 있는 URL을 통해 제공하므로 이벤트에서 첨부 파일을 추출할 수도 있습니다.
메시지가 첨부 파일인지 확인하려면 handleMessage()
함수에서 조건을 업데이트하여 received_message
에 attachments
가 있는지 검사한 다음, 그에 대한 URL을 추출해야 합니다. 실제 봇에서는 이 배열을 반복하여 여러 첨부 파일을 확인할 수 있으나, 이 빠른 시작에서는 첫 번째 첨부 파일만 가져오겠습니다.
function handleMessage(sender_psid, received_message) {
let response;
// Checks if the message contains text
if (received_message.text) {
// Creates the payload for a basic text message, which
// will be added to the body of our request to the Send API
response = {
"text": `You sent the message: "${received_message.text}". Now send me an attachment!`
}
} else if (received_message.attachments) {
// Gets the URL of the message attachment
let attachment_url = received_message.attachments[0].payload.url;
}
// Sends the response message
callSendAPI(sender_psid, response);
}
이제 일반 템플릿 메시지로 이미지에 응답할 것입니다. 일반 템플릿은 가장 흔히 사용하는 구조화된 메시지 유형으로, 하나의 메시지로 이미지, 텍스트, 버튼을 보낼 수 있습니다.
예! Messenger 플랫폼은 유용한 메시지 템플릿 세트를 제공하는데, 각 메시지 템플릿은 리스트, 영수증, 버튼 등을 포함한 여러 가지의 공통적인 메시지 구조를 지원하도록 설계되어 있습니다. 자세한 내용은 템플릿을 참조하세요.
메시지 템플릿은 type
및 payload
속성을 포함하는 메시지의 attachment
속성에 정의되어 있습니다. payload
에서는 다음의 속성으로 일반 템플릿의 상세 정보를 설정합니다.
template_type
: 메시지에 사용할 템플릿 유형을 설정합니다. 일반 템플릿을 사용하고 있으므로 값은 'generic'입니다.elements
: 템플릿의 맞춤 속성을 설정합니다. 일반 템플릿의 경우 제목, 하위 제목, 이미지, Postback 버튼 2개를 지정합니다.구조화된 메시지의 경우, 템플릿에 표시하도록 image_url
로 전송된 attachment_url
을 사용하고 메시지 수신인이 응답할 수 있도록 2개의 Postback 버튼을 포함합니다. 메시지 페이로드를 생성하고 일반 템플릿을 전송하려면 handleMessage()
를 다음으로 업데이트합니다.
function handleMessage(sender_psid, received_message) {
let response;
// Checks if the message contains text
if (received_message.text) {
// Create the payload for a basic text message, which
// will be added to the body of our request to the Send API
response = {
"text": `You sent the message: "${received_message.text}". Now send me an attachment!`
}
} else if (received_message.attachments) {
// Get the URL of the message attachment
let attachment_url = received_message.attachments[0].payload.url;
response = {
"attachment": {
"type": "template",
"payload": {
"template_type": "generic",
"elements": [{
"title": "Is this the right picture?",
"subtitle": "Tap a button to answer.",
"image_url": attachment_url,
"buttons": [
{
"type": "postback",
"title": "Yes!",
"payload": "yes",
},
{
"type": "postback",
"title": "No!",
"payload": "no",
}
],
}]
}
}
}
}
// Send the response message
callSendAPI(sender_psid, response);
}
마지막 단계는 메시지 수신인이 일반 템플릿의 Postback 버튼 중 하나를 누를 때 전송되는 messaging_postbacks
Webhooks 이벤트를 처리하는 것입니다.
Postback 버튼은 messaging_postbacks
Webhooks 이벤트를 payload
속성에 최대 1,000자의 맞춤 설정 문자열을 포함하는 Webhooks로 전송합니다. 그러므로 파싱하고 특정 동작으로 응답할 수 있는 서로 다른 Postback 페이로드를 손쉽게 구현할 수 있습니다.
일반 템플릿을 통해 메시지 수신인이 두 개의 Postback 버튼 중에서 선택할 수 있으므로, Facebook에서는 Postback 이벤트의 payload
속성값에 기반하여 응답합니다. 이를 위해 handlePostback()
스텁을 다음과 같이 업데이트합니다.
function handlePostback(sender_psid, received_postback) {
let response;
// Get the payload for the postback
let payload = received_postback.payload;
// Set the response based on the postback payload
if (payload === 'yes') {
response = { "text": "Thanks!" }
} else if (payload === 'no') {
response = { "text": "Oops, try sending another image." }
}
// Send the message to acknowledge the postback
callSendAPI(sender_psid, response);
}