Google Chat 앱과의 상호작용 수신 및 응답

이 페이지에서는 Google Chat 앱이 사용자 상호작용(Google Chat 앱 상호작용 이벤트라고도 함)을 수신하고 이에 응답하는 방법을 설명합니다.

Google Chat 앱 상호작용 이벤트는 채팅 앱을 @멘션하거나 스페이스에 추가하는 등 사용자가 채팅 앱을 호출하거나 상호작용하기 위해 실행하는 모든 작업을 나타냅니다. 사용자가 채팅 앱과 상호작용할 때 Google Chat은 채팅 앱에 상호작용 이벤트를 전송합니다. 채팅 앱은 이벤트를 사용하여 상호작용을 처리하고 응답을 만들 수 있습니다.

예를 들어 채팅 앱은 상호작용 이벤트를 사용하여 다음 작업을 실행합니다.

상호작용 이벤트의 예 채팅 앱의 일반적인 응답
사용자가 @멘션하거나 슬래시 명령어를 사용하여 채팅 앱을 호출합니다. 채팅 앱은 메시지에 나온 내용을 처리하여 메시지를 만듭니다. 예를 들어 채팅 앱은 채팅 앱이 할 수 있는 작업을 설명하는 메시지를 포함하여 /about 명령어에 응답합니다.
사용자가 스페이스에 채팅 앱을 추가합니다. 채팅 앱에서 실행되는 작업과 스페이스의 사용자가 앱과 상호작용할 수 있는 방법을 설명하는 온보딩 메시지를 보냅니다.
사용자가 스페이스에서 채팅 앱을 삭제할 때 채팅 앱은 스페이스용으로 구성된 수신 알림 (예: 웹훅 삭제)을 삭제하고 내부 저장소를 모두 삭제합니다.
사용자가 채팅 앱에서 보낸 카드 또는 대화상자의 버튼을 클릭합니다. 채팅 앱은 사용자가 제출한 데이터를 처리하고 저장하거나 다른 카드 또는 대화상자를 반환합니다.

Google Chat은 사용자 상호작용 유형별로 다른 유형의 상호작용 이벤트를 전송합니다. 예를 들어 Google Chat은 사용자가 메시지에서 채팅 앱을 호출하는 모든 상호작용에 MESSAGE 이벤트 유형을 사용합니다. 자세한 내용은 Google Chat 앱 상호작용 이벤트 유형을 참고하세요.

이 페이지에서는 다음 작업을 수행하는 방법을 설명합니다.

  • 이벤트를 수신하도록 채팅 앱을 구성합니다.
  • 인프라에서 상호작용 이벤트를 처리합니다.
  • 적절한 경우 상호작용 이벤트에 응답합니다.

Chat 앱 상호작용 이벤트 수신

이 섹션에서는 Chat 앱의 상호작용 이벤트를 수신하고 처리하는 방법을 설명합니다.

상호작용 이벤트를 수신하도록 채팅 앱 구성

모든 Chat 앱이 대화형은 아닙니다. 예를 들어 수신 웹훅은 발신 메시지만 보낼 수 있고 사용자에게 응답할 수는 없습니다. 대화형 Chat 앱을 빌드하는 경우 Chat 앱이 상호작용 이벤트를 수신하고, 처리하고, 응답할 수 있게 해주는 엔드포인트를 선택해야 합니다. 채팅 앱 설계에 관한 자세한 내용은 채팅 앱 구현 아키텍처를 참고하세요.

대화형 채팅 앱을 빌드한 경우 Google Chat에서 상호작용 이벤트를 보낼 수 있도록 Google Chat API를 구성해야 합니다.

  1. Google Cloud 콘솔에서 Google Chat API 페이지를 엽니다.

    Google Chat API 페이지로 이동

  2. Configuration 탭을 클릭합니다.
  3. 양방향 기능 섹션에서 양방향 기능 사용 설정 전환 버튼을 클릭하여 사용 위치로 전환합니다.
  4. 기능에서 다음 체크박스 중 하나 또는 둘 다를 선택합니다.
    1. 1:1 메시지 수신: 사용자가 채팅 메시지 (DM) 스페이스에서 채팅 앱과 상호작용할 수 있습니다. 채팅 앱은 사용자가 DM 스페이스에서 메시지를 보낼 때마다 상호작용 이벤트를 수신합니다.
    2. 스페이스 및 그룹 대화 참여: 사용자가 2명 이상의 사용자가 참여 중인 스페이스에 Chat 앱을 추가하거나 삭제할 수 있습니다. 채팅 앱은 스페이스에 추가 또는 삭제될 때마다 또는 사용자가 스페이스에서 @멘션하거나 슬래시 명령어를 사용할 때마다 상호작용 이벤트를 수신합니다.
  5. 연결 설정에서 Google Chat이 Chat 앱 상호작용 이벤트를 보내는 위치를 지정합니다.
  6. 선택사항: 슬래시 명령어에서 슬래시 명령어를 하나 이상 추가하고 구성합니다. 자세한 내용은 슬래시 명령어 설정을 참고하세요.
  7. 선택사항: 링크 미리보기에서 채팅 앱에서 미리 볼 수 있는 URL 패턴을 하나 이상 추가하고 구성합니다. 자세한 내용은 미리보기 링크를 참고하세요.
  8. 저장을 클릭합니다.

