이벤트 API
이벤트 API (Events API)
슬랙에서 어떤 일이 일어났을 때 우리 앱이 "알아서" 반응하게 만들려면 이벤트 API가 필요해요. 이벤트 API를 쓰면 우리가 계속 확인하러 다닐 필요 없이, 슬랙이 우리를 호출해요. 사용자가 메시지를 보내거나 리액션을 달았을 때 Slack이 우리 서버로 이벤트를 JSON으로 보내주고, 우리는 그걸 받아 응답하면 되는 구조예요. 봇이나 앱이 슬랙 안에서 벌어지는 활동에 반응하게 만들 때 가장 기본이 되는 축이에요.
이벤트 수신 방식 두 가지
이벤트를 받는 방법은 두 가지예요. **소켓 모드(Socket Mode)**를 쓰거나, 앱이 리슨하는 공개 HTTP 엔드포인트를 지정하는 방법이에요. 이후 어떤 이벤트를 구독할지 정하면 Slack이 해당 이벤트를 우리에게 보내줘요.
이벤트 API가 돌아가는 흐름
- 사용자가 어떤 상황을 만들어 이벤트 구독을 트리거해요.
- 우리 서버가 그 이벤트를 설명하는 JSON 페이로드를 받아요.
- 우리 서버가 이벤트 수신을 인지(acknowledge)해요.
- 비즈니스 로직이 그 이벤트로 무엇을 할지 정해요.
- 우리 서버가 그 결정을 실행해요.
예를 들어 봇이 속한 #random 채널에서 누군가 오늘의 비밀 단어가 담긴 메시지를 보내면, 우리 서버는 message.channels 이벤트를 받고 HTTP 200 OK로 재빠르게 응답해요. 봇이 비밀 단어를 감지하면 chat.postMessage API 메서드로 채널에 격려 메시지를 보내는 식이에요. 이렇게 웹 API를 이벤트 API와 함께 쓰면 단순히 듣고 답하는 것보다 훨씬 많은 걸 할 수 있어요.
앱을 준비하기
권한 모델
이벤트 API는 Slack의 객체 기반 OAuth 스코프 체계를 그대로 이용해 접근을 제어해요. 예를 들어 files:read 스코프로 파일에 접근할 수 있다면, file_created·file_deleted 같은 파일 관련 이벤트를 구독할 수 있어요. 그리고 우리 앱을 인가한 사용자가 자기 워크스페이스에서 "볼 수 있는" 이벤트만 받아요. 비공개 채널 기록 접근을 인가했다면, 그 사용자가 멤버인 비공개 채널의 활동만 보이지 워크스페이스 전체의 비공개 채널 활동이 보이는 건 아니에요.
이벤트 종류 구독하기
앱 설정의 Event Subscriptions를 켜고 구독을 추가하면 돼요. 구독 종류는 두 가지로 나뉘어요:
- 워크스페이스 이벤트(Workspace Events) — 해당하는 OAuth 스코프가 필요하고, 앱을 설치하는 사용자 관점에서 바라보는 이벤트예요.
- 봇 이벤트(Bot Events) — 앱의 봇 사용자 입장에서 구독해요.
bot스코프 외에 추가 스코프가 필요 없어요.
일부 이벤트 종류는 봇 사용자 구독에서 지원되지 않을 수 있으니, 특정 이벤트의 문서 페이지에서 봇 사용자 지원 여부를 확인해야 해요.
이벤트 수신하기
구독한 이벤트가 발생하면 Slack이 우리 request URL로 Content-Type: application/json 형식의 HTTP POST 요청을 보내요. 이벤트 콜백 페이로드는 대략 이렇게 생겼어요:
{
"type": "event_callback",
"token": "XXYYZZ",
"team_id": "T123ABC456",
"api_app_id": "A123ABC456",
"event": { "type": "name_of_event", "event_ts": "1234567890.123456", "user": "U123ABC456", ... },
"event_context": "EC123ABC456",
"event_id": "Ev123ABC456",
"event_time": 1234567890,
"authorizations": [ { "enterprise_id": "E123ABC456", "team_id": "T123ABC456", "user_id": "U123ABC456", "is_bot": false, "is_enterprise_install": false } ],
"is_ext_shared_channel": false,
"context_team_id": "T123ABC456",
"context_enterprise_id": null
}
주요 콜백 필드를 정리하면:
| Field | Type | Description |
|---|---|---|
type |
String | 어떤 콜백인지 나타내요. 보통 event_callback이고, 설정 과정에서는 url_verification을 만날 수 있어요. |
token |
String | Slack 요청 검증용이었지만 이제 **폐기(deprecated)**됐어요. 대신 서명된 시크릿(signed secret)으로 요청을 검증해야 해요. |
team_id |
String | 이벤트가 발생한 워크스페이스의 고유 식별자예요. |
api_app_id |
String | 이벤트가 향하는 앱의 고유 ID예요. 페이로드에서 우리 앱을 식별하고 싶을 때 보는 필드예요. |
event |
Event | 실제 일어난 이벤트의 내부 필드를 담는 이벤트 봉투(envelope)예요. |
event_id |
String | 이 특정 이벤트의 고유 식별자로, 전체 워크스페이스를 통틀어 전역 고유해요. |
event_time |
Integer | 이벤트가 전송된 시각의 epoch 초 단위 값이에요. |
authorizations |
Object | 이 이벤트가 보이는 앱 설치(installation) 중 하나예요. 여러 사용자를 위한 데이터라면 사용자별 메시지 대신 이벤트 하나로 받아요. 모든 인가(설치)를 가져오려면 apps.event.authorizations.list API 메서드를 써요. |
내부 event 필드에는 실제 이벤트 종류가 담겨요. 예를 들어 이모지 리액션 이벤트는 이렇게 생겼어요:
{
"token": "z26uFbvR1xHJEdHE1OQiO6t8",
"team_id": "T123ABC456",
"api_app_id": "A123ABC456",
"event": {
"type": "reaction_added",
"user": "U123ABC456",
"item": { "type": "message", "channel": "C123ABC456", "ts": "1464196127.000002", "channel_type": "channel" },
"reaction": "slightly_smiling_face",
"item_user": "U222222222",
"event_ts": "1465244570.336841"
},
"type": "event_callback",
"authorizations": [ { "enterprise_id": "E123ABC456", "team_id": "T123ABC456", "user_id": "U123ABC456", "is_bot": false } ],
"event_id": "Ev123ABC456",
"event_context": "EC123ABC456",
"event_time": 1234567890
}
구버전 RTM API에 익숙하다면, 안쪽 event 구조는 그때와 동일한데 이벤트 봉투로 감싸져 온다고 보면 돼요. event_ts는 이벤트 시각, user는 그 동작을 일으킨 사용자 ID, ts는 이벤트가 설명하는 대상의 시각을 나타내는 식이에요.
이벤트에 응답하기
각 이벤트에는 검증, 재시도, 레이트 리밋 규칙이 적용돼요. 자세한 정책은 각 이벤트 문서와 이벤트 API의 오류 처리·지연 이벤트 재시도 섹션을 확인해야 해요. 레이트 리밋이 걸리면 app_rate_limited 같은 이벤트가 먼저 우리 앱에 알려져요.