HTTP Google Chat 앱 빌드

이 페이지에서는 HTTP 채팅 앱을 만드는 방법을 설명합니다. 이 아키텍처를 구현하는 방법에는 여러 가지가 있습니다. Google Cloud에서는 Cloud Functions, Cloud Run, App Engine을 사용할 수 있습니다 이 빠른 시작에서는 Chat 앱에서 사용자의 메시지에 응답하는 데 사용하는 Cloud 함수를 작성하고 배포합니다.

이 아키텍처를 사용하면 다음 다이어그램과 같이 HTTP를 사용하여 Google Cloud 또는 온프레미스 서버와 통합되도록 Chat을 구성할 수 있습니다.

온프레미스 서버에서 웹 서비스를 사용하는 채팅 앱 아키텍처

위 다이어그램에서 HTTP(S) 서버와 상호작용하는 사용자는 채팅 앱에는 다음과 같은 정보 흐름이 있습니다.

  1. 사용자가 Chat에서 채팅 메시지 또는 채팅 창 Chat 스페이스.
  2. HTTP 요청은 Chat 앱 로직이 포함된 클라우드 또는 온프레미스 시스템인 웹 서버로 전송됩니다.
  3. 원하는 경우 Chat 앱 로직을 Google Workspace 서비스(예: Calendar, Sheets), 기타 Google 서비스(예: 지도, YouTube, Vertex AI) 또는 기타 웹 서비스(예: 프로젝트 관리 시스템, 티켓 판매 도구)와 통합할 수 있습니다.
  4. 웹 서버는 HTTP 응답을 Chat의 채팅 앱 서비스입니다.
  5. 응답이 사용자에게 전달됩니다.
  6. 채팅 앱에서 선택적으로 Chat API를 사용하여 비동기식으로 메시지를 게시하거나 사용됩니다.

이 아키텍처는 이러한 채팅 앱을 다양한 프로그래밍 언어를 사용하여 설계할 수 있으므로 시스템에 이미 있는 기존 라이브러리와 구성요소를 유연하게 사용할 수 있도록 지원합니다.

목표

  • 환경을 설정합니다.
  • Cloud 함수를 만들고 배포합니다.
  • Chat에 앱을 게시합니다.
  • 앱을 테스트합니다.

기본 요건

환경 설정

Google API를 사용하려면 먼저 Google Cloud 프로젝트에서 사용 설정해야 합니다. 단일 Google Cloud 프로젝트에서 하나 이상의 API를 사용 설정할 수 있습니다.
  • Google Cloud 콘솔에서 Google Chat API, Cloud Build API, Cloud Functions API, Cloud Pub/Sub API, Cloud Logging API, Artifact Registry API, Cloud Run API를 사용 설정합니다.

    API 사용 설정

Cloud 함수 생성 및 배포

발신자의 표시 이름과 아바타 이미지가 포함된 채팅 카드를 생성하는 Cloud 함수를 만들고 배포합니다. 채팅 앱이 메시지를 수신하면 함수를 실행하고 카드로 응답합니다.

채팅 앱을 위한 함수를 만들고 배포하려면 다음 안내를 따르세요. 다음 단계를 완료하세요.

