Series/내가 해본

Slack Bot 으로 채널에 글쓰기

Hyunec 2021. 8. 4. 00:15

옛날에 채널에 글을 작성하는 슬랙 연동을 했을 때는 webhook으로 했던 것 같은데, 다시 해보니 잘 안됐습니다.

정확히는 local 에서는 됐지만 github에 올리면 webhook url 이 바뀌는 현상이 발생했습니다.
이상해서 검색해보니 요즘은 slack API 를 연동하는 것이 최신이기도 하고 webhook 보다 다양하게 쓸 수 있을 것 같아서 연동해본 내용을 기록합니다.

사전 조사

 

Using Slack APIs

Every Slack app has access to a bag of tricks—a range of APIs that provide access to read, write, and update all kinds of data in Slack.

api.slack.com

먼저 slack API 사용을 위해서는 어떤 것을 해야 되는지 살펴봅시다.

Post bodies 에서 확인 가능한 example

 

이 example 에서 header의 Authorization에 token 이 들어가야 된다는 것을 확인할 수 있었습니다.

사용 가능한 API들
chat.postMessage: Sends a message to a channel.  가 제가 원하는 API라는 것을 찾을 수 있었습니다.

 

API 발송 준비

1. API 스펙 확인

token과 함께 scope 도 필요한 것을 볼 수 있습니다.

아마 기존에 네이버나 카카오를 연동시켜보신 분이라면 developer 등록하는 절차가 기억나실 겁니다.
slack 도 비슷한 방식으로 내 앱을 등록하고 앱을 통해 토큰을 생성할 수 있습니다.
그러면 bot token 을 만들기 위해 Your Apps 에 가서 app을 만들어봅시다.

 

2. 내 app 생성

앱을 만드실 때 주의할 점을 2개입니다.
Bots으로 선택하고, Permission에서 scope를 주는 것입니다.

 

3. 워크스페이스 & 채널에 연결하기

Install to Workspace를 통해 원하는 워크스페이스에 연결
xoxb로 시작하는 bot token 생성 확인
앱을 채널에 초대

 

4. 발송

POST https://slack.com/api/chat.postMessage
Content-Type: application/json
Authorization: Bearer xoxb-2198502468292-***

{
"channel": "C029T",
"text": "I hope the tour went well, Mr. Wonka."
}

 

마무리

다 연동하고 나서 안 것이지만 기존의 webhook 방식에 문제가 있던 것이 아니었습니다.
문제가 된 부분은 local에서 테스트한 후 webhook url을 public repository에 그대로 push 했고, 그것이 GitGuardian과 slack의 감지 시스템을 통해 차단이 된 것이었습니다. (기존에 했던 작업은 private repository 이어서 생각하지 못한 부분이었습니다.)

이 이슈는 AWS Elastic Beanstalk 에 환경 변수로 넣으면 해결되는 문제이기에 더 이상 개선하지는 않았습니다.
마지막으로 연동한 코드 중 일부를 공유합니다.

@RequiredArgsConstructor
@Service
public class PostMessageService {

    private final String slackBotToken;
    private final WebClient webClient;

    private static final String chatPostMessage = "https://slack.com/api/chat.postMessage";

    public Mono<String> sendChatPostMessage(PostMessageDto postMessageDto) {
        return webClient.post()
            .uri(chatPostMessage)
            .headers(headers -> headers.add(AUTHORIZATION, "Bearer " + slackBotToken))
            .contentType(MediaType.APPLICATION_JSON)
            .bodyValue(postMessageDto)
            .retrieve()
            .bodyToMono(String.class);
    }
}


@Test
public void send() {
    // given
    String webhookTestUrl = "C029******";
    PostMessageDto postMessageDto = PostMessageDto.of(webhookTestUrl, "Test Message");

    // when
    String block = postMessageService
    .sendChatPostMessage(postMessageDto)
    .block();

    // then
    assertThat(block).startsWith("{\"ok\":true");
}