2025. 1. 15. 14:26ㆍ개발
팀에서 신규 Slack을 사용하면서 기존 Spring 어플리케이션에서 사용하는 Webhook URL을 변경할 일이 생겼다.
일반적으로 Slack Webhook URL은 1개의 채널과 바인딩되지만 신규 Slack으로 이전하면서 Webhook URL은 개발환경/운영환경 2개로 구분 운영하기로 했다.
1개의 Webhook URL로 여러 채널에 알림을 보내기 위해서는 채널 구분이 필요해 기존 코드를 수정해야했는데
현재 사용 중인 slack-api-client에서 채널을 구분하기 위해서는 Payload 클래스의 deprecated된 channel() 메소드를 사용해야 했다.
AS-IS
public class SlackService {
@Value("${logging.slack.webhook-uri}")
private String webhookUri;
@Value("${logging.slack.channel}")
private String channel;
public void send(String message) {
try {
String text = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + message;
WebhookResponse response = Slack.getInstance().send(webhookUri, Payload.builder()
.channel(channel) // deprecated
.text(text)
.build());
log.info("[슬랙] 알림 발송 성공, 응답 코드 : {}, 응답 메시지 : {}, 응답 body : {}", response.getCode(), response.getMessage(), response.getBody());
} catch (Exception e) {
log.error("[슬랙] 알림 발송 실패 : {}", e.getMessage());
}
}
}
deprecated된 메소드를 사용하는게 찝찝하기도 하고 Bot Token도 따로 운영중이었기 때문에 수정하는 김에 Bot Token을 사용하는 방식으로 변경했다.
TO-BE
public class SlackService {
@Value("${logging.slack.bot-token}")
private String botToken;
@Value("${logging.slack.channel}")
private String channel;
public void send(String message) {
try {
String text = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + message;
ChatPostMessageRequest request = ChatPostMessageRequest.builder()
.channel(channel)
.text(text)
.build();
ChatPostMessageResponse response = Slack.getInstance()
.methods(botToken)
.chatPostMessage(request);
log.info("[슬랙] 알림 발송 성공, 응답 코드 : {}, 응답 메시지 : {}", response.getError(), response.getMessage());
} catch (Exception e) {
log.error("[슬랙] 알림 발송 실패 : {}", e.getMessage());
}
}
}
변경 후 알림 발송 테스트를 하자 아래 예외가 발생했다.
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
찾아보니 원인은 다양하지만 대부분은 통신 대상의 인증서 문제로 발생하는 듯 했다.
Java는 내부적으로 CA의 공개키 인증서들이 저장된 Truststore라는 저장소를 관리하는데 SSL/TLS 통신시 상대(서버/클라이언트) 신뢰를 검증하기 위해 해당 저장소를 사용한다.
쉽게 말해 상대 서버가 Truststore에는 없는 신뢰할 수 없는 인증서를 가지고 있어서 발생하는 문제.
chatPostMessage(ChatPostMessageRequest req)를 추적하면 내부적으로 slack.com으로 API를 호출하고 있다.

slack.com의 인증서를 Truststore에 추가하기 위해서 아래 과정이 필요하다.(Mac기준)
1. 인증서 추출
echo | openssl s_client -showcerts -connect slack.com:443 2>/dev/null | openssl x509 -outform PEM > slack_cert.pem
2. Java Truststore에 인증서 추가
keytool -import -file slack_cert.pem -keystore $JAVA_HOME/lib/security/cacerts -alias slack -storepass changeit
3. 추가된 인증서 확인
keytool -list -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit | grep slack
인증서 추가 후에 다시 변경된 코드를 실행해보면 정상적으로 알림이 발송된다.
문제는 개발/운영환경 배포시 혹은 slack.com 인증서 갱신시 Truststore에 추가하도록 자동화 해야하는데, 신뢰할 수 없는 인증서를 추가한다는게 deprecated된 메소드를 쓰는 것 만큼이나 찝찝하다.

결국 고민 끝에 Webhook url만 변경하고 deprecated된 channel 메소드를 쓰기로 결정했다.
비즈니스 로직과 크게 상관없는 알림이라 크리티컬하지도 않고 기본적인 ERROR 알림 또한 따로 전달받고 있으니 괜찮겠지..
정신 승리해버리기
'개발' 카테고리의 다른 글
| [알고리즘] DFS(Depth First Search) 깊이 우선 탐색 (0) | 2024.07.08 |
|---|