Node.js

  1. Google Cloud 콘솔에서 Cloud Functions 페이지로 이동합니다.

    Cloud Functions로 이동

    Chat 앱의 프로젝트가 선택되어 있는지 확인합니다.

  2. 함수 만들기를 클릭합니다.

  3. 함수 만들기 페이지에서 함수를 설정합니다.

    1. 환경에서 2세대를 선택합니다.
    2. 함수 이름QuickStartChatApp를 입력합니다.
    3. 리전에서 리전을 선택합니다.
    4. 인증에서 인증 필요를 선택합니다.
    5. 다음을 클릭합니다.
  4. 런타임에서 Node.js의 최신 버전을 선택합니다.

  5. 소스 코드에서 인라인 편집기를 선택합니다.

  6. 진입점에서 기본 텍스트를 삭제하고 avatarApp를 입력합니다.

  7. index.js의 내용을 다음 코드로 바꿉니다.

    node/avatar-app/index.js
    // The ID of the slash command "/about".
    // It's not enabled by default, set to the actual ID to enable it. You need to
    // use the same ID as set in the Google Chat API configuration.
    const ABOUT_COMMAND_ID = "";
    
    /**
     * Google Cloud Function that responds to messages sent from a
     * Google Chat space.
     *
     * @param {Object} req Request sent from Google Chat space
     * @param {Object} res Response to send back
     */
    exports.avatarApp = function avatarApp(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.');
      }
    
      // Stores the Google Chat event as a variable.
      const event = req.body;
    
      // Checks for the presence of a slash command in the message.
      if (event.message.slashCommand) {
        // Executes the slash command logic based on its ID.
        // Slash command IDs are set in the Google Chat API configuration.
        switch (event.message.slashCommand.commandId) {
          case ABOUT_COMMAND_ID:
            return res.send({
              privateMessageViewer: event.user,
              text: 'The Avatar app replies to Google Chat messages.'
            });
        }
      }
    
      const sender = req.body.message.sender.displayName;
      const image = req.body.message.sender.avatarUrl;
      const data = createMessage(sender, image);
      res.send(data);
    };
    
    /**
     * Creates a card with two widgets.
     * 
     * @param {string} displayName the sender's display name
     * @param {string} avatarUrl the URL for the sender's avatar
     * @return {Object} a card with the user's avatar.
     */
    function createMessage(displayName, avatarUrl) {
      return {
        text: 'Here\'s your avatar',
        cardsV2: [{
          cardId: 'avatarCard',
          card: {
            name: 'Avatar Card',
            header: {
              title: `Hello ${displayName}!`,
            },
            sections: [{ widgets: [{
              textParagraph: { text: 'Your avatar picture: ' }
            }, {
              image: { imageUrl: avatarUrl }
            }]}]
          }
        }]
      };
    }

  8. 배포를 클릭합니다.

Python

  1. Google Cloud 콘솔에서 Cloud Functions 페이지로 이동합니다.

    Cloud Functions로 이동

    채팅 앱의 프로젝트가 다음과 같은지 확인합니다. 선택합니다.

  2. 함수 만들기를 클릭합니다.

  3. 함수 만들기 페이지에서 함수를 설정합니다.

    1. 환경에서 2세대를 선택합니다.
    2. 함수 이름QuickStartChatApp를 입력합니다.
    3. 리전에서 리전을 선택합니다.
    4. 인증에서 인증 필요를 선택합니다.
    5. 다음을 클릭합니다.
  4. 런타임에서 최신 버전의 Python을 선택합니다.

  5. 소스 코드에서 인라인 편집기를 선택합니다.

  6. 진입점에서 기본 텍스트를 삭제하고 avatar_app를 입력합니다.

  7. main.py의 내용을 다음 코드로 바꿉니다.

    python/avatar-app/main.py
    from typing import Any, Mapping
    
    import flask
    import functions_framework
    
    # The ID of the slash command "/about".
    # It's not enabled by default, set to the actual ID to enable it. You need to
    # use the same ID as set in the Google Chat API configuration.
    ABOUT_COMMAND_ID = ""
    
    @functions_framework.http
    def avatar_app(req: flask.Request) -> Mapping[str, Any]:
      """Google Cloud Function that handles requests from Google Chat
    
      Args:
          flask.Request: the request
    
      Returns:
          Mapping[str, Any]: the response
      """
      if req.method == "GET":
        return "Hello! This function must be called from Google Chat."
    
      request_json = req.get_json(silent=True)
    
      # Checks for the presence of a slash command in the message.
      if "slashCommand" in request_json["message"]:
        # Executes the slash command logic based on its ID.
        # Slash command IDs are set in the Google Chat API configuration.
        if request_json["message"]["slashCommand"]["commandId"] == ABOUT_COMMAND_ID:
          return {
            "privateMessageViewer": request_json["user"],
            "text": 'The Avatar app replies to Google Chat messages.'
          }
    
      display_name = request_json["message"]["sender"]["displayName"]
      avatar = request_json["message"]["sender"]["avatarUrl"]
      response = create_message(name=display_name, image_url=avatar)
      return response
    
    
    def create_message(name: str, image_url: str) -> Mapping[str, Any]:
      """Google Cloud Function that handles requests from Google Chat
    
      Args:
          str name: the sender's display name.
          str image_url: the URL for the sender's avatar.
    
      Returns:
          Mapping[str, Any]: a card with the user's avatar.
      """
      return {
        "text": "Here's your avatar",
        "cardsV2": [{
          "cardId": "avatarCard",
          "card": {
              "name": "Avatar Card",
              "header": { "title": f"Hello {name}!" },
              "sections": [{
                "widgets": [{
                  "textParagraph": { "text": "Your avatar picture:" }
                }, {
                  "image": { "imageUrl": image_url }
                }]
              }]
          }
        }]
      }

  8. 배포를 클릭합니다.

