Direct Line API 3.0의 봇에서 활동 받기Receive activities from the bot in Direct Line API 3.0

직접 회선 3.0 프로토콜을 사용하면 클라이언트는 WebSocket 스트림을 통해 활동을 수신하거나 HTTP GET 요청을 실행하여 활동을 검색할 수 있습니다.Using the Direct Line 3.0 protocol, clients can receive activities via WebSocket stream or retrieve activities by issuing HTTP GET requests.

WebSocket 대 HTTP GETWebSocket vs HTTP GET

스트리밍 WebSocket은 메시지를 클라이언트에 효율적으로 푸시하지만, GET 인터페이스를 사용하면 클라이언트가 메시지를 명시적으로 요청할 수 있습니다.A streaming WebSocket efficiently pushes messages to clients, whereas the GET interface enables clients to explicitly request messages. WebSocket 메커니즘은 효율성으로 인해 종종 선호되지만, GET 메커니즘은 WebSocket을 사용할 수 없는 클라이언트에 유용할 수 있습니다.Although the WebSocket mechanism is often preferred due to its efficiency, the GET mechanism can be useful for clients that are unable to use WebSockets.

이 서비스는 대화당 하나의 WebSocket 연결만 허용합니다.The service allows only 1 WebSocket connection per conversation. Direct Line은 추가 WebSocket 연결을 이유 값 collision으로 닫을 수 있습니다.Direct Line may close additional WebSocket connections with a reason value of collision.

모든 활동 형식이 WebSocket 및 HTTP GET을 둘 다 사용하여 제공되는 것은 아닙니다.Not all activity types are available both via WebSocket and via HTTP GET. 다음 표에서는 직접 회선 프로토콜을 사용하는 클라이언트에 대한 다양한 활동 형식의 가용성을 설명합니다.The following table describes the availability of the various activity types for clients that use the Direct Line protocol.

활동 유형Activity type 가용성Availability
messagemessage HTTP GET 및 WebSocketHTTP GET and WebSocket
typingtyping WebSocket만WebSocket only
conversationUpdateconversationUpdate 클라이언트를 통해 전송/수신되지 않음Not sent/received via client
contactRelationUpdatecontactRelationUpdate 직접 회선에서 지원되지 않음Not supported in Direct Line
endOfConversationendOfConversation HTTP GET 및 WebSocketHTTP GET and WebSocket
모든 기타 활동 형식all other activity types HTTP GET 및 WebSocketHTTP GET and WebSocket

WebSocket 스트림을 통해 활동 수신Receive activities via WebSocket stream

클라이언트가 봇과 대화를 열기 위해 대화 시작 요청을 보내면 서비스 응답에는 클라이언트가 이후에 WebSocket을 통해 연결하는 데 사용할 수 있는 streamUrl 속성이 포함됩니다.When a client sends a Start Conversation request to open a conversation with a bot, the service's response includes a streamUrl property that the client can subsequently use to connect via WebSocket. 스트림 URL은 권한이 미리 부여되어 있으므로 WebSocket을 통해 연결하기 위한 클라이언트의 요청에 Authorization 헤더가 필요하지 않습니다.The stream URL is preauthorized and therefore the client's request to connect via WebSocket does NOT require an Authorization header.

다음 예제에서는 streamUrl을 사용하여 WebSocket을 통해 연결하는 요청을 보여 줍니다.The following example shows a request that uses a streamUrl to connect via WebSocket.

-- connect to wss://directline.botframework.com --
GET /v3/directline/conversations/abc123/stream?t=RCurR_XV9ZA.cwA..."
Upgrade: websocket
Connection: upgrade
[other headers]

서비스에서 상태 코드 HTTP 101(“프로토콜 전환”)로 응답합니다.The service responds with status code HTTP 101 ("Switching Protocols").

HTTP/1.1 101 Switching Protocols
[other headers]

메시지 받기Receive messages

WebSocket을 통해 연결한 후 클라이언트는 직접 회선 서비스에서 다음 형식의 메시지를 받을 수 있습니다.After it connects via WebSocket, a client may receive these types of messages from the Direct Line service:

  • 하나 이상의 활동 및 워터마크(아래 설명됨)를 포함하는 ActivitySet이 있는 메시지.A message that contains an ActivitySet that includes one or more activities and a watermark (described below).
  • 연결이 계속 유효한지 확인하기 위해 직접 회선 서비스에서 사용하는 빈 메시지.An empty message, which the Direct Line service uses to ensure the connection is still valid.
  • 나중에 정의되는 추가 형식.Additional types, to be defined later. 이러한 형식은 JSON 루트의 속성으로 식별됩니다.These types are identified by the properties in the JSON root.

