[Microsoft Bot Framework] Direct Line REST API 3.0

Direct Line REST API

Microsoft Bot Framework는 Skype, Facebook Messenger, Slack 등의 다양한 Conversation Channel을 지원하고 있고 그 수가 점점 늘어나고 있다. 하지만 내가 만들 모바일 앱에서 Bot 을 만들고 싶으면 어떤 방법이 있을까? Direct Line이라는 REST API를 지원하기 때문에 우리가 잘 알고 있는 프로그래밍 방법으로 쉽게 Bot 과 연결 시킬 수 있다.

즉, 기존에 있는 채널이 아닌 프로그래밍 방식으로 Bot 과 연결 시키고 싶다면 Direct Line API를 사용하면 된다. 실제로 안드로이드 앱에서 Direct Line REST API를 사용하여 Bot에 연결시킨 프로토타입 프로젝트가 Github에 올려져 있다. Ket-bot 프로젝트 코드에서 실제 사용한 예를 볼 수 있다.

microsoft-bot-framework

Bot Connector는 Conversation Channel과 Bot 사이에 존재하는 마이크로소프트가 운영하는 서비스다. 채널은 Bot Connector만 연결해주고 메시지를 주고 받으면 된다. Bot 도 역시 Connector만 보고 메시지를 주고 받는다.

현재 최신버전은 3.0이고 공식 문서에 모든 내용이 나와 있다. 1.1 버전에 비해서 WebSocket을 지원하고 파일 업로드도 지원한다.

API 를 이해한 후 C# 개발자라면 Direct Line Nuget Package를 받아서 활용하면 되고 Swagger file 도 제공하기 때문에 자동으로 클라이언트 코드를 생성해서 빠르게 개발을 할 수 도 있다. 테스트는 REST API이기 때문에  Chrome Postman이나 Fiddler 또는 공식문서 하단에 있는 Swagger를 이용하면 된다.

이 글에서는 (WebSocket이 아닌)HTTP POST로 메시지를 보내고 GET을 Polling해서 응답 메시지를 받는 방법에 대해서 알아보기로 하겠다.

Authentication

인증과정은 Bot Dev Center에서 생성한 Secret 키를 던지고 token을 받아오는 과정이다. 받아온 token은 오고 가는 메시지의 HTTP 헤더에 넣어서 사용한다. Secret 키는 Bot 등록페이지에서 Direct Line 설정 페이지에서 얻을 수 있다.

bot-framework-direct-line-secret

POST로 https://directline.botframework.com/v3/directline/tokens/generate URL에 Authentication이라는 헤더에 “Bearer “를 앞에 붙인 Secret를 보내면 token을 받을 수 있다.

  • URL: /v3/directline/tokens/generate
  • Method: POST
  • Header: Authorization: Bearer {secret key}
  • body : 없음

bot-auth-postman

응답에는 3가지 값이 오는데  우선 이단계에서는 token 만 챙긴다. token은  expires_in 시간이 지나면 무효가 되는데 기본값이 1800초/30분이다. 즉 30분이내에 Refresh 시켜줘야 한다. Refresh 방법은 /v3/directline/tokens/refresh 주소로 POST 전송을 보낼때 헤더에 기존 token을 보내면 된다. 상세 내용은 Refresh a token 참조

대화시작

다음 단계는 클라이언트에서 대화를 시작해야 한다.  Auth에서 받은 token을 헤더에 Authentication이라는 헤더로 전달하고 /v3/directline/conversations 주소로 Post Request를 보내면 Auth에서 받은 같은 conversationId 와 새로운 token, streamUrl을 받아온다. 여기서 streamUrl은 웹소켓 URL이다. 이 웹소켓 URL 역시 만료 시간이 있다. 만약 처음 시작한 대화라면 HTTP 201(Created) 응답을 주고 기존 대화라면 200 응답을 준다.

  • URL: /v3/directline/conversations
  • Method: POST
  • Header: Authorization: Bearer {token}
  • body : 없음