자바

  1. Google Cloud 콘솔에서 Cloud Functions 페이지로 이동합니다.

    Cloud Functions로 이동

    채팅 앱의 프로젝트가 다음과 같은지 확인합니다. 선택합니다.

  2. 함수 만들기를 클릭합니다.

  3. 함수 만들기 페이지에서 함수를 설정합니다.

    1. 환경에서 2세대를 선택합니다.
    2. 함수 이름QuickStartChatApp를 입력합니다.
    3. 리전에서 리전을 선택합니다.
    4. 인증에서 인증 필요를 선택합니다.
    5. 다음을 클릭합니다.
  4. 런타임에서 최신 버전의 Java를 선택합니다.

  5. 소스 코드에서 인라인 편집기를 선택합니다.

  6. 진입점에서 기본 텍스트를 삭제하고 App를 입력합니다.

  7. src/main/java/com/example/Example.java의 이름을 src/main/java/App.java로 바꿉니다.

  8. App.java의 내용을 다음 코드로 바꿉니다.

    java/avatar-app/src/main/java/App.java
    import java.util.List;
    
    import com.google.api.services.chat.v1.model.CardWithId;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Card;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1CardHeader;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Image;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Section;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1TextParagraph;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Widget;
    import com.google.api.services.chat.v1.model.Message;
    import com.google.cloud.functions.HttpFunction;
    import com.google.cloud.functions.HttpRequest;
    import com.google.cloud.functions.HttpResponse;
    import com.google.gson.Gson;
    import com.google.gson.JsonObject;
    
    public class App implements HttpFunction {
      private static final Gson gson = new Gson();
    
      // The ID of the slash command "/about".
      // It's not enabled by default, set to the actual ID to enable it. You need to
      // use the same ID as set in the Google Chat API configuration.
      private static final String ABOUT_COMMAND_ID = "";
    
      @Override
      public void service(HttpRequest request, HttpResponse response) throws Exception {
        JsonObject body = gson.fromJson(request.getReader(), JsonObject.class);
    
        if (request.getMethod().equals("GET") || !body.has("message")) {
          response.getWriter().write("Hello! This function must be called from Google Chat.");
          return;
        }
    
        // Checks for the presence of a slash command in the message.
        if (body.getAsJsonObject("message").has("slashCommand")) {
          // Executes the slash command logic based on its ID.
          // Slash command IDs are set in the Google Chat API configuration.
          JsonObject slashCommand = body.getAsJsonObject("message").getAsJsonObject("slashCommand");
          switch (slashCommand.get("commandId").getAsString()) {
            case ABOUT_COMMAND_ID:
            JsonObject aboutMessage = new JsonObject();
            aboutMessage.addProperty("text", "The Avatar app replies to Google Chat messages.");
            aboutMessage.add("privateMessageViewer", body.getAsJsonObject("user"));
              response.getWriter().write(gson.toJson(aboutMessage));
              return;
          }
        }
    
        JsonObject sender = body.getAsJsonObject("message").getAsJsonObject("sender");
        String displayName = sender.has("displayName") ? sender.get("displayName").getAsString() : "";
        String avatarUrl = sender.has("avatarUrl") ? sender.get("avatarUrl").getAsString() : "";
        Message message = createMessage(displayName, avatarUrl);
        response.getWriter().write(gson.toJson(message));
      }
    
      Message createMessage(String displayName, String avatarUrl) {
        GoogleAppsCardV1CardHeader cardHeader = new GoogleAppsCardV1CardHeader();
        cardHeader.setTitle(String.format("Hello %s!", displayName));
    
        GoogleAppsCardV1TextParagraph textParagraph = new GoogleAppsCardV1TextParagraph();
        textParagraph.setText("Your avatar picture: ");
    
        GoogleAppsCardV1Widget avatarWidget = new GoogleAppsCardV1Widget();
        avatarWidget.setTextParagraph(textParagraph);
    
        GoogleAppsCardV1Image image = new GoogleAppsCardV1Image();
        image.setImageUrl(avatarUrl);
    
        GoogleAppsCardV1Widget avatarImageWidget = new GoogleAppsCardV1Widget();
        avatarImageWidget.setImage(image);
    
        GoogleAppsCardV1Section section = new GoogleAppsCardV1Section();
        section.setWidgets(List.of(avatarWidget, avatarImageWidget));
    
        GoogleAppsCardV1Card card = new GoogleAppsCardV1Card();
        card.setName("Avatar Card");
        card.setHeader(cardHeader);
        card.setSections(List.of(section));
    
        CardWithId cardWithId = new CardWithId();
        cardWithId.setCardId("previewLink");
        cardWithId.setCard(card);
    
        Message message = new Message();
        message.setText("Here's your avatar");
        message.setCardsV2(List.of(cardWithId));
    
        return message;
      }
    }

  9. pom.xml의 내용을 다음 코드로 바꿉니다.

    java/avatar-app/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</groupId>
      <artifactId>avatar-app</artifactId>
      <version>1.0-SNAPSHOT</version>
    
      <properties>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.compiler.source>17</maven.compiler.source>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>com.google.cloud.functions</groupId>
          <artifactId>functions-framework-api</artifactId>
          <version>1.0.1</version>
        </dependency>
    
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.9.1</version>
        </dependency>
    
        <!-- https://mvnrepository.com/artifact/com.google.apis/google-api-services-chat -->
        <dependency>
          <groupId>com.google.apis</groupId>
          <artifactId>google-api-services-chat</artifactId>
          <version>v1-rev20230115-2.0.0</version>
        </dependency>
      </dependencies>
    
      <!-- Required for Java 11 functions in the inline editor -->
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
              <excludes>
                <exclude>.google/</exclude>
              </excludes>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>

  10. 배포를 클릭합니다.

