인커밍 웹훅으로 메시지 보내기
인커밍 웹훅으로 메시지 보내기 (Incoming Webhooks)
앱에서 슬랙으로 메시지를 보내는 가장 단순한 방법은 인커밍 웹훅이에요. 인커밍 웹훅을 만들면 고유한 URL이 하나 생기는데, 거기에 메시지 텍스트와 옵션을 담은 JSON 페이로드를 POST로 던져주면 그 글이 슬랙에 올라가요. 복잡한 코드 없이 "딱 메시지를 보내는" 기능만 필요한 상황에 맞는 방식이에요.
시작하기
- 슬랙 앱을 만든다 — 아직 없다면 앱을 새로 만들고 이름과 워크스페이스를 정한 뒤 Create를 눌러요. 테스트 메시지가 많이 쌓일 테니 테스트용 채널을 하나 만들어 두면 편해요.
- 인커밍 웹훅을 활성화한다 — 앱 설정에서 Incoming Webhooks 항목을 찾아 Activate Incoming Webhooks 토글을 켜요.
- 웹훅을 생성한다 — 설정 화면이 갱신되면서 나타나는 Add New Webhook to Workspace 버튼을 눌러요. 그러면 앱 설정의 Webhook URLs for Your Workspace 항목 아래에 웹훅 URL이 등록돼요. 주소는 대략 이렇게 생겼어요:
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
이 URL은 특정 사용자 한 명과 특정 채널 하나에 묶여 있어요. 참고로 GovSlack용 앱을 만든다면 slack.com 대신 slack-gov.com 도메인으로 API 호출을 해야 해요.
- 웹훅 URL로 메시지를 보낸다 — 아래처럼 HTTP POST 요청 하나면 끝이에요. 요청을 보내는 URL은 앞에서 생성한 그 URL과 같아야 해요.
POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Content-type: application/json
{ "text": "Hello, world." }
앱이 설치된 채널을 확인해 보면 "Hello, world" 메시지가 올라가 있는 걸 볼 수 있어요. 요청을 보낼 때 자주 쓰는 HTTP 요청 라이브러리를 cURL 대신 써도 요청 구조는 똑같아요.
주의할 점이 하나 있어요. 인커밍 웹훅은 게시한 메시지를 삭제할 수 없어요. 메시지 삭제가 필요한 더 복잡한 채팅 흐름이라면 chat.postMessage 메서드를 쓰세요.
메시지를 멋지게 꾸미기
페이로드에 blocks 배열을 넣으면 블록 킷(Block Kit) 구성 요소로 메시지를 표현력 있게 꾸밀 수 있어요.
POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Content-type: application/json
{
"text": "Danny Torrence left a 1 star review for your property.",
"blocks": [
{ "type": "section", "text": { "type": "mrkdwn", "text": "Danny Torrence left the following review for your property:" } },
{ "type": "section", "text": { "type": "mrkdwn", "text": "<https://example.com|Overlook Hotel>\n:star:" } }
]
}
인커밍 웹훅으로 메시지를 보낼 때는 기본 채널, 사용자 이름, 아이콘을 덮어쓸 수 없어요. 이 값들은 항상 연결된 슬랙 앱 설정에서 상속돼요.
스레드 답글로 게시하기
인커밍 웹훅으로 메시지를 스레드의 답글(reply)로 만들 수도 있어요. 웹훅 요청에는 ts 값이 반환되지 않으므로, 메시지의 ts 값을 별도로 확보한 뒤 웹훅 요청의 thread_ts 필드로 넣어주면 돼요.
프로그래밍 방식으로 웹훅 URL 생성하기
웹훅 URL을 코드로 만들어야 한다면, OAuth의 scope 목록에 incoming-webhook 권한을 포함해야 해요. 그래야 인증 화면에서 사용자가 웹훅이 게시할 채널을 고를 수 있죠. 인증(OAuth) 응답에 incoming_webhook 객체가 들어오는데, 그 url 필드가 바로 새 웹훅 URL이에요.
{
"ok": true,
"access_token": "xoxp-XXXXXXXX-XXXXXXXX-XXXXX",
"scope": "identify,bot,commands,incoming-webhook,chat:write:bot",
"user_id": "XXXXXXXX",
"team_name": "Your Workspace Name",
"team_id": "XXXXXXXX",
"incoming_webhook": {
"channel": "",
"channel_id": "C05002EAE",
"configuration_url": "https://workspacename.slack.com/services/BXXXXX",
"url": "https://hooks.slack.com/TXXXXX/BXXXXX/XXXXXXXXXX"
}
}
incoming_webhook 객체가 담는 필드를 정리하면:
| Attribute | Type | Description |
|---|---|---|
channel |
String | 사용자가 메시지 목적지로 고른 채널 이름 |
configuration_url |
String | 워크스페이스에 설치된 앱을 설정하는 페이지 링크 |
url |
String | 인커밍 웹훅 URL |
오류 처리
인커밍 웹훅은 Web API보다 더 표현력 있는 오류를 반환해요. HTTP 400 Bad Request, 403 Forbidden, 404 Not Found 같은 상태 코드가 대표적이에요. 자주 만나는 오류 코드를 몇 가지 정리하면:
action_prohibited— 관리자가 메시지 게시를 제한한 상태라, 지금은 요청을 다시 시도하면 안 돼요.channel_is_archived— 지정한 채널이 보관(archive)되어 더는 메시지를 받지 않아요.invalid_payload— 받은 요청이 형식에 어긋나요(JSON 구조가 틀렸거나 텍스트 이스케이프가 잘못된 경우). 고치지 않고 재시도하면 안 돼요.invalid_token— 토큰이 만료·무효·누락됐어요.no_active_hooks— 웹훅이 비활성 상태예요.no_text— 페이로드에text속성이 없어요.too_many_attachments— 첨부가 100개를 넘어요. 메시지의 최대 첨부는 100개예요.posting_to_general_channel_denied— #general 채널에 게시가 제한된 워크스페이스에서 그 채널로 보내려 했을 때 나와요.