Slack App 만들기

[Slack App] 슬랙 앱 만들기 - event, action, command, shortcut, method

dohye1 2023. 1. 23. 21:41
반응형

슬랙 앱을 만들땐, view만 구성하는것이아니라, 슬랙이라는 수단을 통해 실제 사용자와 데이터를 주고받는것이 목적일것이다.

 

그래서 서버와 slack app에서 정보를 주고받을수있는 수단이 있는데,

그 종류는 event, action, method, command, shortcut등이 있다.

 

이 이벤트들을 설정하기전에 사전적으로 정해야할것이 있는데,

0. Socket Mode

앱을 나의 workspace에서만 쓸거라면 소켓모드를 on하면 된다.

하지만 앱을 실제로 app directory에 올려서 public하게 쓰고싶다면

socket mode를 끄고 http 요청을 통해서 슬랙앱-서버가 통신하도록 해야한다.

socket mode를 끄고 작업하는것은 여기를 참고하시라

socket mode켠 상태에서 작업하다가 껐을때, 수정할건 많지않으니 그냥 socket mode 를 켠 상태에서 작업을 다 하고 나중에 변경해줘도 되긴함!!

 

1. event 

event는 슬랙 앱에서 발생하는 특정한 행위를 서버로 알려준다.

가장 간단하고 기본적인 event은 app_home_opened이 있다.

이 이벤트는 이름 그대로 사용자가 앱의 홈에 진입했을때 발생하고, 진입하는 시점에 서버로 이벤트를 보내고, 서버는 이에 대한 처리로 app home화면을 publish하면 된다.

 

slack에서 발생하는 이벤트는 여기에 모두 정리되어있다.

여기에 정의되어있는 이벤트만 받을수있기때문에, 필요한것들을 찾아서 쓰면 된다.

 

앱에 내가 받을 이벤트를 등록할때는 아래처럼 app에 이벤트를 등록하면 된다.

공식문서에 콜백의 인자로 넘어오는값이 정리되어있으니, 필요한 값을 찾아서 쓰면된다.

(근데 실제로 넘어오는값과, 공식문서에 정리되어있는 값이 일치하지않는 이벤트도 있기때문에, 콘솔을 찍어보면서 해야하는경우도있었음....^_^;;)

// When a user joins the team, send a message in a predefined channel asking them to introduce themselves
app.event('team_join', async ({ event, client, logger }) => {
  try {
    // Call chat.postMessage with the built-in client
    const result = await client.chat.postMessage({
      channel: welcomeChannelId,
      text: `Welcome to the team, <@${event.user.id}>! 🎉 You can introduce yourself in this channel.`
    });
    logger.info(result);
  }
  catch (error) {
    logger.error(error);
  }
});

그리고 아래의 사진에서 보이는것처럼 특정 이벤트마다 Required scopes라는것이 있다.

없는 이벤트도 있지만, 만약 Required scopes가 있는 이벤트라면 앱의 dashboard > oauth&permisstions 탭에 들어가서 Bot Token Scopes&User Token Scopes에 추가를 해야한다.

권한을 추가하면 앱을 다시설치하라는 알림이 뜰때가있으니 만약 알림이뜬다면 그 알림에서 시키는대로 하면됨!!

그리고 여기서 중요한거!!!!!!

코드상에서 app.event("?")를 추가한다고해서 이벤트를 받을수있는게 아니라,

위의 왼쪽 사진에 보이는 Event Subscriptions 탭에 들어가서 내가 실제로 쓸 events들을 선택해야한다.

(내가 이거땜에 삽질진짜 많이함ㅠㅜㅠㅜㅠㅜ 이벤트가 안받아와져서ㅠㅜ)

이렇게 이벤트를 추가하면 Required Scope가 옆에 나오는데, 저거보고 oauth&permisstions에서 추가해도된다!

 

아무튼 이렇게 이벤트수신 처리를 해주면, 실제로 내가 지정한 이벤트가 발생했을때, 서버로 이벤트가 넘어온다.

 

2. action

액션은 custom하게 설정한 actionId를 가지고있는 interactive component가 사용자에 의해 trigger되었을때, 서버는 동일한 actionId를 가진 액션함수를 실행시킨다.

await ack()는 무조건 호출해야함. 여기를 참고하시라

// Your listener function will be called every time an interactive component with the action_id "approve_button" is triggered
app.action('approve_button', async ({ ack }) => {
  await ack();
  // Update the message to reflect the action
});

예를들어 

view의 코드가 아래와 같을때 

