빠른 시작 튜토리얼

이 튜토리얼에서는 Messenger 경험을 처음으로 빌드하기 위해 알아야 하는 모든 내용을 설명합니다. 시작하기 전에 스타터 프로젝트의 옵션 중 하나를 선택하여 시작하는 데 필요한 코드를 가져온 다음, 시작하기 아래의 단계에 따라 설정을 완료합니다.

완성된 코드를 바로 보고 싶으신가요? 문제없습니다! GitHub에서 포크하면 됩니다.

목차

스타터 프로젝트

이 빠른 시작을 진행하기 전에 다음 중 하나를 완료하여 필요한 스타터 코드를 준비하세요. 스타터 코드는 Messenger 경험의 기반으로 사용할 기본 Webhooks를 제공합니다.

옵션 1: 직접 빌드하기

Webhooks 설정 가이드에서는 처음부터 끝까지 이 빠른 시작으로 사용할 수 있는 첫 Webhooks를 빌드하는 방법을 단계별로 설명합니다.

Webhooks 빌드하기

옵션 2: GitHub에서 다운로드

GitHub에서 Webhooks 스타터 코드를 다운로드하고 원하는 서버에 배포합니다.

코드 다운로드

옵션 3: Glitch에서 리믹스

Webhooks를 배포할 서버가 없다면 Glitch에서 스타터 Webhooks 프로젝트를 리믹스할 수 있습니다. 그러면 Webhooks용으로 HTTPS를 통해 서비스되는 공개 URL을 얻게 됩니다.

Glitch에서 자체 Webhooks를 만드는 방법은 다음과 같습니다.

  1. Glitch에서 스타터 Webhooks 프로젝트를 엽니다. Glitch에서 리믹스
  2. '내 프로젝트 리믹스' 버튼을 클릭합니다. 그러면 프로젝트 사본이 생성됩니다.
  3. 왼쪽 상단 모서리에서 드롭다운 메뉴를 클릭한 다음, 프로젝트 설명 아래의 공개 URL을 복사합니다. 이것이 Webhooks의 기본 URL이 됩니다.
  4. 앱 설정 가이드에 따라 Webhooks가 Facebook 앱을 구독하도록 합니다. Webhooks URL은 /webhook를 덧붙인 Glitch URL이 됩니다.
    https://

시작하기

첫 Messenger 경험을 빌드하기 전에 먼저 앱의 자격 증명을 설정합니다.

1
Facebook 앱 설정

Messenger 플랫폼에서 사용할 Facebook 앱을 아직 설정하지 않았다면 앱 설정 가이드에 따라 설정합니다.

개발 모드의 앱

Messenger에서 공개적으로 사용하기 위해 앱을 제출하고 승인을 받을 때까지 페이지 토큰은 앱에서 관리자, 개발자 또는 테스트 역할이 부여된 Facebook 계정과만 페이지가 상호작용하도록 허용합니다.

다른 Facebook 계정에 이러한 역할을 부여하려면 앱 설정의 '역할' 탭으로 이동합니다.

2
페이지 액세스 토큰 생성

Messenger 플랫폼 API에 대한 모든 요청은 쿼리 문자열의 access_token 매개변수에 페이지 수준 액세스 토큰을 포함하여 인증됩니다.

Facebook 앱을 설정할 때 페이지 액세스 토큰을 생성하지 않았다면 다음을 수행합니다.

  1. 앱의 Messenger 설정에 있는 '토큰 생성' 섹션의 '페이지' 드롭다운에서 토큰을 생성하려는 Facebook 페이지를 선택합니다. 액세스 토큰은 '페이지 액세스 토큰' 필드에 표시됩니다.
  2. '페이지 액세스 토큰' 필드를 클릭하여 토큰을 클립보드에 복사합니다.

생성된 토큰은 이 UI에 저장되지 않습니다. 드롭다운에서 페이지를 선택할 때마다 새 토큰이 생성됩니다. 새 토큰을 생성해도 이전에 생성한 토큰은 계속 작동합니다.
3
페이지 토큰을 환경 변수로 저장

페이지 액세스 토큰과 같은 민감한 정보는 Webhooks에 하드코딩하지 않고 보호하는 것이 좋습니다.

이를 위해서는 다음을 환경 변수에 추가합니다. 여기에서 <PAGE_ACCESS_TOKEN>은 방금 생성한 액세스 토큰이고 <VERIFY_TOKEN>은 Webhooks를 인증하기 위해 설정한 무작위 문자열입니다.

PAGE_ACCESS_TOKEN="

Glitch의 환경 변수

Glitch를 사용할 경우 제공된 .env 파일에 있는 환경 변수를 설정하여 다른 Glitch 사용자에게 보이지 않도록 합니다.

4
페이지를 추가하고 Webhooks에 대해 토큰 인증

이제 페이지 액세스 토큰을 추가하고 Webhooks 로직에 사용할 수 있도록 app.js 파일의 상단에서 토큰을 인증합니다.

const PAGE_ACCESS_TOKEN = process.env.PAGE_ACCESS_TOKEN;
const VERIFY_TOKEN = process.env.VERIFY_TOKEN;

