API 연동
참고자료
이전 강의 자료를 찾아보아도 됐지만 Bot이 채널이 아닌 개인에게 Direct Message로 알림을 전달해야하기 때문에 공식 문서를 참고하여 진행했다.
Bolt
Slack 에서는 Java 환경에서 제공하는 API를 간단하게 사용할 수 있도록 Bolt라는 라이브러리를 제공한다. 사용해보니 간편하고 통신에 대한 설정을 생략할 수 있어서 금방 적용할 수 있었다. 하지만 학습했던 MSA 기술들을 사용하기 위해 OpenFeign을 사용하여 직접 HTTP 통신하는 방법을 진행했다.
Direct Message 가능한지?
Workspace에 참가되어있는 Bot이 다른 사용자에게 DirectMessage를 보내는 기능을 하는 API를 공식 문서에서 찾아볼 수 없었다. 무조건 채널을 거쳐야 가능하다고 나와있었고 많은 포스팅에서도 같은 답변을 했다. 포기하려는 무렵에 stact overflow에서 아주 감사하게도 해결책을 설명하는 답변을 찾을 수 있었다. slack이 제공하는 api중에 conversations.open
를 통해서 개인과의 채널을 열 수 있고, 그 이후에 그 채널 id를 chat.postMessage
에서 지정해주면 dm이 가능했다. 이것으로 보아 채널이라는 표현 안에 대화 방식이 여러개 포함되어 있는 것 같다.
users.lookupByEmail
→ conversations.open
→ chat.postMessage
트러블 슈팅
문제 상황
Slack API를 사용해 이메일로 유저 정보를 조회하려고 했지만, {"ok":false,"error":"invalid_auth"}
응답이 돌아왔다. OpenFeign을 이용한 HTTP 통신을 구현했으나, IntellJ .http
테스트에서 문제가 없었음에도 불구하고 발생한 문제였다.
원인 및 해결 과정
1. 요청 데이터 전달 확인
로그를 찍어 이메일과 토큰이 정상적으로 전달되는지 확인했지만, 데이터 전달에는 문제가 없었다.
2. Header로 Token 전달
token
Authentication token bearing required scopes. Tokens should be passed as an HTTP Authorization header or alternatively, as a POST parameter.
API 문서에서 토큰의 전달방식을 Authorization 헤더에 포함시키는 방법도 제시가 되어있어 헤더에 토큰을 추가해봤지만 실패했다. 토큰 데이터의 예시로 xxxx-xxxxxxxxx-xxxx
라고 나와있지만 혹시 몰라서 토큰 앞에 Bearer
을 포함해보았고, bot 타입에 해당하는 문자열을 제거하는 등 토큰을 변형하여 시도했지만 응답은 동일했다.
3.Bot 권한(Scope) 설정 확인
API에 필요한 users:read.email
권한이 누락되었을 가능성을 확인했으나, 정상적으로 설정되어 있었다.
골뱅이
4. 이메일 인코딩 문제 확인
이메일 주소(test@test.com
)가 전달될 때 골뱅이(@
)가 인코딩 이슈가 발생하지는 않았는지 테스트 하기 위해 .http
파일에서 골뱅이(@
)를 URL 인코딩(%40
)으로 대체해 테스트해본 결과, 문제가 없었음을 확인했다.
5. 요청 환경의 차이점 분석
반대로 IntelliJ가 성공하는게 이상한 것이 아닐까? 라는 생각이 들어, Talend와 Postman으로 테스트해보았는데 실패했다. IntelliJ만 통신에 성공이 되는 이유가 무었일까 고민하다가, 요청시 User-Agent
같이 헤더에 차이가 있는 부분을 반영해 테스트했으나 실패했다. Redirect 처리 방식이 차이가 있을 수 있겠다고 가정하고, Talend에서 Follow Redirects 옵션 추가 후 재시도했으나 실패했다.
6. Content-Type 확인
놓치고 부분이 뭐가 있을까 하고 생각하다가 제일 친숙하지 않은 Content-Type: application/x-www-form-urlencoded
을 조사를 해보았다. 알고보니 HTTP Body로 데이터를 전달해야 했지만, GET 메소드 API여서 당연히 QueryString 으로 전달할거라고 생각하고 있어 문제가 발생했음을 깨달았다.
최종 해결
1. HTTP Body 전달 방식으로 수정
Talend에서 인수를 HTTP Body로 전달하자 정상 응답을 받을 수 있었다.
2. Feign Client 설정 변경
Feign Client에서 @RequestBody
로 전달을 시도했으나, 기본 설정으로는 x-www-form-urlencoded
인코딩이 지원되지 않았다. 가이드 자료를 참고해 Spring Form Encoder를 Bean으로 등록했다.
3. DTO 대신 Map 사용
Config 클래스를 FeignClient 어노테이션에 지정해주고 테스트를 해보았는데, 새로운 응답 내용을 받을 수 있었다.
{"ok":false,"error":"not_authed","warning":"superfluous_charset","response_metadata":{"warnings":["superfluous_charset"]}}
인코딩을 진행할때 SpringFormEncoder
가 직렬화를 위해 DTO를 지원하지 않아, 대신 Map<String, String>
사용해야 했다. 로직을 변경한 후, Slack ID를 성공적으로 응답받을 수 있었다.