이제 채팅 앱이 Google Chat의 상호작용 이벤트를 수신하도록 구성되었습니다.

Google Chat에서 요청 인증하기

HTTP 엔드포인트를 기반으로 빌드된 앱의 경우 이 섹션에서는 엔드포인트에 대한 요청이 Google Chat에서 비롯되는지 확인하는 방법을 설명합니다.

채팅 앱의 엔드포인트에 상호작용 이벤트를 전달하기 위해 Google은 서비스에 요청을 보냅니다. Google에서 보낸 요청인지 확인하기 위해 Google Chat은 엔드포인트에 대한 모든 HTTPS 요청의 Authorization 헤더에 Bearer 토큰을 포함합니다. 예를 들면 다음과 같습니다.

POST
Host: yourappurl.com
Authorization: Bearer AbCdEf123456
Content-Type: application/json
User-Agent: Google-Dynamite

위 예시에서 AbCdEf123456 문자열은 Bearer 승인 토큰입니다. Google에서 생성하는 암호화 토큰입니다. 오픈소스 Google API 클라이언트 라이브러리를 사용하여 Bearer 토큰을 확인할 수 있습니다.

Google Chat 요청에서 전송된 Bearer 토큰의 경우 발급기관은 chat@system.gserviceaccount.com이고 audience 필드는 Chat 앱을 빌드하는 데 사용한 Google Cloud 프로젝트의 번호로 설정됩니다. 예를 들어 채팅 앱의 Cloud 프로젝트 번호가 1234567890이면 Bearer 토큰의 audience 필드는 1234567890입니다.

채팅 앱에서 토큰이 확인되지 않으면 서비스는 HTTPS 응답 코드 401 (Unauthorized)로 요청에 응답해야 합니다.

Java

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager;
import com.google.api.client.http.apache.ApacheHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;

/** Tool for verifying JWT Tokens for Apps in Google Chat. */
public class JWTVerify {
  // Bearer Tokens received by apps will always specify this issuer.
  static String CHAT_ISSUER = "chat@system.gserviceaccount.com";

  // Url to obtain the public certificate for the issuer.
  static String PUBLIC_CERT_URL_PREFIX =
      "https://www.googleapis.com/service_accounts/v1/metadata/x509/";

  // Intended audience of the token, which is the project number of the app.
  static String AUDIENCE = "1234567890";

  // Get this value from the request's Authorization HTTPS header.
  // For example, for "Authorization: Bearer AbCdEf123456" use "AbCdEf123456"
  static String BEARER_TOKEN = "AbCdEf123456";

  public static void main(String[] args) throws GeneralSecurityException, IOException {
    JsonFactory factory = new JacksonFactory();

    GooglePublicKeysManager.Builder keyManagerBuilder =
        new GooglePublicKeysManager.Builder(new ApacheHttpTransport(), factory);

    String certUrl = PUBLIC_CERT_URL_PREFIX + CHAT_ISSUER;
    keyManagerBuilder.setPublicCertsEncodedUrl(certUrl);

    GoogleIdTokenVerifier.Builder verifierBuilder =
        new GoogleIdTokenVerifier.Builder(keyManagerBuilder.build());
    verifierBuilder.setIssuer(CHAT_ISSUER);
    GoogleIdTokenVerifier verifier = verifierBuilder.build();

    GoogleIdToken idToken = GoogleIdToken.parse(factory, BEARER_TOKEN);
    if (idToken == null) {
      System.out.println("Token cannot be parsed");
      System.exit(-1);
    }

    // Verify valid token, signed by CHAT_ISSUER.
    if (!verifier.verify(idToken)
        || !idToken.verifyAudience(Collections.singletonList(AUDIENCE))
        || !idToken.verifyIssuer(CHAT_ISSUER)) {
      System.out.println("Invalid token");
      System.exit(-1);
    }

    // Token originates from Google and is targeted to a specific client.
    System.out.println("The token is valid");
  }
}