ActivitySet에는 봇 및 대화의 모든 사용자가 보내는 메시지가 포함됩니다.An ActivitySet contains messages sent by the bot and by all users in the conversation. 다음 예제에서는 단일 메시지가 포함된 ActivitySet을 보여 줍니다.The following example shows an ActivitySet that contains a single message.

{
    "activities": [
        {
            "type": "message",
            "channelId": "directline",
            "conversation": {
                "id": "abc123"
            },
            "id": "abc123|0000",
            "from": {
                "id": "user1"
            },
            "text": "hello"
        }
    ],
    "watermark": "0000a-42"
}

메시지 처리Process messages

클라이언트는 각 ActivitySet으로 받는 watermark 값을 추적해야 합니다. 이렇게 해야 워터마크를 사용하여 연결이 끊어져서 대화에 다시 연결해야 할 경우 손실되는 메시지가 없도록 보장할 수 있습니다.A client should keep track of the watermark value that it receives in each ActivitySet, so that it may use the watermark to guarantee that no messages are lost if it loses its connection and needs to reconnect to the conversation. 클라이언트가 ActivitySet을 받을 때 여기에 포함된 watermark 속성이 null이거나 없는 경우에는 값을 무시하고 클라이언트가 받은 이전 워터마크를 덮어쓰지 않아야 합니다.If the client receives an ActivitySet wherein the watermark property is null or missing, it should ignore that value and not overwrite the prior watermark that it received.

클라이언트는 직접 회선 서비스에서 받는 빈 메시지를 무시해야 합니다.A client should ignore empty messages that it receives from the Direct Line service.

클라이언트는 직접 회선 서비스에 빈 메시지를 보내 연결을 확인할 수 있습니다.A client may send empty messages to the Direct Line service to verify connectivity. 직접 회선 서비스는 클라이언트에서 받은 빈 메시지를 무시합니다.The Direct Line service will ignore empty messages that it receives from the client.

직접 회선 서비스는 특정 조건에서 WebSocket 연결을 강제로 끊을 수 있습니다.The Direct Line service may forcibly close the WebSocket connection under certain conditions. 클라이언트가 endOfConversation 활동을 받지 않으면 새 WebSocket 스트림 URL을 생성하여 대화에 다시 연결하는 데 사용할 수 있습니다.If the client has not received an endOfConversation activity, it may generate a new WebSocket stream URL that it can use to reconnect to the conversation.

WebSocket 스트림에는 라이브 업데이트와 최근 메시지(WebSocket을 통한 연결 호출이 실행된 이후)가 포함되지만 가장 최근 POST 전에 /v3/directline/conversations/{id}에 전송된 메시지는 포함되지 않습니다.The WebSocket stream contains live updates and very recent messages (since the call to connect via WebSocket was issued) but it does not include messages that were sent prior to the most recent POST to /v3/directline/conversations/{id}. 대화 이전에 전송된 메시지를 검색하려면 아래 설명대로 HTTP GET을 사용합니다.To retrieve messages that were sent earlier in the conversation, use HTTP GET as described below.

HTTP GET을 사용하여 활동 검색Retrieve activities with HTTP GET

WebSocket을 사용할 수 있는 클라이언트는 HTTP GET을 사용하여 활동을 검색할 수 있습니다.Clients that are unable to use WebSockets can retrieve activities by using HTTP GET.

특정 대화에 대한 메시지를 검색하려면 /v3/directline/conversations/{conversationId}/activities 엔드포인트에 GET 요청을 실행하고, 선택적으로 watermark 매개 변수를 지정하여 클라이언트가 표시하는 가장 최근 메시지를 나타냅니다.To retrieve messages for a specific conversation, issue a GET request to the /v3/directline/conversations/{conversationId}/activities endpoint, optionally specifying the watermark parameter to indicate the most recent message seen by the client.

