이 페이지에서는 Cloud Pub/Sub를 사용하여 Chat에서 이벤트를 수신하는 Chat 앱을 만드는 방법을 설명합니다. 이 아키텍처는 Chat 앱이 방화벽 뒤에 있거나 Google Workspace Events API를 사용하여 Chat 스페이스 또는 사용자에 관한 이벤트를 전송하거나 수신하려는 경우에 유용합니다.
다음 다이어그램은 Pub/Sub로 빌드된 Chat 앱의 아키텍처를 보여줍니다.
앞의 다이어그램에서 Pub/Sub Chat 앱과 상호작용하는 사용자는 다음과 같은 정보 흐름을 갖습니다.
사용자는 메시지를 보내거나, 명령어를 실행하거나, Chat 스페이스에서 Chat 앱을 추가 또는 삭제하는 등의 방법으로 Chat 앱과 상호작용합니다.
Chat은 메시지를 Pub/Sub 주제로 전송합니다.
Chat 앱 로직을 포함하는 클라우드 또는 온프레미스 시스템인 애플리케이션 서버는 방화벽을 통해 메시지를 수신하기 위해 Pub/Sub 주제를 구독합니다.
필요에 따라 Chat 앱은 Chat API를 호출하여 메시지를 비동기식으로 게시하거나 다른 작업을 실행할 수 있습니다.
기본 요건
Node.js
- Google Chat에 액세스할 수 있는 Business 또는 Enterprise Google Workspace 계정.
- 결제가 사용 설정된 Google Cloud 프로젝트. 기존 프로젝트에 결제가 사용 설정되어 있는지 확인하려면 프로젝트의 결제 상태 확인을 참조하세요. 프로젝트를 만들고 결제를 설정하려면 Google Cloud 프로젝트 만들기를 참조하세요.
- Node.js 14 이상
- npm 패키지 관리 도구
- 초기화된 Node.js 프로젝트. 새 프로젝트를 초기화하려면 새 폴더를 만들고 전환한 후 명령줄 인터페이스에서 다음 명령어를 실행합니다.
npm init
Python
- Google Chat에 액세스할 수 있는 Business 또는 Enterprise Google Workspace 계정.
- 결제가 사용 설정된 Google Cloud 프로젝트. 기존 프로젝트에 결제가 사용 설정되어 있는지 확인하려면 프로젝트의 결제 상태 확인을 참조하세요. 프로젝트를 만들고 결제를 설정하려면 Google Cloud 프로젝트 만들기를 참조하세요.
- Python 3.6 이상
- pip 패키지 관리 도구
자바
- Google Chat에 액세스할 수 있는 Business 또는 Enterprise Google Workspace 계정.
- 결제가 사용 설정된 Google Cloud 프로젝트. 기존 프로젝트에 결제가 사용 설정되어 있는지 확인하려면 프로젝트의 결제 상태 확인을 참조하세요. 프로젝트를 만들고 결제를 설정하려면 Google Cloud 프로젝트 만들기를 참조하세요.
- Java 11 이상
- Maven 패키지 관리 도구
API 사용 설정
Google API를 사용하려면 Google Cloud 프로젝트에서 API를 사용 설정해야 합니다. 단일 Google Cloud 프로젝트에서 하나 이상의 API를 사용 설정할 수 있습니다.Google Cloud 콘솔에서 Google Chat API 및 Pub/Sub API를 사용 설정합니다.
Pub/Sub 설정
Chat API가 메시지를 전송할 수 있는 Pub/Sub 주제를 만듭니다. Chat 앱당 하나의 주제를 사용하는 것이 좋습니다.
Chat 앱이 Pub/Sub 및 Chat으로 승인할 서비스 계정을 만들고 비공개 키 파일을 작업 디렉터리에 저장합니다.
스크립트 작성
이 섹션에서는 Chat 앱의 애플리케이션 로직을 정의합니다. 사용자가 Chat 앱에 메시지를 보낼 때와 같이 Google Cloud로 인증하고 Pub/Sub 주제를 구독하여 Chat에서 이벤트를 수신하는 스크립트를 작성합니다.
스크립트가 메시지를 수신하면 이벤트 데이터를 처리하고 Google Chat API를 사용하여 사용자 또는 스페이스에 응답을 다시 게시합니다. 이 설정을 사용하면 Chat 앱이 방화벽 뒤에서 작동하면서도 Chat 사용자와 상호작용할 수 있습니다.
Node.js
CLI에서 서비스 계정 사용자 인증 정보를 제공합니다.
export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATHCLI에서 Google Cloud 프로젝트 ID를 제공합니다.
export PROJECT_ID=PROJECT_IDCLI에서 이전에 만든 Pub/Sub 구독의 구독 ID를 제공합니다.
export SUBSCRIPTION_ID=SUBSCRIPTION_ID작업 디렉터리에
package.json이라는 파일을 만듭니다.package.json파일에 다음 코드를 붙여넣습니다.{ "name": "pub-sub-app", "version": "1.0.0", "description": "Google Chat App that listens for messages via Cloud Pub/Sub", "main": "index.js", "scripts": { "start": "node index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { "@google-apps/chat": "^0.4.0", "@google-cloud/pubsub": "^4.5.0" }, "license": "Apache-2.0" }작업 디렉터리에
index.js라는 파일을 만듭니다.index.js에 다음 코드를 붙여넣습니다.const {ChatServiceClient} = require('@google-apps/chat'); const {MessageReplyOption} = require('@google-apps/chat').protos.google.chat.v1.CreateMessageRequest; const {PubSub} = require('@google-cloud/pubsub'); const {SubscriberClient} = require('@google-cloud/pubsub/build/src/v1'); // Receives messages from a pull subscription. function receiveMessages() { const chat = new ChatServiceClient({ keyFile: process.env.GOOGLE_APPLICATION_CREDENTIALS, scopes: ['https://www.googleapis.com/auth/chat.bot'], }); const subscriptionPath = new SubscriberClient() .subscriptionPath(process.env.PROJECT_ID, process.env.SUBSCRIPTION_ID) const subscription = new PubSub() .subscription(subscriptionPath); // Handle incoming message, then acknowledge the received message const messageHandler = message => { console.log(`Id : ${message.id}`); const event = JSON.parse(message.data); console.log(`Data : ${JSON.stringify(event)}`); // Post the response to Google Chat. const request = formatRequest(event); if (request != null) { chat.createMessage(request); } // Acknowledge the message. message.ack(); } subscription.on('message', messageHandler); console.log(`Listening for messages on ${subscriptionPath}`); // Keep main thread from exiting while waiting for messages setTimeout(() => { subscription.removeListener('message', messageHandler); console.log(`Stopped listening for messages.`); }, 60 * 1000); } // Send message to Google Chat based on the type of event function formatRequest(event) { const chatEvent = event.chat || {}; // If the app was removed, we don't respond. if (chatEvent.removedFromSpacePayload) { console.log(`App removed from space.`); return null; } const payload = chatEvent.messagePayload || chatEvent.addedToSpacePayload; const spaceName = payload?.space?.name; if (!spaceName) { console.log('No space name in event.'); return null; } if (chatEvent.addedToSpacePayload) { // An app can also be added to a space by @mentioning it in a // message. In that case, we fall through to the message case // and let the app respond. If the app was added using the // invite flow, we just post a thank you message in the space. return { parent: spaceName, message: { text: 'Thank you for adding me!' }, }; } else if (chatEvent.messagePayload) { // In case of message, post the response in the same thread. const message = chatEvent.messagePayload.message; return { parent: spaceName, messageReplyOption: MessageReplyOption.REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD, message: { text: 'You said: `' + message.text + '`', thread: { name: message.thread.name }, }, }; } } if (!process.env.PROJECT_ID) { console.log('Missing PROJECT_ID env var.'); process.exit(1); } if (!process.env.SUBSCRIPTION_ID) { console.log('Missing SUBSCRIPTION_ID env var.'); process.exit(1); } if (!process.env.GOOGLE_APPLICATION_CREDENTIALS) { console.log('Missing GOOGLE_APPLICATION_CREDENTIALS env var.'); process.exit(1); } receiveMessages();
Python
CLI에서 서비스 계정 사용자 인증 정보를 제공합니다.
export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATHCLI에서 Google Cloud 프로젝트 ID를 제공합니다.
export PROJECT_ID=PROJECT_IDCLI에서 이전에 만든 Pub/Sub 구독의 구독 ID를 제공합니다.
export SUBSCRIPTION_ID=SUBSCRIPTION_ID작업 디렉터리에
requirements.txt라는 파일을 만듭니다.requirements.txt파일에 다음 코드를 붙여넣습니다.google-cloud-pubsub>=2.23.0 google-apps-chat==0.1.9작업 디렉터리에
app.py라는 파일을 만듭니다.app.py에 다음 코드를 붙여넣습니다.import json import logging import os import sys import time from google.apps import chat_v1 as google_chat from google.cloud import pubsub_v1 from google.oauth2.service_account import Credentials def receive_messages(): """Receives messages from a pull subscription.""" scopes = ['https://www.googleapis.com/auth/chat.bot'] service_account_key_path = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS') creds = Credentials.from_service_account_file(service_account_key_path) chat = google_chat.ChatServiceClient( credentials=creds, client_options={'scopes': scopes} ) project_id = os.environ.get('PROJECT_ID') subscription_id = os.environ.get('SUBSCRIPTION_ID') subscriber = pubsub_v1.SubscriberClient() subscription_path = subscriber.subscription_path(project_id, subscription_id) # Handle incoming message, then acknowledge the received message def callback(message): event = json.loads(message.data) logging.info('Data : %s', event) # Post the response to Google Chat. request = format_request(event) if request is not None: chat.create_message(request) # Acknowledge the message. message.ack() subscriber.subscribe(subscription_path, callback = callback) logging.info('Listening for messages on %s', subscription_path) # Keep main thread from exiting while waiting for messages while True: time.sleep(60) def format_request(event): """Send message to Google Chat based on the type of event. Args: event: A dictionary with the event data. """ chat_event = event.get('chat', {}) # If the app was removed, we don't respond. if 'removedFromSpacePayload' in chat_event: logging.info('App removed from space.') return payload = chat_event.get('messagePayload') or chat_event.get( 'addedToSpacePayload' ) space_name = payload.get('space', {}).get('name') if payload else None if not space_name: logging.warning('No space name in event.') return if 'addedToSpacePayload' in chat_event: # An app can also be added to a space by @mentioning it in a # message. In that case, we fall through to the message case # and let the app respond. If the app was added using the # invite flow, we just post a thank you message in the space. return google_chat.CreateMessageRequest( parent = space_name, message = { 'text': 'Thank you for adding me!' } ) elif 'messagePayload' in chat_event: # In case of message, post the response in the same thread. message = chat_event['messagePayload']['message'] return google_chat.CreateMessageRequest( parent = space_name, message_reply_option = google_chat.CreateMessageRequest.MessageReplyOption.REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD, message = { 'text': 'You said: `' + message['text'] + '`', 'thread': { 'name': message['thread']['name'] } } ) if __name__ == '__main__': if 'PROJECT_ID' not in os.environ: logging.error('Missing PROJECT_ID env var.') sys.exit(1) if 'SUBSCRIPTION_ID' not in os.environ: logging.error('Missing SUBSCRIPTION_ID env var.') sys.exit(1) if 'GOOGLE_APPLICATION_CREDENTIALS' not in os.environ: logging.error('Missing GOOGLE_APPLICATION_CREDENTIALS env var.') sys.exit(1) logging.basicConfig( level=logging.INFO, style='{', format='{levelname:.1}{asctime} {filename}:{lineno}] {message}') receive_messages()
자바
CLI에서 서비스 계정 사용자 인증 정보를 제공합니다.
export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATHCLI에서 Google Cloud 프로젝트 ID를 제공합니다.
export PROJECT_ID=PROJECT_IDCLI에서 이전에 만든 Pub/Sub 구독의 구독 ID를 제공합니다.
export SUBSCRIPTION_ID=SUBSCRIPTION_ID작업 디렉터리에
pom.xml이라는 파일을 만듭니다.pom.xml파일에 다음 코드를 붙여넣습니다.<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.google.chat.addon</groupId> <artifactId>pubsub-addon-chat-app</artifactId> <version>0.1.0</version> <name>pubsub-addon-chat-app-java</name> <properties> <maven.compiler.release>11</maven.compiler.release> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>com.google.cloud</groupId> <artifactId>libraries-bom</artifactId> <version>26.41.0</version> <!-- Use a recent BOM version --> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- Google Chat GAPIC library --> <dependency> <groupId>com.google.cloud</groupId> <artifactId>google-cloud-chat</artifactId> </dependency> <!-- Google Cloud Pub/Sub library --> <dependency> <groupId>com.google.cloud</groupId> <artifactId>google-cloud-pubsub</artifactId> </dependency> <!-- Google Apps Add-ons Event Object --> <dependency> <groupId>com.google.apps.addons.v1</groupId> <artifactId>google-apps-addons-v1-java</artifactId> <version>0.2.0</version> <!-- Check for latest version --> </dependency> <!-- Protobuf JSON utility --> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java-util</artifactId> </dependency> <!-- Google Auth Library --> <dependency> <groupId>com.google.auth</groupId> <artifactId>google-auth-library-oauth2-http</artifactId> </dependency> <dependency> <groupId>com.google.api</groupId> <artifactId>gax</artifactId> </dependency> <!-- JSON utilities for PubSub message (if needed, though protobuf-java-util is primary for EventObject) --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.14.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>1.7.36</version> <scope>runtime</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.13.0</version> <configuration> <source>11</source> <target>11</target> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.3.0</version> <configuration> <mainClass>Main</mainClass> </configuration> </plugin> </plugins> </build> </project>작업 디렉터리에서
src/main/java디렉터리 구조를 만듭니다.src/main/java디렉터리에서Main.java라는 파일을 만듭니다.Main.java에 다음 코드를 붙여넣습니다.import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.api.gax.core.FixedCredentialsProvider; import com.google.auth.oauth2.GoogleCredentials; import com.google.chat.v1.ChatServiceClient; import com.google.chat.v1.ChatServiceSettings; import com.google.chat.v1.CreateMessageRequest; import com.google.chat.v1.CreateMessageRequest.MessageReplyOption; import com.google.chat.v1.Message; import com.google.chat.v1.Thread; import com.google.cloud.pubsub.v1.AckReplyConsumer; import com.google.cloud.pubsub.v1.MessageReceiver; import com.google.cloud.pubsub.v1.Subscriber; import com.google.pubsub.v1.ProjectSubscriptionName; import com.google.pubsub.v1.PubsubMessage; import java.io.FileInputStream; import java.util.Collections; public class Main { public static final String PROJECT_ID_ENV_PROPERTY = "PROJECT_ID"; public static final String SUBSCRIPTION_ID_ENV_PROPERTY = "SUBSCRIPTION_ID"; public static final String CREDENTIALS_PATH_ENV_PROPERTY = "GOOGLE_APPLICATION_CREDENTIALS"; public static void main(String[] args) throws Exception { ProjectSubscriptionName subscriptionName = ProjectSubscriptionName.of( System.getenv(Main.PROJECT_ID_ENV_PROPERTY), System.getenv(Main.SUBSCRIPTION_ID_ENV_PROPERTY)); // Instantiate app, which implements an asynchronous message receiver. EchoApp echoApp = new EchoApp(); // Create a subscriber for <var>SUBSCRIPTION_ID</var> bound to the message receiver final Subscriber subscriber = Subscriber.newBuilder(subscriptionName, echoApp).build(); System.out.println("Subscriber is listening to events..."); subscriber.startAsync(); // Wait for termination subscriber.awaitTerminated(); } } /** * A demo app which implements {@link MessageReceiver} to receive messages. * It echoes incoming messages. */ class EchoApp implements MessageReceiver { // Path to the private key JSON file of the service account to be used for posting response // messages to Google Chat. // In this demo, we are using the same service account for authorizing with Cloud Pub/Sub to // receive messages and authorizing with Google Chat to post messages. If you are using // different service accounts, set the path to the private key JSON file of the service // account used to post messages to Google Chat here. private static final String SERVICE_ACCOUNT_KEY_PATH = System.getenv(Main.CREDENTIALS_PATH_ENV_PROPERTY); // Developer code for Google Chat API scope. private static final String GOOGLE_CHAT_API_SCOPE = "https://www.googleapis.com/auth/chat.bot"; private static final String ADDED_RESPONSE = "Thank you for adding me!"; ChatServiceClient chatServiceClient; EchoApp() throws Exception { GoogleCredentials credential = GoogleCredentials.fromStream(new FileInputStream(SERVICE_ACCOUNT_KEY_PATH)) .createScoped(Collections.singleton(GOOGLE_CHAT_API_SCOPE)); // Create the ChatServiceSettings with the app credentials ChatServiceSettings chatServiceSettings = ChatServiceSettings.newBuilder() .setCredentialsProvider(FixedCredentialsProvider.create(credential)) .build(); // Set the Chat service client chatServiceClient = ChatServiceClient.create(chatServiceSettings); } // Called when a message is received by the subscriber. @Override public void receiveMessage(PubsubMessage pubsubMessage, AckReplyConsumer consumer) { System.out.println("Id : " + pubsubMessage.getMessageId()); // Handle incoming message, then acknowledge the received message try { ObjectMapper mapper = new ObjectMapper(); JsonNode dataJson = mapper.readTree(pubsubMessage.getData().toStringUtf8()); System.out.println("Data : " + dataJson.toString()); handle(dataJson); consumer.ack(); } catch (Exception e) { System.out.println(e); // Negative acknowledgement makes Pub/Sub redeliver the message. consumer.nack(); } } // Send message to Google Chat based on the type of event. public void handle(JsonNode eventJson) throws Exception { // Google Chat events for add-ons are wrapped in a 'chat' object. if (!eventJson.has("chat")) { System.out.println("Ignored: Not a Chat event (missing 'chat' field)."); return; } JsonNode chatNode = eventJson.get("chat"); CreateMessageRequest createMessageRequest = null; if (chatNode.has("messagePayload")) { // HANDLE MESSAGE JsonNode messagePayload = chatNode.get("messagePayload"); JsonNode message = messagePayload.get("message"); JsonNode space = messagePayload.get("space"); String spaceName = space.get("name").asText(); String userText = message.has("text") ? message.get("text").asText() : ""; String threadName = message.has("thread") ? message.get("thread").get("name").asText() : ""; System.out.println("Received message in " + spaceName + ": " + userText); createMessageRequest = CreateMessageRequest.newBuilder() .setParent(spaceName) .setMessageReplyOption(MessageReplyOption.REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD) .setMessage( Message.newBuilder() .setText("You said: `" + userText + "`") .setThread(Thread.newBuilder().setName(threadName).build()) .build()) .build(); } else if (chatNode.has("addedToSpacePayload")) { // HANDLE ADDED TO SPACE JsonNode addedPayload = chatNode.get("addedToSpacePayload"); JsonNode space = addedPayload.get("space"); String spaceName = space.get("name").asText(); System.out.println("Added to space: " + spaceName); createMessageRequest = CreateMessageRequest.newBuilder() .setParent(spaceName) .setMessage(Message.newBuilder().setText(ADDED_RESPONSE).build()) .build(); } else if (chatNode.has("removedFromSpacePayload")) { System.out.println("Removed from space."); return; } else { System.out.println("Ignored: Unhandled Chat event type."); return; } if (createMessageRequest != null) { // Post the response to Google Chat. chatServiceClient.createMessage(createMessageRequest); System.out.println("Sent reply."); } } }
Chat 앱 구성
Google Cloud 콘솔에서 Chat 앱을 구성하여 이름 및 아바타와 같은 세부정보를 제공하고 Pub/Sub 주제에 대한 연결을 설정합니다.
Pub/Sub 주제에 연결하면 Chat에서 앱으로 이벤트를 전송할 수 있습니다. 주제를 구독하는 스크립트는 이러한 이벤트를 수신하고 사용자에게 응답할 수 있습니다.
Google Cloud 콘솔에서 메뉴 > API 및 서비스 > 사용 설정된 API 및 서비스 > Google Chat API > 구성으로 이동합니다.
Pub/Sub용 Chat 앱을 구성합니다.
- 앱 이름에
Add-on Chat App을 입력합니다. - 아바타 URL에
https://developers.google.com/workspace/add-ons/images/quickstart-app-avatar.png를 입력합니다. - 설명에
Quickstart app을 입력합니다. - 기능에서 스페이스 및 그룹 대화 참여를 선택합니다.
- 연결 설정에서 Cloud Pub/Sub를 선택하고 이전에 만든 Pub/Sub 주제의 이름을 붙여넣습니다.
- **공개 상태** 에서 도메인의 **특정 사용자 및 그룹에 이 Google Chat 앱을 사용할 수 있도록 설정** 을 선택하고 이메일 주소를 입력합니다.
- 로그에서 오류를 Logging에 로깅을 선택합니다.
- 앱 이름에
저장 을 클릭합니다.
이제 Chat 앱을 구성했으므로 Pub/Sub 구성을 업데이트해야 합니다.
- Chat API 구성 페이지의 연결 설정에서 Google Cloud 프로젝트에 대해 생성된 고유한 이메일인 서비스 계정 이메일을 복사합니다.
- 이전에 복사한 서비스 계정 이메일에 Pub/Sub 게시자 역할을 할당하여 Chat에 주제에 게시할 권한을 부여합니다.
이제 앱에서 Chat의 메시지를 수신하고 응답할 수 있습니다.
스크립트 실행
CLI에서 작업 디렉터리로 전환하고 스크립트를 실행합니다.
Node.js
npm install
npm start
Python
python -m venv env
source env/bin/activate
pip install -r requirements.txt -U
python app.py
자바
mvn compile exec:java -Dexec.mainClass=Main
코드를 실행하면 애플리케이션이 Pub/Sub 주제에 게시된 메시지를 리슨하기 시작합니다.
Chat 앱 테스트
Chat 앱을 테스트하려면 Chat 앱으로 채팅 메시지 스페이스를 열고 메시지를 보냅니다.
신뢰할 수 있는 테스터로 자신을 추가할 때 제공한 Google Workspace 계정을 사용하여 Google Chat을 엽니다.
- 새 채팅 추가를 클릭합니다.
- 1명 이상 추가 필드에 Chat 앱의 이름을 입력합니다.
검색 결과에서 채팅 앱을 선택합니다. 채팅 메시지가 열립니다.
- 앱과의 새 채팅 메시지에서
Hello를 입력하고enter를 누릅니다.
신뢰할 수 있는 테스터를 추가하고 대화형 기능 테스트에 관해 자세히 알아보려면 Google Chat 앱의 대화형 기능 테스트를 참고하세요.
문제 해결
Google Chat 앱 또는 카드가 오류를 반환하면 Chat 인터페이스에 '문제가 발생했습니다.' 또는 '요청을 처리할 수 없습니다.' Chat UI에 오류 메시지가 표시되지 않지만 Chat 앱 또는 카드가 예기치 않은 결과를 생성하는 경우도 있습니다. 예를 들어 카드 메시지가 표시되지 않을 수 있습니다.
Chat UI에 오류 메시지가 표시되지 않더라도 Chat 앱의 오류 로깅이 사용 설정되어 있으면 오류를 해결하는 데 도움이 되는 설명 오류 메시지 및 로그 데이터를 사용할 수 있습니다. 오류를 보고, 디버깅하고, 해결하는 데 도움이 필요하면 Google Chat 오류 문제 해결 및 수정을 참고하세요.
삭제
이 튜토리얼에서 사용한 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 클라우드 프로젝트를 삭제하는 것이 좋습니다.
- Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다. 메뉴 메뉴 > IAM 및 관리 > 리소스 관리 를 클릭합니다.
- 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제 를 클릭합니다.
- 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.
관련 주제
Chat 앱에 더 많은 기능을 추가하려면 다음을 참고하세요.