Cloud Functions 세부정보 페이지가 열리고 함수가 두 개의 하나는 빌드와 서비스에 대한 진행률 표시기입니다. 두 진행률 표시기가 모두 사라지고 체크표시로 대체되면 함수가 배포되고 준비된 것입니다.

Google Chat이 함수를 호출하도록 승인하기

Google Chat에서 함수를 호출하도록 승인하려면 Google Chat 서비스 계정에 Cloud Run 호출자 역할을 부여해야 합니다.

  1. Google Cloud 콘솔에서 Cloud Run 페이지로 이동합니다.

    Cloud Run으로 이동

  2. Cloud Run 서비스 목록에서 함수를 사용하세요. 함수 자체를 클릭하지 마세요.

  3. 권한을 클릭합니다. 권한 패널이 열립니다.

  4. 주 구성원 추가를 클릭합니다.

  5. 새 주 구성원에서 chat@system.gserviceaccount.com를 입력합니다.

  6. 역할 선택에서 Cloud Run을 선택합니다. Cloud Run 호출자

  7. 저장을 클릭합니다.

Google Chat에 앱 게시

Cloud 함수를 배포한 후 다음 단계에 따라 Google Chat 앱:

  1. Google Cloud 콘솔에서 메뉴 > Cloud Functions를 클릭합니다.

    Cloud Functions로 이동

    Cloud Functions를 사용 설정한 프로젝트가 선택합니다.

  2. 함수 목록에서 QuickStartChatApp을 클릭합니다.

  3. 트리거 탭을 클릭합니다.

  4. HTTPS에서 URL을 복사합니다.

  5. 'Google Chat API'를 검색합니다. Google Chat API를 클릭한 다음 관리를 클릭합니다.

    Chat API로 이동

  6. 구성을 클릭하고 Google Chat 앱을 설정합니다.

    1. 앱 이름Quickstart App를 입력합니다.
    2. 아바타 URLhttps://developers.google.com/chat/images/quickstart-app-avatar.png를 입력합니다.
    3. 설명Quickstart app를 입력합니다.
    4. 기능에서 1:1 메시지 수신을 선택하고 스페이스 및 그룹 대화에 참여하기
    5. 연결 설정에서 HTTP 엔드포인트 URL을 선택하고 다음에 대한 URL을 붙여넣습니다. Cloud 함수 트리거를 상자에 넣습니다.
    6. 인증 대상에서 HTTP 엔드포인트 URL을 선택합니다.
    7. 공개 상태에서 이 Google Chat 앱을 특정 사용자 및 그룹에 로그인하고 이메일 주소를 입력합니다.
    8. 로그에서 Logging에 오류 로깅을 선택합니다.
  7. 저장을 클릭합니다.

