SW 개발/Kotlin
Spring Boot, Kotlin, Slack 채널 메시지 전송하기
지단로보트
2020. 6. 27. 05:23
개요
- Slack은 아주 편리한 엔터프라이즈 협업 도구이다. 애플리케이션에서도 Slack을 이용하면 장애와 같은 중요한 상황에서 적절한 메시지를 특정 채널에 전송할 수 있다. 이번 글에서는 Slack 연동을 통한 메시지 전송 방법을 소개하고자 한다.
Slack 채널 생성 및 WebHook URL 획득
- Slack에 메시지를 전송하기 위해서는 먼저 채널 생성과 WebHook URL 획득이 선행되어야 한다. 방법은 아래와 같다.
Slack 로그인 → Administration → [Manage Apps] 클릭 → Search App Directory: Incoming WebHooks → [Add to Slack] 클릭
→ (채널을 이미 만들었을 경우) Choose a channel: 생성한 채널 선택
→ (채널을 만들지 않았을 경우) [create a new channel] 클릭 → Name: some-api-error → [Create] 클릭
→ [Add Incoming WebHooks integration] 클릭
→ 생성된 WebHook URL을 복사 (ex: https://hooks.slack.com/services/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)
→ [Save Settings] 클릭
환경 설정 추가
- 프로젝트의 /src/resources/application.yml 파일에 아래 내용을 추가한다. 앞서 획득한 WebHookURL을 연결하는 작업으로 다양한 프로파일에 대한 복수개의 WebHookURL을 설정할 수 있는 장점이 있다.
slack:
webhook-url:
info: https://hooks.slack.com/services/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
warn: https://hooks.slack.com/services/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
error: https://hooks.slack.com/services/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
Slack SDK 연동
- 프로젝트의 /build.gradle 파일에 아래 내용을 추가한다.
dependencies {
compile group: 'com.slack.api', name: 'slack-api-client', version: '1.0.11'
compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.7.2'
}
- Slack SDK는 내부적으로 HTTP 요청시
OkHttp
를 사용하여 통신하여 라이브러리 추가가 필요하다.
Slack 메시지 송신 레벨 정의
- 다양한 상황에 대한 메시지를 전송하기 위해 메시지 송신 레벨을 아래와 같이 정의한다.
enum class SlackMessageLevel {
INFO,
WARN,
ERROR
}
Slack 메시지 전송 서비스 작성
- 이제 메시지 서비스를 작성할 차례이다. 먼저 인터페이스이다.
interface SlackService {
fun sendMessage(fieldMap: Map<String, String>, messageLevel: SlackMessageLevel = SlackMessageLevel.INFO): Future<Boolean>
}
- 다음은 인터페이스에 대한 구현체를 작성할 차례이다.
@Service
@Async("taskExecutor")
class SlackServiceImpl : SlackService {
@Value("\${slack.webhook-url.info}")
private lateinit var SLACK_WEBHOOK_URL_INFO: String
@Value("\${slack.webhook-url.warn}")
private lateinit var SLACK_WEBHOOK_URL_WARN: String
@Value("\${slack.webhook-url.error}")
private lateinit var SLACK_WEBHOOK_URL_ERROR: String
override fun sendMessage(fieldMap: Map<String, String>, messageLevel: SlackMessageLevel): Future<Boolean> {
val slack: Slack = Slack.getInstance()
val webHookUrl = when (messageLevel) {
SlackMessageLevel.INFO -> SLACK_WEBHOOK_URL_INFO
SlackMessageLevel.WARN -> SLACK_WEBHOOK_URL_WARN
SlackMessageLevel.ERROR -> SLACK_WEBHOOK_URL_ERROR
}
val text = StringBuilder().apply {
fieldMap.forEach {
if (it.value != null) {
append("*${it.key}*")
append("\n ${it.value}\n\n")
}
}
}.toString()
val payload = Payload.builder().text(text).build()
val response = slack.send(webHookUrl, payload)
return AsyncResult(response.code == 200)
}
Slack 메시지 전송 예
- 이제 Slack 채널에 메시지를 전송할 차례이다. 사용 예는 아래와 같다.
slackService.sendMessage(MDC.getCopyOfContextMap(), SlackMessageLevel.ERROR)
Spring Boot 애플리케이션 이벤트 연동
- 위 제작된 코드를 응용하면 아래와 같이 Spring Boot 애플리케이션의 시작 시점에도 메시지를 전송할 수 있다.
@Component
class SlackEventListener(
val slackService: SlackService
) {
@EventListener(ApplicationReadyEvent::class)
fun afterApplicationReady() {
MDC.clear()
MDC.put("message", "APPLICATION_STARTED")
MDC.put("environment", CommonUtil.getCurrentEnvironmentName())
MDC.put("application", "some-api")
MDC.put("ip_address", InetAddress.getLocalHost().hostAddress)
slackService.sendMessage(MDC.getCopyOfContextMap(), SlackMessageLevel.INFO)
}
@EventListener(ApplicationFailedEvent::class)
fun afterApplicationFailed() {
MDC.clear()
MDC.put("message", "APPLICATION_STARTUP_FAILED")
MDC.put("environment", CommonUtil.getCurrentEnvironmentName())
MDC.put("application", "some-api")
MDC.put("ip_address", InetAddress.getLocalHost().hostAddress)
slackService.sendMessage(MDC.getCopyOfContextMap(), SlackMessageLevel.ERROR)
}
}