본문 바로가기
[개발] Info/소개

Slack과 스프링 앱 연동하기

by Devsong26 2023. 11. 15.

스프링 앱에서 경보성 알림을 이메일이나 메신저로 발송하여 개발자가 이슈를 개선하도록 공지합니다.

 

회사에서 많이 사용하는 슬랙을 스프링 앱과 연동하여 메시지를 발송해보려고 합니다.

 

슬랙 의존성 라이브러리도 있으나 버전 관리등을 직접적으로 해야 하므로 관리 책임을 지우지 않기 위해

RESTful API를 이용한 메시지 전송 방식을 선택했습니다.

 

우선 슬랙 워크스페이스와 연결할 앱을 만들어야 합니다.

 

https://api.slack.com/apps 에 접속합니다.

 

 

From scratch를 선택합니다.

 

App Name과 워크스페이스를 입력하고 'Create App' 버튼을 누릅니다.

 

 

생성한 앱의 'OAuth & Permissions' 메뉴 > Scopes 영역으로 이동합니다.

'Add an OAuth Scope' 버튼을 입력하고 'chat:write'를 선택합니다.

 

OAuth & Permissions 메뉴 > 'OAuth Tokens for Your Workspace' 영역으로 이동합니다.

'Install to Workspace' 버튼을 눌러 워크스페이스에 앱을 연결합니다.

 

 

위의 과정이 완료되면 OAuth Tokens for Your Workspace 영역에 Bot User OAuth Token 이 생성됩니다.

 

워크스페이스에서 생성된 앱을 확인한 후 앱에 채널을 추가합니다.

 


 

이제 자바 코드를 개발하겠습니다.

 

@Immutable
@Component("slackNotiBot")
public class SlackNotiBot {

    private final String botToken = "#{botToken}";
    
    private final RestTemplate restTemplate = new RestTemplate();

    private final String channelId = "#{channelId}";
    
    public void notify(String message){
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(botToken);

        String body = "{\"channel\":\"" + channelId + "\", \"text\":\"" + message + "\"}";
        HttpEntity<String> request = new HttpEntity<>(body, headers);

        String response = restTemplate.postForObject("https://slack.com/api/chat.postMessage", request, String.class);
        System.out.println(response);
    }

}

 

성공 시 아래 응답을 받습니다.

warning으로 "missing_charset"이 표시되는데 MediaType.APPLICATION_JSON_UTF8이 deprecated 되어 있어 사용하지 않았습니다.

{
  "ok": true,
  "channel": "#{channelId}",
 ...
  "message": {
    ...
    "type": "message",
    "text": "TEST DEV MESSAGE",
    ...   
  },
  "warning": "missing_charset",
  "response_metadata": {
    "warnings": [
      "missing_charset"
    ]
  }
}

 

하지만 아래와 같은 실패 응답을 받게 된다면 봇 앱에 채널을 추가하시면 해결됩니다.

채널에 봇이 추가되어 있지 않아 발생하는 실패 케이스입니다.

{
    "ok": false,
    "error": "not_in_channel"
}