Chat 앱이 Chat에서 메시지를 수신하고 응답할 준비가 되었습니다.

채팅 앱 테스트

채팅 앱을 테스트하려면 다음을 사용하여 채팅 메시지 스페이스를 엽니다. 채팅 앱을 열고 메시지를 보내세요.

  1. 신뢰할 수 있는 테스터로 추가할 때 제공한 Google Workspace 계정을 사용하여 Google Chat을 엽니다.

    Google Chat으로 이동

  2. 새 채팅을 클릭합니다.
  3. 1명 이상 사용자 추가 입력란에 채팅 앱
  4. 검색 결과에서 채팅 앱을 선택합니다. 직접 메시지가 열립니다.

  5. 앱의 새 직접 메시지에 Hello를 입력하고 enter를 누릅니다.

채팅 앱의 응답에는 카드 메시지에 발신자의 이름과 아바타 이미지를 입력합니다.

발신자의 표시 이름과 아바타 이미지가 포함된 카드로 응답하는 Chat 앱

신뢰할 수 있는 테스터를 추가하고 양방향 기능 테스트에 관해 자세히 알아보려면 다음을 참고하세요. Google에서 제공하는 Google Chat 앱.

문제 해결

Google Chat 앱 또는 card가 오류를 반환하는 경우 Chat 인터페이스에 '문제가 발생했습니다'라는 메시지가 표시됨 또는 '요청을 처리할 수 없습니다.' 채팅 UI가 오류 메시지가 표시되지 않지만 채팅 앱 또는 카드에서 예기치 않은 결과가 발생합니다. 예를 들어 카드 메시지가 나타납니다.

채팅 UI에 오류 메시지가 표시되지 않을 수도 있지만 오류 해결에 도움이 되는 오류 메시지 및 로그 데이터를 사용할 수 있음 채팅 앱의 오류 로깅이 사용 설정된 경우 오류를 보고, 디버그하고, 수정하는 방법에 관한 도움말은 Google Chat 오류 문제 해결하기를 참고하세요.

삭제

이 튜토리얼에서 사용한 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 Cloud 프로젝트를 삭제하는 것이 좋습니다.

  1. Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다. 클릭 메뉴 &gt; IAM 및 관리자 &gt; 리소스 관리를 클릭합니다.

    Resource Manager로 이동

  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제 를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 다음 종료를 클릭하여 프로젝트를 삭제합니다.