HomeTab()
    .privateMetaData(JSON.stringify(metaData ?? {}))
    .blocks(
      Blocks.Actions().elements([
        Button()
          .text("Receive")
          .primary(globalFilter === GlobalFilter.RECEIVED)
          .actionId("RECEIVED_FILTER"),
        Button()
          .text("Send")
          .primary(globalFilter === GlobalFilter.SENT)
          .actionId("SENT_FILTER"),
        Button()
          .text("Watcher")
          .primary(globalFilter === GlobalFilter.WATCHER)
          .actionId("WATCHER_FILTER"),
      ]),
      ...

각 버튼은 고유한 actionId를 가지고있는데, 

저 버튼이 눌렸을때 저 actionId와 동일하게 등록되어있는 액션의 콜백함수가 호출된다!

app.action("RECEIVED_FILTER", async ({ ack }) => {
  await ack();
  // received filter에 대한 처리
});

app.action("SENT_FILTER", async ({ ack }) => {
  await ack();
  // sent filter에 대한 처리
});

app.action("WATCHER_FILTER", async ({ ack }) => {
  await ack();
  // watcher filter에 대한 처리
});

3. method

그리고 가장 중요한 method가 있는데,

이 method는 앱의 기능을 담당하는 핵심적인 부분이다.

 

method의 종류는 여기에서 보면된다.

event, action, command, shortcut의 콜백의 인자에 client라는 객체가 들어있는데, 이 client를 통해 모든 method에 접근 가능하다.

 

그래서 사용자가 앱에 들어왔을때에 app_home_opened이벤트의 콜백함수에 client.views.publish(VIEW_OBJECT)를 호출하면 앱의 홈 화면이 그려진다.

 

그리고 각 method 마다 Required scopes가 있는데, 이러한 scope는 아까 위에서 말했던것처럼 oauth&permission 페이지에서 설정하면된다.

그리고 아래 이미지를 보면 bot token의 권한과, user token의 권한이 다른걸 볼 수 있는데,

내가 어떤 토큰을 사용해서 앱 기능을 제공하는가에 따라 권한의 범위가 달라진다!

(웬만한건 봇토큰으로 가능했었어서 난 bot token의 oauth만 추가함)

그리고 각 method의 디테일 페이지에 인자값과 결과값이 자세히 적혀있으니 꼼꼼히 읽어보고 쓰면된다!!

4. command

command는 슬랙 대화창에서  / (slash)를 입력하면 슬랙앱을 검색할 수 있는 팝업이 뜬다.

내가만든 슬랙앱에서도 command를 통해 간편한 기능을 제공하고싶다면 

app dashboard > slash commands 탭에 들어가서 create command를 누르면 오른쪽의 화면이 켜진다.

command - 실제로 사용자에게 제공하고싶은 command(만약 다른 앱의 command와 겹친다면 사용자가 해당 command에 어떤 앱이 실행되도록할지 선택한다고함)

request url - 이 값은 socket mode가 on일때는 설정안해줘도 됐었는데, socket mode를 끄니 나옴. 이 부분은 여기를 참고하세요.

short description - command를 쳤을때 보여지는 내 앱에 관한 설명

usage hint - 만약 command와 같이 추가적인 데이터를 받고싶을땐 아래의 사진처럼 받을 데이터의 인자이름을 적어주면된다.

그럼 사용자가 command를 입력하면 오른쪽 사진처럼 힌트가 보여진다.

 

 

그런데 데이터가 내가 정한 usage hint와 순서가 짝지어서 서버로 넘어오는게아니라, 사용자가 입력한 command 전체가 하나의 문자열로 넘어오기때문에 서버에서 데이터를 알아서 분리해서 사용해야한다!

 

그리고 만약 사용자나 채널명의 id를 같이 command로 받고싶다면 Escape channels, users, and links sent to your app 옵션을 on해야한다.

off일때는 @user #general이런 형태로 데이터가 넘어오고

on일때는 <@U1234|user> <#C1234|general> 이렇게 user나 channel의 id도 같이 넘어오기때문에 id를 활용할 수 있음!!

 

그리고 코드상에서 아래처럼 command를 등록해줘야한다.

여기서 주의할것 

🚨command의 첫번째 인자에 무조건 /(slash)를 붙여줘야함🚨

// The echo command simply echoes on command
app.command('/echo', async ({ command, ack, respond }) => {
  // Acknowledge command request
  await ack();

  await respond(`${command.text}`);
});

5. shortcut

이 기능은 아래의 사진을보면 바로 이해될것이다.

(이 사진은 공식홈페이지에서 가져온 사진임)

 

shortcut은 global shortcut/message shortcut이 있는데,

global shortcut은 왼쪽 사진에서 아래쪽에 있는 + 버튼을 눌렀을때 슬랙앱을 실행할 수 있는 기능이고,

message shortcut은 특정 메시지에 hover시 보여지는 오른쪽 상단의 더보기 버튼을 눌렀을때 슬랙앱을 실행할 수 있는 기능이다.

global shortcut/message shortcut

이 기능을 추가하는 방법을 알아보자

앱 대시보드 > interactivity & shortcuts 페이지에 들어가보면 shortcut을 등록할 수 있고, 생성버튼을 누르면 shortcut의 타입을 선택하는 페이지가 나온다.

name과 short desc를 입력해주고, callbackId를 적어줘야하는데, callbackId가 서버에서 인지하는 shortcut의 이름이니 unique하게 적어줘야한다!!!

// The open_modal shortcut opens a plain old modal
app.shortcut('open_modal', async ({ shortcut, ack, client, logger }) => {

  try {
    // Acknowledge shortcut request
    await ack();

    // Call the views.open method using one of the built-in WebClients
    const result = await client.views.open({
      trigger_id: shortcut.trigger_id,
      view: {
      	...
       }
    });

    logger.info(result);
  }
  catch (error) {
    logger.error(error);
  }
});

 

그리고 앱에 shortcut을 등록해주면 되는데 여기서 주의할점

🚨shortcut의 첫번째 인자에 /(slash)를 붙이면 안됨🚨

🚨command엔 붙이고 shortcut엔 붙이면안됨!!!!!!!!🚨

내가 이거땜에 삽질겁나함

 

이정도만 알아도 웬만한 기능은 구현할 수 있다!