미라클 모닝 챌린지 슬랙 봇 3 - 슬랙 모달 입력하기

김지욱·2021년 8월 6일
1

지난 포스트에서 슬랙앱과 연동까지 성공했었다. 이번에는 Botl 메서드를 이용해서 모달창을 만들고 입력 결과를 보내는 과정에 대해서 다루어 보겠습니다.

Todo List

  • 슬랙으로 문제 알림 전송
  • 메시지 클릭 시 문제 모달 화면
  • 문제 답 입력 후 결과 메시지 전송

#슬랙으로 알림 전송

슬랙으로 메시지를 보내는 기본적인 방법은 슬랙 api에서 제공하는 chat.postMessage를 사용해서 보낼 수 있다. post 요청으로 토큰, 채널명 등의 정보를 담아서 보내면 해당 채널로 메시지를 전송해 주는 방식이다.

하지만 Bolt 메서드를 사용해서 조금 더 편한 방법으로 메시지를 보낼 수 있다.

지난 포스팅에서 Initialize 까지 완료를 했었다.

const { App } = require('@slack/bolt');

const slackApp = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET,
  socketMode: true,
  appToken: process.env.SLACK_APP_TOKEN
});

slackApp.message('hello', async ({ message, say }) => {
  await say(`Hey there <@${message.user}>!`);
});

(async () => {
  await slackApp.start(process.env.PORT || 3000);
  console.log('⚡️ Bolt app is running!');
})();

#Block Kit?

단순히 메시지를 보내기만 하는 것이 아니라 버튼을 만들고 클릭 이벤트를 통해서 모달을 보이게 해야 했었다. 그래서 사용한 것이 Block Kit이다.

Block Kit은 다양한 형식의 슬랙 메시지를 보낼 수 있도록 만들어 준다. button, input, image 등의 다양한 기능들을 활용하기 쉽다.

Block Kit Builder의 예시를 보면 바로 이해할 수 있다. 원하는 조합을 만들어서 샘플 메시지와 코드를 미리 보기 할 수 있다.

그럼 이제 이렇게 만든 메시지를 보내보자.

slackApp.client.chat.postMessage({
    channel: "challenge",
    text: `☀️ Good Morning`,
    blocks: [
      {
        type: "section",
        text: {
          type: "mrkdwn",
          text: `☀️ Good Morning`,
        },
        accessory: {
          type: "button",
          text: {
            type: "plain_text",
            text: "오늘의 문제",
          },
          action_id: "morning_button",
        },
      },
    ],
  });

client.chat.postMessage 를 사용해서 객체에 보낼 메시지의 정보를 담아주면 된다.

channel : 메시지를 보낼 채널명

text: 알림이 올 때 표시될 내용

그리고 Block Kit Builder를 통해 만든 코드를 blocks에 입력해 준다.

여기서 중요한 건 버튼에 있는 action_id 부분이다. 이것을 통해서 해당 버튼을 클릭했다는 식별자 역할을 해준다.

이렇게 하면 아래와 같이 메시지가 보내진다. 아직은 오늘의 문제를 클릭해도 아무런 반응이 없다.

#모달 입력

app.action('morning_button', async ({ ack }) => {});

action 메서드를 사용해서 버튼 클릭과 같은 액션을 받을 수 있다.

slackApp.action("morning_button", async ({ body, ack, say, client }) => {
    await ack();
    try {
      const result = await client.views.open({
        trigger_id: body.trigger_id,
        view: {
          type: "modal",
          callback_id: "morning_modal",
          title: {
            type: "plain_text",
            text: "미라클 모닝 챌린지",
          },
          blocks: [
            {
              type: "section",
              text: {
                type: "mrkdwn",
                text: "오늘의 문제.",
              },
            },
            {
              type: "input",
              block_id: "question",
              label: {
                type: "plain_text",
                text: "1 + 1 = ?",
              },
              element: {
                type: "plain_text_input",
                action_id: "answer",
              },
            },
          ],
          submit: {
            type: "plain_text",
            text: "Submit",
          },
        },
      });
      console.log(result);
    } catch (error) {
      console.error(error);
    }
  });

모달을 띄어주는 코드이다.

views.open 메서드를 사용해서 모달을 열 수 있다. 버튼은 action_id가 식별자 역할을 했는데 모달은 callback_id가 그 역할을 해준다.

제출 버튼을 누르면 입력 값을 확인해서 결과를 보내주어야 한다.

#최종 결과 확인

모달에서 제출한 입력 값을 받아오기 위해서는 view 메서드를 사용한다.

slackApp.view("morning_modal", async ({ ack, body, view, client }) => {
    await ack();
    const question = view.blocks[1]["label"]["text"];
    const answer = view["state"]["values"]["question"]["answer"]["value"];
    const user = body.user.name;
    const result = "정답입니다."

    try {
      await client.chat.postMessage({
        channel: "challenge",
        text: `${user}${result}`,
      });
    } catch (error) {
      console.error(error);
    }
  });

view 객체에 위의 blocks에서 작성한 내용들이 담겨있다.

입력한 값을 확인하고 postMessage로 결과를 전송해준다.

완성된 화면

결과 메시지만 보내기는 심심한 느낌이 있어서 마감 메시지 알림으로 랜덤 명언(?)과 고양이 사진을 추가해서 마무리해주었다.

여기까지 슬랙 봇 기능 구현은 끝이 났다. 이제 마지막으로 배포하는 일만 남았다. 다음 포스팅에서는 serverless 프레임워크를 이용해서 aws 람다 배포를 하는 과정에 대해 정리해 볼 예정이다.

참고

0개의 댓글