다음 코드 조각은 대화 활동 가져오기 요청 및 응답의 예제를 제공합니다.The following snippets provide an example of the Get Conversation Activities request and response. 대화 활동 가져오기 응답에는 watermarkActivitySet의 속성으로 포함됩니다.The Get Conversation Activities response contains watermark as a property of the ActivitySet. 클라이언트는 활동이 반환되지 않을 때까지 watermark 값을 전달하여 사용 가능한 활동을 페이징해야 합니다.Clients should page through the available activities by advancing the watermark value until no activities are returned.

요청Request

GET https://directline.botframework.com/v3/directline/conversations/abc123/activities?watermark=0001a-94
Authorization: Bearer RCurR_XV9ZA.cwA.BKA.iaJrC8xpy8qbOF5xnR2vtCX7CZj0LdjAPGfiCpg4Fv0

응답Response

HTTP/1.1 200 OK
[other headers]
{
    "activities": [
        {
            "type": "message",
            "channelId": "directline",
            "conversation": {
                "id": "abc123"
            },
            "id": "abc123|0000",
            "from": {
                "id": "user1"
            },
            "text": "hello"
        }, 
        {
            "type": "message",
            "channelId": "directline",
            "conversation": {
                "id": "abc123"
            },
            "id": "abc123|0001",
            "from": {
                "id": "bot1"
            },
            "text": "Nice to see you, user1!"
        }
    ],
    "watermark": "0001a-95"
}

타이밍 고려 사항Timing considerations

대부분 클라이언트는 전체 메시지 기록을 보존하려고 합니다.Most clients wish to retain a complete message history. 직접 회선은 잠재적인 타이밍 격차가 있는 다중 파트 프로토콜이지만, 프로토콜 및 서비스는 신뢰할 수 있는 클라이언트를 빌드할 수 있도록 디자인되어 있습니다.Even though Direct Line is a multi-part protocol with potential timing gaps, the protocol and service is designed to make it easy to build a reliable client.

  • WebSocket 스트림 및 대화 활동 가져오기 응답으로 전송되는 watermark 속성은 신뢰할 수 있습니다.The watermark property that is sent in the WebSocket stream and Get Conversation Activities response is reliable. 클라이언트는 워터마크 축자를 재생하는 경우 메시지를 놓치지 않습니다.A client will not miss any messages as long as it replays the watermark verbatim.

  • 클라이언트가 대화를 시작하고 WebSocket 스트림에 연결하면 POST 이후, 소켓이 열리기 전에 전송되는 모든 활동은 새 활동 전에 재생됩니다.When a client starts a conversation and connects to the WebSocket stream, any activities that are sent after the POST but before the socket is opened are replayed before new activities.

  • 클라이언트가 WebSocket 스트림에 연결된 동안 대화 활동 가져오기 요청을 실행하면(기록을 새로 고치기 위해) 두 개의 채널에서 활동이 중복될 수 있습니다.When a client issues a Get Conversation Activities request (to refresh history) while it is connected to the WebSocket stream, activities may be duplicated across both channels. 클라이언트는 중복 활동이 발생할 경우 이를 거부할 수 있도록 모든 알려진 활동 ID를 추적해야 합니다.Clients should keep track of all known activity IDs so that they are able to reject duplicate activities, should they occur.

HTTP GET을 사용하여 폴링하는 클라이언트는 용도와 일치하는 폴링 간격을 선택해야 합니다.Clients that poll using HTTP GET should choose a polling interval that matches their intended use.

  • 서비스 간 애플리케이션은 종종 5초 또는 10초의 폴링 간격을 사용합니다.Service-to-service applications often use a polling interval of 5s or 10s.

  • 클라이언트 쪽 애플리케이션은 종종 1초의 폴링 간격을 사용하고, 클라이언트가 메시지를 보낼 때마다(봇의 응답을 빠르게 검색하기 위해) 메시지 전송 직후 단일 추가 요청을 실행합니다.Client-facing applications often use a polling interval of 1s, and issue a single additional request shortly after every message that the client sends (to rapidly retrieve a bot's response). 이 지연 시간은 300ms로 짧은 시간일 수 있지만 봇의 속도와 전송 시간에 따라 조정해야 합니다.This delay can be as short at 300ms but should be tuned based on the bot's speed and transit time. 모든 연장 기간 동안 초당 두 번 이상의 간격으로 폴링이 수행되어서는 안 됩니다.Polling should not be more frequent than once per second for any extended period of time.

추가 리소스Additional resources