캔버스 프롬프트

웹 앱으로 정보를 릴레이하려면 대화 로직에서 Canvas 응답을 전송해야 합니다. Canvas 응답은 다음 중 하나를 실행할 수 있습니다.

  • 사용자 기기에서 전체 화면 웹 앱 렌더링
  • 데이터를 전달하여 웹 앱 업데이트

다음 섹션에서는 각 시나리오에서 Canvas 응답을 반환하는 방법을 설명합니다.

Interactive Canvas 사용 설정

Interactive Canvas를 사용하려면 특정 방식으로 작업을 구성해야 합니다. Interactive Canvas를 사용하는 작업을 만들려면 Actions 콘솔에서 추가 구성을 사용해야 합니다 (Actions SDK의 경우 settings.yaml 파일 수정). Actions SDK로 Interactive Canvas 작업을 만들고 구성하는 전체 절차를 확인하려면 프로젝트 만들기를 참고하세요.

Actions Builder를 사용할 때는 다음 추가 단계에 따라 Interactive Canvas를 사용 설정하세요.

  1. 어떤 유형의 작업을 빌드하고 싶으신가요? 화면에서 게임 카드를 선택하지 않았다면 상단 탐색 메뉴에서 배포를 클릭합니다. 추가 정보에서 게임 및 오락 카테고리를 선택합니다. 저장을 클릭합니다.
  2. Actions 콘솔의 상단 탐색 메뉴에서 Develop을 클릭합니다.
  3. 왼쪽 탐색 메뉴에서 Interactive Canvas를 클릭합니다.
  4. 작업에서 Interactive Canvas를 사용하시겠어요?에서 다음 중 하나를 선택합니다.
    • 서버 웹훅 처리를 사용하여 Interactive Canvas 사용 설정 이 옵션은 웹훅을 사용하여 특정 기능에 액세스하며 자주 onUpdate()를 사용하여 데이터를 웹 앱에 전달합니다. 사용 설정하면 인텐트 일치가 장면에서 처리되며 다른 장면으로 전환하거나 대화를 종료하기 전에 웹훅을 호출하도록 선택할 수 있습니다.
    • 클라이언트 처리를 사용하여 Interactive Canvas 사용 설정 이 옵션을 사용하면 웹훅 처리 로직을 웹 앱으로 이동하고 웹훅 호출을 계정 연결과 같이 필요한 대화 기능으로만 제한할 수 있습니다. 사용 설정된 경우 expect()를 사용하여 클라이언트 측에 인텐트 핸들러를 등록할 수 있습니다.
  5. 선택사항: 기본 웹 앱 URL 설정 필드에 웹 앱 URL을 입력합니다. 이 작업은 URL 필드가 있는 기본 Canvas 응답을 Main 호출에 추가합니다.
  6. 저장을 클릭합니다.

Actions SDK를 사용할 때는 다음 추가 단계에 따라 Interactive Canvas를 사용 설정하세요.

  1. 사용자가 작업을 가장 잘 설명하고 찾을 수 있도록 settings.yaml 파일의 category 필드를 GAMES_AND_TRIVIA로 설정합니다.
  2. settings.yaml 파일의 usesInteractiveCanvas 필드를 true로 설정합니다.

노출 영역 기능 확인

Interactive Canvas 프레임워크는 시각적 인터페이스를 제공하는 어시스턴트 기기에서만 실행되므로 작업은 사용자 기기의 INTERACTIVE_CANVAS 기능을 확인해야 합니다. Actions Builder에서 프롬프트를 정의할 때 candidates 객체의 selector 필드에 기기 기능 목록을 지정할 수 있습니다. 메시지 선택기는 사용자의 기기 기능에 가장 적합한 메시지 후보를 선택합니다.

Canvas 응답을 반환하려면 작업의 로직이 다음을 실행해야 합니다.

  1. 사용자의 기기가 INTERACTIVE_CANVAS 기능을 지원하는지 확인합니다. 지원한다면 사용자에게 Canvas 응답을 전송합니다.
  2. Interactive Canvas 기능을 사용할 수 없다면 사용자 기기에서 RICH_RESPONSE 기능을 지원하는지 확인합니다. 포함하는 경우 사용자에게 리치 응답을 대신 전송합니다.
  3. 리치 응답 기능을 사용할 수 없는 경우 사용자에게 간단한 응답을 보냅니다.

다음 스니펫은 사용자 기기의 기능에 따라 적절한 응답을 반환합니다.

YAML

candidates:
  - selector:
      surface_capabilities:
        capabilities:
          - INTERACTIVE_CANVAS
    canvas:
      url: 'https://example.web.app'
  - selector:
      surface_capabilities:
        capabilities:
          - RICH_RESPONSE
    content:
      card:
        title: Card title
        text: Card Content
        image:
          url: 'https://example.com/image.png'
          alt: Alt text
        button:
          name: Link name
          open:
            url: 'https://example.com/'
  - first_simple:
      variants:
        - speech: Example simple response.
    

