사용자가 Google Chat에서 링크를 공유할 때 컨텍스트 전환을 방지하기 위해 채팅 앱에서는 메시지에 카드를 첨부하여 링크를 미리 볼 수 있습니다. 이 카드는 자세한 정보를 제공하고 사용자가 Google Chat에서 바로 조치를 취할 수 있도록 합니다.
예를 들어 회사의 모든 고객 서비스 상담사와 Case-y라는 채팅 앱이 포함된 Google Chat 스페이스가 있다고 가정해 보겠습니다. 상담사는 Chat 스페이스에서 고객 서비스 케이스 링크를 자주 공유하므로, 매번 동료가 케이스 링크를 열어 담당자, 상태, 제목과 같은 세부정보를 확인해야 합니다. 마찬가지로 사용자가 케이스의 소유권을 얻거나 상태를 변경하려면 링크를 열어야 합니다.
링크 미리보기를 사용하면 스페이스의 상주 Chat 앱인 Case-y에서 담당자, 상태, 제목을 보여주는 카드를 첨부하여 케이스 링크를 공유할 때마다 확인할 수 있습니다. 카드에 있는 버튼을 사용하면 상담사가 채팅 스트림에서 직접 케이스의 소유권을 가져와 상태를 변경할 수 있습니다.
링크 미리보기 작동 방식
누군가 메시지에 링크를 추가하면 채팅 앱에서 링크를 미리 볼 수 있음을 알려주는 칩이 표시됩니다.
![채팅 앱에서 링크를 미리 볼 수 있음을 나타내는 칩](https://developers.google.com/static/workspace/chat/images/link-preview-chip.png?hl=ko)
메시지를 보내면 채팅 앱으로 링크가 전송되고, 앱에서 카드를 생성하여 사용자의 메시지에 첨부합니다.
![채팅 앱에서 메시지에 카드를 첨부하여 링크 미리보기](https://developers.google.com/static/workspace/chat/images/link-preview-case-details.png?hl=ko)
카드에는 링크와 함께 버튼과 같은 상호작용 요소를 비롯하여 링크에 관한 추가 정보가 표시됩니다. 채팅 앱은 버튼 클릭과 같은 사용자 상호작용에 대한 응답으로 첨부된 카드를 업데이트할 수 있습니다.
메시지에 카드를 첨부하여 채팅 앱에서 링크를 미리 보는 것을 원하지 않는 사용자는 미리보기 칩에서 cancel를 클릭하여 미리보기를 표시하지 않을 수 있습니다. 사용자는 미리보기 삭제를 클릭하여 언제든지 첨부된 카드를 삭제할 수 있습니다.
기본 요건
Node.js
양방향 기능이 사용 설정된 Google Chat 앱
대화형 채팅 앱을 사용하려면 이 빠른 시작을 완료하세요.
Apps Script
양방향 기능이 사용 설정된 Google Chat 앱
Apps Script에서 대화형 채팅 앱을 사용하려면 이 빠른 시작을 완료하세요.
채팅 앱에서 미리 볼 수 있도록 Google Cloud 콘솔의 채팅 앱 구성 페이지에서 특정 링크(예: example.com
, support.example.com
, support.example.com/cases/
)를 URL 패턴으로 등록합니다.
![링크 미리보기 구성 메뉴](https://developers.google.com/static/workspace/chat/images/link-preview-configuration.png?hl=ko)
- Google Cloud 콘솔을 엽니다.
- 'Google Cloud' 옆에는 아래쪽 화살표 arrow_drop_down를 클릭하고 채팅 앱의 프로젝트를 엽니다.
- 검색창에
Google Chat API
를 입력하고 Google Chat API를 클릭합니다.
- Manage > Configuration을 클릭합니다.
- 링크 미리보기에서 URL 패턴을 추가하거나 수정합니다.
- 새 URL 패턴에 대한 링크 미리보기를 구성하려면 URL 패턴 추가를 클릭합니다.
- 기존 URL 패턴에 대한 구성을 수정하려면 아래쪽 화살표 expand_more를 클릭합니다.
호스트 패턴 입력란에 URL 패턴의 도메인을 입력합니다. 채팅 앱에서 이 도메인으로 연결되는 링크를 미리 봅니다.
subdomain.example.com
과 같은 특정 하위 도메인의 Chat 앱 미리보기 링크를 사용하려면 하위 도메인을 포함하세요.
전체 도메인에 Chat 앱 미리보기 링크를 사용하려면 하위 도메인으로 별표 (*)가 있는 와일드 카드 문자를 지정합니다. 예를 들어 *.example.com
는 subdomain.example.com
및 any.number.of.subdomains.example.com
와 일치합니다.
경로 프리픽스 입력란에 호스트 패턴 도메인에 추가할 경로를 입력합니다.
호스트 패턴 도메인의 모든 URL과 일치시키려면 경로 접두어를 비워둡니다.
예를 들어 호스트 패턴이 support.example.com
인 경우 support.example.com/cases/
에 호스팅된 케이스의 URL과 일치시키려면 cases/
을 입력합니다.
완료를 클릭합니다.
저장을 클릭합니다.
이제 사용자가 Chat 앱이 포함된 Chat 스페이스의 메시지에 링크 미리보기 URL 패턴과 일치하는 링크를 포함할 때마다 앱에서 링크를 미리 볼 수 있습니다.
링크 미리보기
특정 링크에 대한 링크 미리보기를 구성한 후에는
채팅 앱이 다음을 통해 링크를 인식하고 미리 볼 수 있습니다.
더 많은 정보를 첨부합니다
다음을 포함하는 Chat 스페이스 내부
채팅 앱: 사용자의 메시지에
링크 미리보기 URL 패턴과 일치하면 채팅 앱이
를 받을 수 있습니다.
MESSAGE
상호작용 이벤트. JSON
상호작용 이벤트의 페이로드에는 matchedUrl
필드가 포함됩니다.
JSON
"message": {
. . . // other message attributes redacted
"matchedUrl": {
"url": "https://support.example.com/cases/case123"
},
. . . // other message attributes redacted
}
MESSAGE
이벤트에 matchedUrl
필드가 있는지 확인
채팅 앱이 페이로드로
메시지를 미리보기된 링크와 함께 표시합니다. 채팅 앱에서 다음 작업을 할 수 있습니다.
간단한 문자 메시지로 답장하거나 카드를 첨부하세요.
문자 메시지로 답장
간단한 응답의 경우 채팅 앱에서 링크를 미리 볼 수 있습니다.
간단한 문자 메시지로 답장
링크 추가 이 예에서는
링크 미리보기 URL 패턴과 일치합니다.
카드 첨부
미리보기된 링크에 카드를 첨부하려면 다음 단계를 따르세요.
반환
ActionResponse
유형이 UPDATE_USER_MESSAGE_CARDS
입니다. 이 예에서는 간단한 카드를 첨부합니다.
![채팅 앱에서 메시지에 카드를 첨부하여 링크 미리보기](https://developers.google.com/static/chat/images/link-preview-case-details.png?hl=ko)
Node.js
/**
* Responds to messages that have links whose URLs match URL patterns
* configured for link previewing.
*
* @param {Object} req Request sent from Google Chat.
* @param {Object} res Response to send back.
*/
exports.onMessage = (req, res) => {
if (req.method === 'GET' || !req.body.message) {
return res.send(
'Hello! This function is meant to be used in a Google Chat Space.');
}
// Checks for the presence of event.message.matchedUrl and attaches a card
// if present
if (req.body.message.matchedUrl) {
return res.json({
'actionResponse': {'type': 'UPDATE_USER_MESSAGE_CARDS'},
'cardsV2': [
{
'cardId': 'attachCard',
'card': {
'header': {
'title': 'Example Customer Service Case',
'subtitle': 'Case basics',
},
'sections': [
{
'widgets': [
{'keyValue': {'topLabel': 'Case ID', 'content': 'case123'}},
{'keyValue': {'topLabel': 'Assignee', 'content': 'Charlie'}},
{'keyValue': {'topLabel': 'Status', 'content': 'Open'}},
{
'keyValue': {
'topLabel': 'Subject', 'content': 'It won"t turn on...',
}
},
],
},
{
'widgets': [
{
'buttons': [
{
'textButton': {
'text': 'OPEN CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123',
},
},
},
},
{
'textButton': {
'text': 'RESOLVE CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123?resolved=y',
},
},
},
},
{
'textButton': {
'text': 'ASSIGN TO ME',
'onClick': {
'action': {
'actionMethodName': 'assign',
},
},
},
},
],
},
],
},
],
},
},
],
});
}
// If the Chat app doesn’t detect a link preview URL pattern, it says so.
return res.json({'text': 'No matchedUrl detected.'});
};
Apps Script
이 예시에서는
카드 JSON과 함께 사용합니다.
또한
Apps Script 카드 서비스.
/**
* Responds to messages that have links whose URLs match URL patterns
* configured for link previewing.
*
* @param {Object} event The event object from Chat API.
* @return {Object} Response from the Chat app attached to the message with
* the previewed link.
*/
function onMessage(event) {
// Checks for the presence of event.message.matchedUrl and attaches a card
// if present
if (event.message.matchedUrl) {
return {
'actionResponse': {
'type': 'UPDATE_USER_MESSAGE_CARDS',
},
'cardsV2': [{
'cardId': 'attachCard',
'card': {
'header': {
'title': 'Example Customer Service Case',
'subtitle': 'Case basics',
},
'sections': [{
'widgets': [
{'keyValue': {'topLabel': 'Case ID', 'content': 'case123'}},
{'keyValue': {'topLabel': 'Assignee', 'content': 'Charlie'}},
{'keyValue': {'topLabel': 'Status', 'content': 'Open'}},
{
'keyValue': {
'topLabel': 'Subject', 'content': 'It won\'t turn on...',
},
},
],
},
{
'widgets': [{
'buttons': [
{
'textButton': {
'text': 'OPEN CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123',
},
},
},
},
{
'textButton': {
'text': 'RESOLVE CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123?resolved=y',
},
},
},
},
{
'textButton': {
'text': 'ASSIGN TO ME',
'onClick': {'action': {'actionMethodName': 'assign'}},
},
},
],
}],
}],
},
}],
};
}
// If the Chat app doesn’t detect a link preview URL pattern, it says so.
return {'text': 'No matchedUrl detected.'};
}
카드 업데이트
미리보기된 링크에 첨부된 카드를 업데이트하려면
ActionResponse
드림
(UPDATE_USER_MESSAGE_CARDS
유형). 채팅 앱은 업데이트만 가능
링크에 대한 응답으로 링크를 미리 보는 카드
채팅 앱 상호작용 이벤트.
채팅 앱은 Chat API를 호출하여 이러한 카드를 업데이트할 수 없습니다.
있습니다.
링크 미리보기에서는 UPDATE_MESSAGE
유형의 ActionResponse
반환을 지원하지 않습니다. UPDATE_MESSAGE
는 카드만 업데이트하는 대신 전체 메시지를 업데이트하므로 채팅 앱에서 원본 메시지를 만든 경우에만 작동합니다. 링크 미리보기를 사용하면 사용자가 만든 메시지에 카드가 첨부되므로 채팅 앱에는 카드를 업데이트할 권한이 없습니다.
채팅 스트림에서 사용자가 만든 카드와 앱에서 만든 카드를 모두 함수에 업데이트하려면 채팅 앱 또는 사용자가 메시지를 만들었는지에 따라 ActionResponse
를 동적으로 설정하세요.
이를 위해서는 두 가지 방법이 있습니다. 즉, 연결된 카드 (메시지를 사용자가 만든 것으로 식별)의 onclick
속성의 일부로 맞춤 actionMethodName
를 지정하고 확인하거나 사용자가 메시지를 작성했는지 확인하는 것입니다.
actionMethodName
를 사용하여 미리보기된 카드의 CARD_CLICKED
상호작용 이벤트를 적절하게 처리하려면 연결된 카드의 onclick
속성의 일부로 맞춤 actionMethodName
를 설정합니다.
JSON
. . . // Preview card details
{
"textButton": {
"text": "ASSIGN TO ME",
"onClick": {
// actionMethodName identifies the button to help determine the
// appropriate ActionResponse.
"action": {
"actionMethodName": "assign",
}
}
}
}
. . . // Preview card details
"actionMethodName": "assign"
가 버튼을 링크 미리보기의 일부로 식별하면 일치하는 actionMethodName
을 확인하여 올바른 ActionResponse
를 동적으로 반환할 수 있습니다.
옵션 2: 발신자 유형 확인하기
message.sender.type
이 HUMAN
인지 BOT
인지 확인합니다. HUMAN
인 경우 ActionResponse
를 UPDATE_USER_MESSAGE_CARDS
로 설정하고 그렇지 않으면 ActionResponse
를 UPDATE_MESSAGE
로 설정합니다. 방법은 다음과 같습니다.
카드를 업데이트하는 일반적인 이유는 버튼 클릭에 대한 응답입니다. 이전 섹션인 카드 첨부에서 나에게 할당 버튼을 상기합니다. 다음 전체 예에서는 카드가 '나'에게 할당되도록 업데이트합니다. 사용자가 나에게 할당을 클릭한 후 이 예에서는 발신자 유형을 확인하여 ActionResponse
를 동적으로 설정합니다.
전체 예: 고객 서비스 채팅 앱 Case-y
다음은 고객 서비스 상담사가 공동작업하는 Chat 스페이스에서 공유된 케이스의 링크를 미리 보는 채팅 앱인 Case-y의 전체 코드입니다.
Node.js
/**
* Responds to messages that have links whose URLs match URL patterns
* configured for link previewing.
*
* @param {Object} req Request sent from Google Chat.
* @param {Object} res Response to send back.
*/
exports.onMessage = (req, res) => {
if (req.method === 'GET' || !req.body.message) {
return res.send(
'Hello! This function is meant to be used in a Google Chat Space.');
}
// Respond to button clicks on attached cards
if (req.body.type === 'CARD_CLICKED') {
// Checks whether the message event originated from a human or a Chat app
// and sets actionResponse.type to "UPDATE_USER_MESSAGE_CARDS if human or
// "UPDATE_MESSAGE" if Chat app.
const actionResponseType = req.body.action.actionMethodName === 'HUMAN' ?
'UPDATE_USER_MESSAGE_CARDS' :
'UPDATE_MESSAGE';
if (req.body.action.actionMethodName === 'assign') {
return res.json(createMessage(actionResponseType, 'You'));
}
}
// Checks for the presence of event.message.matchedUrl and attaches a card
// if present
if (req.body.message.matchedUrl) {
return res.json(createMessage());
}
// If the Chat app doesn’t detect a link preview URL pattern, it says so.
return res.json({'text': 'No matchedUrl detected.'});
};
/**
* Message to create a card with the correct response type and assignee.
*
* @param {string} actionResponseType
* @param {string} assignee
* @return {Object} a card with URL preview
*/
function createMessage(
actionResponseType = 'UPDATE_USER_MESSAGE_CARDS',
assignee = 'Charlie'
) {
return {
'actionResponse': {'type': actionResponseType},
'cardsV2': [
{
'cardId': 'previewLink',
'card': {
'header': {
'title': 'Example Customer Service Case',
'subtitle': 'Case basics',
},
'sections': [
{
'widgets': [
{'keyValue': {'topLabel': 'Case ID', 'content': 'case123'}},
{'keyValue': {'topLabel': 'Assignee', 'content': assignee}},
{'keyValue': {'topLabel': 'Status', 'content': 'Open'}},
{
'keyValue': {
'topLabel': 'Subject', 'content': 'It won"t turn on...',
},
},
],
},
{
'widgets': [
{
'buttons': [
{
'textButton': {
'text': 'OPEN CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123',
},
},
},
},
{
'textButton': {
'text': 'RESOLVE CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123?resolved=y',
},
},
},
},
{
'textButton': {
'text': 'ASSIGN TO ME',
'onClick': {
'action': {
'actionMethodName': 'assign',
},
},
},
},
],
},
],
},
],
}
},
],
};
}
Apps Script
이 예시에서는
카드 JSON과 함께 사용합니다.
또한
Apps Script 카드 서비스.
/**
* Responds to messages that have links whose URLs match URL patterns
* configured for link previews.
*
* @param {Object} event The event object from Chat API.
* @return {Object} Response from the Chat app attached to the message with
* the previewed link.
*/
function onMessage(event) {
// Checks for the presence of event.message.matchedUrl and attaches a card
// if present
if (event.message.matchedUrl) {
return {
'actionResponse': {
'type': 'UPDATE_USER_MESSAGE_CARDS',
},
'cardsV2': [{
'cardId': 'previewLink',
'card': {
'header': {
'title': 'Example Customer Service Case',
'subtitle': 'Case basics',
},
'sections': [{
'widgets': [
{'keyValue': {'topLabel': 'Case ID', 'content': 'case123'}},
{'keyValue': {'topLabel': 'Assignee', 'content': 'Charlie'}},
{'keyValue': {'topLabel': 'Status', 'content': 'Open'}},
{
'keyValue': {
'topLabel': 'Subject', 'content': 'It won\'t turn on...',
}
},
],
},
{
'widgets': [{
'buttons': [
{
'textButton': {
'text': 'OPEN CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123',
},
},
},
},
{
'textButton': {
'text': 'RESOLVE CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123?resolved=y',
},
},
},
},
{
'textButton': {
'text': 'ASSIGN TO ME',
'onClick': {'action': {'actionMethodName': 'assign'}}
},
},
],
}],
}],
},
}],
};
}
// If the Chat app doesn’t detect a link preview URL pattern, it says so.
return {'text': 'No matchedUrl detected.'};
}
/**
* Updates a card that was attached to a message with a previewed link.
*
* @param {Object} event The event object from Chat API.
* @return {Object} Response from the Chat app. Either a new card attached to
* the message with the previewed link, or an update to an existing card.
*/
function onCardClick(event) {
// Checks whether the message event originated from a human or a Chat app
// and sets actionResponse to "UPDATE_USER_MESSAGE_CARDS if human or
// "UPDATE_MESSAGE" if Chat app.
const actionResponseType = event.message.sender.type === 'HUMAN' ?
'UPDATE_USER_MESSAGE_CARDS' :
'UPDATE_MESSAGE';
// To respond to the correct button, checks the button's actionMethodName.
if (event.action.actionMethodName === 'assign') {
return assignCase(actionResponseType);
}
}
/**
* Updates a card to say that "You" are the assignee after clicking the Assign
* to Me button.
*
* @param {String} actionResponseType Which actionResponse the Chat app should
* use to update the attached card based on who created the message.
* @return {Object} Response from the Chat app. Updates the card attached to
* the message with the previewed link.
*/
function assignCase(actionResponseType) {
return {
'actionResponse': {
// Dynamically returns the correct actionResponse type.
'type': actionResponseType,
},
'cardsV2': [{
'cardId': 'assignCase',
'card': {
'header': {
'title': 'Example Customer Service Case',
'subtitle': 'Case basics',
},
'sections': [{
'widgets': [
{'keyValue': {'topLabel': 'Case ID', 'content': 'case123'}},
{'keyValue': {'topLabel': 'Assignee', 'content': 'You'}},
{'keyValue': {'topLabel': 'Status', 'content': 'Open'}},
{
'keyValue': {
'topLabel': 'Subject', 'content': 'It won\'t turn on...',
}
},
],
},
{
'widgets': [{
'buttons': [
{
'textButton': {
'text': 'OPEN CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123',
},
},
},
},
{
'textButton': {
'text': 'RESOLVE CASE',
'onClick': {
'openLink': {
'url': 'https://support.example.com/orders/case123?resolved=y',
},
},
},
},
{
'textButton': {
'text': 'ASSIGN TO ME',
'onClick': {'action': {'actionMethodName': 'assign'}},
},
},
],
}],
}],
},
}],
};
}
제한사항 및 고려사항
채팅 앱의 링크 미리보기를 구성할 때 다음 제한사항 및 고려사항에 유의하세요.
- 각 채팅 앱은 최대 5개의 URL 패턴에 대한 링크 미리보기를 지원합니다.
- 채팅 앱은 메시지당 하나의 링크를 미리 봅니다. 메일 하나에 미리보기 가능한 링크가 여러 개 있는 경우 미리보기 가능한 첫 번째 링크만 미리볼 수 있습니다.
- 채팅 앱은
https://
로 시작하는 링크만 미리 볼 수 있으므로 https://support.example.com/cases/
는 미리 볼 수 있지만 support.example.com/cases/
는 미리 볼 수 없습니다.
- 슬래시 명령어와 같이 채팅 앱으로 전송되는 다른 정보가 메시지에 포함되어 있지 않은 한 링크 미리보기를 통해 링크 URL만 채팅 앱으로 전송됩니다.
- 미리보기 링크에 연결된 카드는 Chat 앱 상호작용 이벤트에 대한 응답으로
UPDATE_USER_MESSAGE_CARDS
유형의 ActionResponse
만 지원합니다. 링크 미리보기는 Chat API를 통해 미리보기된 링크에 연결된 카드를 업데이트하는 UPDATE_MESSAGE
또는 비동기식 요청을 지원하지 않습니다. 자세한 내용은 카드 업데이트하기를 참고하세요.
디버그 링크 미리보기
링크 미리보기를 구현할 때 앱의 로그를 읽어 채팅 앱을 디버그해야 할 수 있습니다. 로그를 읽으려면 Google Cloud 콘솔에서 로그 탐색기로 이동하세요.