bot-start-coversation

{
  "conversationId": "JSfqQrtzCDn",
  "token": "w9KOqddWUuI.dAA.SgBTAGYAcQBRAHIAdB6AEMARABuAA.sWs_TZNM0gE.oSafVPS2hlU.m2kVr6Zjio_d-Am5cADqbLXHRMB93keAx6_pc7XxPao",
  "expires_in": 1800,
  "streamUrl": "wss://directline.botframework.com/v3/directline/conversations/JSfqQrtzCDn/stream?watermark=-&t=w9KOqddWUuI.dAA.SgBTAGYAcQBRAHIAdAB6AEMARABuAA.sX0gQI9M0gE.jEunMa5gKi8.G6GvGGSy6TPSOav8SoNyaJDbIHaCuBrB6hBRRVsoqg8"
}

메시지(Activity) 보내기

메시지라고 하지 않고 Activity라는 표현을 쓴다. 그 이유는 단순 텍스트 메시지를 보내는 것 외에도 몇가지 타입이 더 있기 때문이다. 메시지를 보내면 응답코드로 상태를 알려주는데 4xx, 5xx 는 오류를 나타내며 성공은 200 상태코드에 보낸 Activity에 ID를 되돌려준다.

프로토콜이 그렇다는 것이고 응답을 받으려면 당연히 응답을 해줄 Bot이 준비되어 있어야 한다. 메시지를 보낼때 Content-Type을 헤더에 써줘야 한다.

  • URL: /v3/directline/conversations/{conversationId}/activities
  • Method: POST
  • Header: Authorization: Bearer {token} / Content-Type: application/json
  • body
{
  "type": "message",
  "from": {
    "id": "{대화이름}"
  },
  "text": "안녕하세요!"
}

bot-send-message

메시지(activity) 받기

메시지를 받을 때는 같은 주소로 GET 요청을 하면 된다. 즉시 응답이 오지 않고 시간이 걸린다. 즉, polling을 하면서 메시지를 기다려야 한다.

  • URL: /v3/directline/conversations/{conversationId}/activities
  • Method: GET
  • Header: Authorization: Bearer {token}

응답을 받아보면 아래와 같다. 각 보내고 받은 메시지에도 ID가 부여 된 걸 알 수 있다. 시간과 채널에 대한 정보와 Bot의 이름 정보도 온다.

{
  "activities": [
    {
      "type": "message",
      "id": "3Dk2pLyFLvc|000000000000000004",
      "timestamp": "2016-12-02T12:18:51.0051607Z",
      "channelId": "directline",
      "from": {
        "id": "ketbotv2",
        "name": "ketbotv2"
      },
      "conversation": {
        "id": "3Dk2pLyFLvc"
      },
      "text": "You sent 안녕하세요! which was 6 characters",
      "replyToId": "3Dk2pLyFLvc|000000000000000003"
    }
  ],
  "watermark": "4"
}

여기서 중요한 값이 하나 오는데 바로 Watermark라는 값이다. 이 값은 메시지를 보낼 때 마다 단순 증가한다. 메시지를 받을 때 GET 요청을 할때 watermark 라는 Query String을 붙여주지 않으면 응답으로 해당 대화의 전체 히스토리를 다 전달 해준다. 메시지를 100번 주고 받았다면 100개의 과거 메시지가 다 전달된다. 이 때 Watermark 값을 GET 요청에 Query String으로 전달해 주면 해당 watermark 이후의 메시지만 응답으로 주니 더욱 효율적인 통신을 할 수 있다.

bot-receive-message

여기까지가 Microsoft Bot Framework의 Direct Line REST API를 이용해서 단순 메시지를 주고 받는 방법이다.

그 외에 문서를 보면 파일을 업로드 하는 방법과 WebSocket 을 이용하는 방법이 더 소개되어 있다.