JSON

{
  "candidates": [
    {
      "selector": {
        "surface_capabilities": {
          "capabilities": [
            "INTERACTIVE_CANVAS"
          ]
        }
      },
      "canvas": {
        "url": "https://example.web.app"
      }
    },
    {
      "selector": {
        "surface_capabilities": {
          "capabilities": [
            "RICH_RESPONSE"
          ]
        }
      },
      "content": {
        "card": {
          "title": "Card title",
          "text": "Card Content",
          "image": {
            "url": "https://example.com/image.png",
            "alt": "Alt text"
          },
          "button": {
            "name": "Link name",
            "open": {
              "url": "https://example.com/"
            }
          }
        }
      }
    },
    {
      "first_simple": {
        "variants": [
          {
            "speech": "Example simple response."
          }
        ]
      }
    }
  ]
}

    

Node.js

const supportsRichResponse = conv.device.capabilities.includes("RICH_RESPONSE");
const supportsInteractiveCanvas = conv.device.capabilities.includes("INTERACTIVE_CANVAS");
if (supportsInteractiveCanvas) {
  // Respond with a Canvas response
  conv.add(new Canvas({
    url: 'https://example.web.app',
  }));
} else if (supportsRichResponse) {
  // Respond with a rich response
  conv.add(new Card({
    title: 'Card title',
    image: new Image({
      url: 'https://example.com/image.png',
      alt: 'Alt text',
    }),
    button: new Link({
      name: 'Link name',
      open: {
        url: 'https://example.com/',
      },
    }),
  }));
} else {
  // Respond with a simple response
  conv.add('Example simple response.');
}
  

웹 앱 렌더링

Interactive Canvas를 사용하는 작업에는 사용자에게 응답으로 전송하는 맞춤설정된 시각적 요소가 포함된 웹 앱이 포함됩니다. 웹 앱이 렌더링되면 사용자는 대화가 끝날 때까지 음성, 텍스트 또는 터치를 통해 계속 앱과 상호작용합니다.

첫 번째 Canvas 응답에는 웹 앱의 URL이 포함되어야 합니다. 이 유형의 Canvas 응답은 Google 어시스턴트에 사용자 기기의 해당 주소에 웹 앱을 렌더링하도록 지시합니다. 일반적으로 사용자가 작업을 호출한 직후에 첫 번째 Canvas 응답을 전송합니다. 웹 앱이 로드되면 Interactive Canvas 라이브러리가 로드되고 웹 앱은 Interactive Canvas API에 콜백 핸들러를 등록합니다.

다음 스크린샷과 같이 Actions Builder에서 웹 앱의 URL을 지정할 수 있습니다.

웹 앱 URL을 지정한 후 Canvas 응답이 포함된 프롬프트를 만들면 Actions Builder가 Canvas 응답의 URL 필드를 자동으로 채웁니다. 콘솔에서 웹 앱 URL을 설정하는 방법에 관한 자세한 내용은 Interactive Canvas 사용 설정 섹션을 참고하세요.

다음 스니펫은 Actions Builder와 웹훅에서 모두 웹 앱을 렌더링하는 Canvas 응답을 구성하는 방법을 보여줍니다.

YAML

candidates:
  - first_simple:
       variants:
         - speech: >-
             Welcome! Do you want me to change color or pause spinning? You can
             also tell me to ask you later.
     canvas:
       url: 'https://your-web-app.com'
    

JSON

{
  "candidates": [
    {
      "first_simple": {
        "variants": [
          {
            "speech": "Welcome! Do you want me to change color or pause spinning? You can also tell me to ask you later."
          }
        ]
      },
      "canvas": {
        "url": "https://your-web-app.com"
      }
    }
  ]
}
    

Node.js

app.handle('welcome', (conv) => {
  conv.add('Welcome! Do you want me to change color or pause spinning? ' +
    'You can also tell me to ask you later.');
  conv.add(new Canvas({
    url: `https://your-web-app.com`,
  }));
});
    

JSON

{
  "session": {
    "id": "session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "Welcome! Do you want me to change color or pause spinning? You can also tell me to ask you later.",
      "text": "Welcome! Do you want me to change color or pause spinning? You can also tell me to ask you later."
    },
    "canvas": {
      "data": [],
      "suppressMic": false,
      "url": "https://your-web-app.com"
    }
  }
}
    

데이터를 전달하여 웹 앱 업데이트

