Backend/Spring Framework
[Spring Boot] Slack 메시지 보내기
mopil
2023. 7. 16. 12:13
반응형
어플리케이션에서 슬랙으로 메시지를 보내는 방법에 대해 공유한다.
토큰을 사용한 봇 방법과 웹훅 방법이 있는데, 여기서는 웹훅 방법을 통해 구현한다.
# 웹훅 만들기
먼저 원하는 워크스페이스로 들어간 다음 웹훅을 생성한다.
add webhook을 누르면 이렇게 채널을 선택할 수 있다. 여기서 대표 채널 하나만 설정하고, 나중에 어플리케이션 레벨에서
하나의 웹 훅으로 여러 채널에서 공유해서 쓸거다.
# SlackClient
@Component
class SlackClient(
private val restTemplate: RestTemplate,
@Value("\${slack.webhook.url}") private val webhookUrl: String,
) {
data class SlackMessage(
val username: String,
val text: String,
@JsonProperty("icon_emoji")
val iconEmoji: String,
val channel: String
)
@Async
fun sendSlack(
senderName: String = "",
message: String,
iconEmoji: String = "",
channel: String
) {
val slackMessage = SlackMessage(
username = senderName,
text = message,
iconEmoji = iconEmoji,
channel = channel
)
val entity = HttpEntity<SlackMessage>(slackMessage)
restTemplate.exchange(webhookUrl, HttpMethod.POST, entity, String::class.java)
}
}
@Value()로 설정파일에 있는 웹훅을 가져온다. 혹시 모르니 시크릿 키처럼 관리하면 좋을 듯하다.
클라이언트 라이브러리는 스프링 내장 RestTemplate를 사용했다. 빈 등록을 해줘야 한다.
슬랙 메시지를 보내는 것은 비동기적으로 처리하도록 Async 어노테이션을 달아줬다.
이는 나중에 예외처리를 할 때 ControllerAdvice에서 처리하지 못하므로, 별도의 예외처리를 해줘야 한다.
각 프로퍼티에 대해 설명하자면,
- senderName : 슬랙봇 이름을 설정한다.
- text : 보낼 메시지
- iconEmoji : 슬랙봇 프로필 이모지. 영문형식으로 :smile: 이렇게 작성하면 슬랙이 자동으로 인식한다. 추가로 슬랙으로는 icon_emoji 형식인 스네이크케이스로 보내야 인식하므로 주의
- channel : 보낼 채널명을 입력. #alert-test이면 alert-test를 적으면 된다. 워크스페이스에 없는 채널명을 입력하면 404 에러가 뜨니 예외처리 해줘야 한다. 채널명은 원래 처음 웹훅을 등록한 채널로 되는데, 이게 오버라이드가 되어서 하나의 웹훅으로 여러 채널로 보낼 수 있다.
# Async 예외 처리
@Async는 ControllerAdvice 전역 예외처리를 할 수 없으므로, 별도의 예외처리 로직을 구현한다.
@Configuration
@EnableAsync
class AsyncConfig : AsyncConfigurer {
override fun getAsyncUncaughtExceptionHandler(): AsyncUncaughtExceptionHandler {
return AsyncUncaughtExceptionHandler { throwable, method, params ->
if (throwable is HttpClientErrorException || throwable is HttpServerErrorException) {
logger.warn("method:${method.name} params:${params.toList()} handleAsyncSlackException: ${throwable.message}")
}
}
}
}
RestTemplate이 요청 서버에서 4xx, 5xx를 받으면 HttpClientErrorException, HttpServerErrorException을 던진다.
이를 적절하게 예외처리 해주면 된다.
# 사용
의존성 주입받아서 사용하면 된다.
@RestController
class TestController(
private val slackClient: SlackClient
) {
@GetMapping(Uris.Test.TEST)
fun test() {
slackClient.sendSlack(
message = "test", channel = "alert-test",
iconEmoji = ":ghost:", senderName = "test")
}
}
반응형