Python

import sys

from oauth2client import client

# Bearer Tokens received by apps will always specify this issuer.
CHAT_ISSUER = 'chat@system.gserviceaccount.com'

# Url to obtain the public certificate for the issuer.
PUBLIC_CERT_URL_PREFIX = 'https://www.googleapis.com/service_accounts/v1/metadata/x509/'

# Intended audience of the token, which will be the project number of the app.
AUDIENCE = '1234567890'

# Get this value from the request's Authorization HTTPS header.
# For example, for 'Authorization: Bearer AbCdEf123456' use 'AbCdEf123456'.
BEARER_TOKEN = 'AbCdEf123456'

try:
  # Verify valid token, signed by CHAT_ISSUER, intended for a third party.
  token = client.verify_id_token(
      BEARER_TOKEN, AUDIENCE, cert_uri=PUBLIC_CERT_URL_PREFIX + CHAT_ISSUER)

  if token['iss'] != CHAT_ISSUER:
    sys.exit('Invalid issuee')
except:
  sys.exit('Invalid token')

# Token originates from Google and is targeted to a specific client.
print 'The token is valid'

서비스에 대한 HTTP 호출 재시도 처리

서비스에 대한 HTTPS 요청이 실패하면 (예: 시간 초과, 일시적인 네트워크 장애, 2xx가 아닌 HTTPS 상태 코드) Google Chat에서 몇 분 내에 전송을 다시 시도할 수 있습니다 (단, 보장되지는 않음). 따라서 채팅 앱은 특정 상황에서 동일한 메시지를 몇 번 받을 수 있습니다. 요청이 성공적으로 완료되었지만 잘못된 메시지 페이로드가 반환되면 Google Chat은 요청을 재시도하지 않습니다.

상호작용 이벤트 처리 또는 응답

이 섹션에서는 Google Chat 앱이 상호작용 이벤트를 처리하고 이에 응답하는 방법을 설명합니다.

채팅 앱이 Google Chat에서 상호작용 이벤트를 수신하면 다양한 방식으로 응답할 수 있습니다. 대부분의 경우 대화형 Chat 앱은 사용자에게 메시지로 응답합니다. Google Chat 앱은 데이터 소스에서 일부 정보를 조회하거나, 상호작용 이벤트 정보를 기록하거나, 그 외 어떤 작업도 할 수 있습니다. 이 처리 동작은 본질적으로 Google Chat 앱을 정의하는 것입니다.

각 상호작용 이벤트에 대해 채팅 앱은 이벤트를 나타내는 JSON 페이로드인 요청 본문을 수신합니다. 이 정보를 사용하여 응답을 처리할 수 있습니다. 이벤트 페이로드의 예시는 채팅 앱 상호작용 이벤트 유형을 참조하세요.

다음 다이어그램은 Google Chat 앱이 일반적으로 다양한 유형의 상호작용 이벤트를 처리하거나 이에 응답하는 방법을 보여줍니다.

Google Chat 앱이 상호작용 이벤트를 처리하는 방식의 아키텍처

실시간 대답

상호작용 이벤트를 사용하면 채팅 앱이 실시간 또는 동기식으로 응답할 수 있습니다. 동기 응답에는 인증이 필요하지 않습니다.

상호작용 이벤트에 대한 동기식 응답을 만들려면 다음 가이드를 참고하세요.

동기식으로 응답하려면 채팅 앱이 30초 이내에 응답해야 하고 응답이 상호작용이 발생한 스페이스에 게시되어야 합니다. 그러지 않으면 채팅 앱이 비동기식으로 응답할 수 있습니다.

비동기식으로 응답

채팅 앱은 30초 후에 상호작용 이벤트에 응답하거나 상호작용 이벤트가 생성된 스페이스 외부에서 작업을 실행해야 하는 경우가 있습니다. 예를 들어 채팅 앱은 장기 실행 작업을 완료한 후 사용자에게 응답해야 할 수 있습니다. 이 경우 채팅 앱은 Google Chat API를 호출하여 비동기식으로 응답할 수 있습니다.

Chat API를 사용하여 메시지를 만들려면 메시지 만들기를 참조하세요. 추가 Chat API 메서드 사용에 대한 가이드는 Chat API 개요를 참조하세요.