초기 Canvas 응답을 전송한 후에는 추가 Canvas 응답을 사용하여 웹 앱의 맞춤 로직이 웹 앱을 변경하는 데 사용하는 data 업데이트를 제공할 수 있습니다. 웹 앱에 데이터를 전달하는 Canvas 응답을 보내면 다음 단계가 발생합니다.

  1. 장면 내에서 인텐트가 일치되면 이벤트가 트리거되고 JSON 페이로드가 있는 data 필드가 포함된 Canvas 응답이 응답으로 다시 전송됩니다.
  2. data 필드는 onUpdate 콜백에 전달되며 웹 앱을 업데이트하는 데 사용됩니다.
  3. 대화형 작업은 새 Canvas 응답을 전송하고 data 필드에 정보를 제공하여 새 업데이트를 보내거나 새 상태를 로드할 수 있습니다.

다음 두 가지 방법으로 웹 앱에 데이터를 전달할 수 있습니다.

  • Actions Builder 사용 Actions Builder가 Canvas 응답의 data 필드에 웹 앱을 업데이트하는 데 필요한 메타데이터를 자동으로 채웁니다.
  • 웹훅 사용. 웹훅이 있으면 커스텀 데이터 페이로드를 구성하여 Canvas 응답에서 웹 앱을 업데이트할 수 있습니다.

다음 섹션에서는 Actions Builder와 웹훅을 통해 데이터를 전달하는 방법을 설명합니다.

Actions Builder를 사용하여 데이터 전달

Actions Builder를 사용하면 웹 앱으로 전송되는 메타데이터를 관리하기 위해 웹훅을 정의할 필요가 없습니다. 대신 Actions Builder UI에서 인텐트 핸들러를 구성할 때 Canvas 응답을 포함할 수 있습니다. data 필드는 인텐트 이름, 사용자의 입력에서 캡처된 매개변수, 현재 장면과 같은 웹 앱을 업데이트하는 데 필요한 메타데이터로 자동으로 채워집니다.

예를 들어, 다음 Guess 인텐트 핸들러는 Canvas 응답을 포함하려고 함을 나타냅니다.

YAML

candidates:
  - canvas:
      send_state_data_to_canvas_app: true
    

JSON

{
  "candidates": [
    {
      "canvas": {
        "send_state_data_to_canvas_app": true
      }
    }
  ]
}
    

필요한 경우 다음 스니펫을 인텐트 핸들러에 추가하여 TTS 메시지를 보낼 수 있습니다.

...
  - first_simple:
      variants:
        - speech: Optional message.

Actions Builder는 다음 스니펫과 같이 메타데이터를 사용하여 Canvas 응답을 자동으로 확장하여 웹 앱을 업데이트합니다. 이 경우 사용자는 단어 추측 게임에서 문자 'a'를 추측했습니다.

YAML

candidates:
  - canvas:
      data:
        - google:
            intent:
              params:
                letter:
                  resolved: a
                  original: a
              name: guess
            scene: Game
      sendStateDataToCanvasApp: true
    

JSON

{
  "candidates": [
    {
      "canvas": {
        "data": [
          {
            "google": {
              "intent": {
                "params": {
                  "letter": {
                    "resolved": "a",
                    "original": "a"
                  }
                },
                "name": "guess"
              },
              "scene": "Game"
            }
          }
        ],
        "sendStateDataToCanvasApp": true
      }
    }
  ]
}
    

이 응답은 사용자의 답변으로 웹 앱을 업데이트하고 적절한 장면으로 전환합니다.

웹훅을 사용하여 데이터 전달

웹 앱을 업데이트하는 데 필요한 상태 정보로 Canvas 응답의 data 필드를 수동으로 구성할 수 있습니다. 이 방법은 웹 앱을 업데이트하는 데 필요한 일반적인 메타데이터만 전달하는 대신 Canvas 응답에 커스텀 data 페이로드를 포함해야 하는 경우에 권장됩니다.

다음 스니펫은 웹훅에서 Canvas 응답으로 데이터를 전달하는 방법을 보여줍니다.

Node.js

app.handle('start_spin', (conv) => {
  conv.add(`Ok, I'm spinning. What else?`);
  conv.add(new Canvas({
    data: {
      command: 'SPIN',
      spin: true,
    },
  }));
});
    

JSON

{
  "session": {
    "id": "session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "Ok, I'm spinning. What else?",
      "text": "Ok, I'm spinning. What else?"
    },
    "canvas": {
      "data": {
        "command": "SPIN",
        "spin": true
      },
      "suppressMic": false,
      "url": ""
    }
  }
}
    

가이드라인 및 제한사항

작업을 빌드할 때 Canvas 응답에 관한 다음 가이드라인과 제한사항에 유의하세요.

  • 처리의 각 웹훅 핸들러에는 Canvas가 포함되어야 합니다. 웹훅 응답에 Canvas이 포함되어 있지 않으면 웹 앱이 닫힙니다.
  • 사용자에게 전송하는 첫 번째 Canvas 응답에 웹 앱 URL을 포함하기만 하면 됩니다.
  • Canvas 응답 URL은 유효해야 하며 프로토콜은 https여야 합니다.
  • Canvas 응답의 크기는 50KB 이하여야 합니다.