설정 완료

이제 첫 Messenger 경험을 빌드해 보겠습니다!

경험 빌드

이 튜토리얼에서는 다음과 같은 기능이 있는 간단한 Messenger 경험을 빌드합니다.

수신되는 Webhooks 이벤트에서 메시지와 보내는 사람의 페이지 범위 ID를 파싱합니다.

messagesmessaging_postbacks Webhooks 이벤트를 처리합니다.

보내기 API를 통해 메시지를 전송합니다.

문자 메시지로 문자 메시지에 응답합니다.

수신된 이미지를 사용하는 일반 템플릿으로 이미지 첨부 파일에 응답합니다.

Postback 페이로드에 조건부로 응답합니다.


1
간략한 핸들러 함수 작성

먼저 지원하려는 수신 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) {
  
}
2
보내는 사람의 페이지 범위 ID 얻기

Messenger에서 사용자에게 응답하려면 먼저 그 사용자가 누구인지 알아야 합니다. 이를 위해 Messenger에서 수신되는 Webhooks 이벤트로부터 메시지를 보내는 사람의 페이지 범위 ID(PSID)를 받으면 됩니다.

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);

});

테스트해 보세요!


Messenger를 열고 Messenger 경험과 연결된 Facebook 페이지로 메시지를 전송합니다. Messenger에서 응답을 수신하지 않겠지만 Webhooks가 실행되는 콘솔에 로깅된 PSID를 포함한 메시지가 보일 것입니다.
Sender PSID: 1254938275682919
3
Webhooks 이벤트 유형 파싱하기

Messenger 경험은 messagesmessaging_postback, 이렇게 두 가지 유형의 Webhooks 이벤트를 처리할 수 있어야 합니다. 이벤트 유형의 이름은 이벤트 본문에 포함되지 않지만, 특정 개체 속성을 검사하면 이를 알 수 있습니다.

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);
  }
  
});
4
문자 메시지 처리

수신되는 메시지가 적절한 핸들러 함수로 라우팅되고 있으므로 이제 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);    
}
5
보내기 API를 통해 메시지 전송

이제 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 요청 보내기

이 빠른 시작에서는 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);
    }
  }); 
}

테스트해 보세요!

Messenge에서 다른 문자 메시지를 Facebook 페이지로 보냅니다. Messenger 경험에서 보낸 자동화된 답변을 통해 내 메시지가 반향되고 이미지를 전송하라는 요청을 받게 됩니다.
6
첨부 파일 처리

응답을 통해 메시지 수신인에게 이미지를 전송하도록 요청했으므로, 다음 단계에서는 첨부 파일을 처리하도록 코드를 업데이트해야 합니다. 전송된 첨부 파일은 Messenger 플랫폼에서 자동으로 저장하고 attachments 배열에서 각 색인의 payload.url 속성에 있는 URL을 통해 제공하므로 이벤트에서 첨부 파일을 추출할 수도 있습니다.

어떤 첨부 파일 유형을 지원하나요?


Messenger 경험에서는 이미지, 오디오, 동영상, 파일 등 대부분의 자산 유형을 주고받을 수 있습니다. 대화 중에 미디어를 표시하고 심지어 재생도 가능하므로 미디어가 풍부한 경험을 구현할 수 있습니다.

메시지가 첨부 파일인지 확인하려면 handleMessage() 함수에서 조건을 업데이트하여 received_messageattachments가 있는지 검사한 다음, 그에 대한 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);    
}
7
구조화된 메시지 보내기

이제 일반 템플릿 메시지로 이미지에 응답할 것입니다. 일반 템플릿은 가장 흔히 사용하는 구조화된 메시지 유형으로, 하나의 메시지로 이미지, 텍스트, 버튼을 보낼 수 있습니다.

다른 메시지 템플릿을 사용할 수 있나요?


예! Messenger 플랫폼은 유용한 메시지 템플릿 세트를 제공하는데, 각 메시지 템플릿은 리스트, 영수증, 버튼 등을 포함한 여러 가지의 공통적인 메시지 구조를 지원하도록 설계되어 있습니다. 자세한 내용은 템플릿을 참조하세요.

메시지 템플릿은 typepayload 속성을 포함하는 메시지의 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);    
}

테스트해 보세요!

Messenger에서 이미지를 Facebook 페이지로 보냅니다. Messenger 경험은 일반 템플릿으로 응답해야 합니다.
8
Postback 처리

마지막 단계는 메시지 수신인이 일반 템플릿의 Postback 버튼 중 하나를 누를 때 전송되는 messaging_postbacks Webhooks 이벤트를 처리하는 것입니다.

Postback으로 무엇을 할 수 있나요?


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);
}

테스트해 보세요!

Messenger에서 일반 템플릿의 각 Postback 버튼을 누릅니다. 각 버튼에 대해 서로 다른 문자 응답을 받게 됩니다.
9
모든 것이 성공적으로 진행되었다면 첫 Messenger 경험을 빌드하는 과정을 완료한 것입니다!

개발자 지원