discord-api

Discord API

Discord API는 여러분이 만든 **봇(bot)**이나 **앱(app)**이 Discord에 연결해 서버에서 일어나는 일을 듣고, 메시지를 보내고, 명령어에 응답할 수 있게 해 주는 공식 개발 인터페이스예요. 봇은 서버에 APP 태그를 단 봇 유저로 등장해서 이벤트를 감지하고, 슬래시 명령어(slash command)에 반응하고, 서버를 관리하고, 메시지를 전송하는 등 다양한 일을 여러분의 코드로 처리할 수 있어요.

Discord 앱이 Discord에 연결하는 방식은 크게 두 가지예요. 하나는 실시간 이벤트를 받는 Gateway WebSocket이고, 다른 하나는 별도의 상시 연결 없이 슬래시 명령어나 UI 컴포넌트를 처리하는 HTTP 인터랙션 엔드포인트예요. 대부분의 봇은 쓰임새에 따라 둘 중 하나 또는 둘 다를 조합해서 사용해요.

봇의 전형적인 쓰임새는 서버 관리 도구, 서버 유틸리티, 게임, 외부 서비스와의 연동, 자동화 워크플로 등 다양해요. 만약 채널에 메시지를 넣기만 하면 되는 경우라면 완전한 봇보다 **웹훅(webhook)**이 더 적합할 수 있어요. 웹훅은 설정이 훨씬 간단하고 리치 임베드(embed)를 담은 메시지를 보낼 수 있지만, 봇처럼 이벤트를 듣거나 인터랙션에 응답할 수는 없어요.

출처: 문서

본문

봇(Bot) 만들기

봇은 가장 흔한 타입의 Discord 앱이에요. 봇은 Gateway WebSocket으로 실시간 이벤트를 받을 수도 있고, HTTP 인터랙션 엔드포인트로 슬래시 명령어와 UI 컴포넌트에 응답할 수도 있어요. Discord API의 기본 주소는 https://discord.com/api/v10이에요.

봇을 만드는 첫걸음 순서는 크게 이렇게 돼요:

  1. Discord Developer Portal에서 애플리케이션을 만들고 Bot 탭에서 봇 유저를 추가해요.
  2. Bot 토큰을 발급받아요. 이 토큰은 봇의 비밀번호 같은 것이므로 절대 공개하면 안 돼요.
  3. 봇을 추가하고 싶은 서버(guild)에 OAuth2 인증 URL로 초대해요.
  4. 코드에서 토큰을 사용해 Gateway에 연결하거나 REST API를 호출해요.

Gateway

Gateway API는 앱이 Discord와 보안 WebSocket 연결을 열어 서버(guild)에서 일어나는 동작(채널이 업데이트되거나 역할이 생성되는 등)에 대한 이벤트를 받을 수 있게 해 주는 실시간 통신 수단이에요. 대부분의 REST 작업은 HTTP API로 처리할 수 있고, Gateway는 주로 실시간 알림을 받는 데 쓰여요.

Gateway 이벤트는 앱과 Discord 사이 오가는 페이로드(payload)예요. 모든 Gateway 이벤트는 하나의 이벤트 페이로드로 캡슐화돼요. 예시:

{
  "op": 0,
  "d": {},
  "s": 42,
  "t": "GATEWAY_EVENT_NAME"
}
  • op — opcode(명령 종류)예요.
  • d — 이벤트 데이터예요.
  • s — 시퀀스 번호로, 하트비트와 재연결(Resume)에 사용돼요.
  • t — 디스패치 이벤트의 이름이에요.

Gateway 연결 주기는 대략 이렇게 돌아가요:

  1. Get Gateway 또는 Get Gateway Bot 엔드포인트로 WSS URL을 가져와 캐시해요.
  2. Discord가 하트비트 주기를 담은 Hello(opcode 10) 이벤트를 보내요.
  3. 앱이 하트비트(Heartbeat, opcode 1)를 주기마다 보내고, Discord는 Heartbeat ACK(opcode 11)로 응답해요.
  4. 앱이 Identify(opcode 2)로 최초 핸드셰이크를 하고, Discord가 Ready(opcode 0)를 보내면 연결이 성립돼요.
  5. 연결이 끊기면 Resume(opcode 6)으로 재개하거나 처음부터 다시 연결해요.

연결 URL은 보통 이렇게 되어요:

wss://gateway.discord.gg/?v=10&encoding=json

인텐트(Intents): 대부분의 이벤트는 앱이 Identify할 때 인텐트를 정의해야 받을 수 있어요. 인텐트는 비트 값이라서 |(OR) 연산으로 원하는 이벤트 묶음을 표시할 수 있어요. 굳이 상시 WebSocket 연결이 필요 없다면 REST API나 인터랙션으로 충분한 경우가 많아요.

인터랙션과 슬래시 명령어

**인터랙션(Interaction)**은 사용자가 앱과 소통하는 방식이에요. **애플리케이션 명령어(Application Command)**는 Discord 클라이언트 안에서 앱과 상호작용하는 기본적인 방법으로, 세 가지 타입이 있어요:

  • CHAT_INPUT (type 1) — 슬래시 명령어로, /명령어 형식이에요.
  • USER (type 2) — 사용자를 우클릭했을 때 나오는 컨텍스트 메뉴 명령어예요.
  • MESSAGE (type 3) — 메시지를 우클릭했을 때 나오는 컨텍스트 메뉴 명령어예요.

명령어는 HTTP 엔드포인트로만 등록할 수 있어요. 글로벌(global) 명령어는 모든 서버에 적용되고, 길드(guild) 명령어는 특정 서버에만 즉시 적용돼요. 개발 중에는 길드 명령어로 빠르게 테스트하고, 공개할 때는 글로벌 명령어로 전환하는 걸 권장해요.

글로벌 슬래시 명령어를 등록하는 예시:

import requests

url = "https://discord.com/api/v10/applications/<my_application_id>/commands"

# 이건 type 1인 CHAT_INPUT, 즉 슬래시 명령어 예시예요
json = {
    "name": "blep",
    "type": 1,
    "description": "Send a random adorable animal photo",
    "options": [
        {
            "name": "animal",
            "description": "The type of animal",
            "type": 3,
            "required": True,
            "choices": [
                {"name": "Dog", "value": "animal_dog"},
                {"name": "Cat", "value": "animal_cat"},
                {"name": "Penguin", "value": "animal_penguin"}
            ]
        },
        {
            "name": "only_smol",
            "description": "Whether to show only baby animals",
            "type": 5,
            "required": False
        }
    ]
}

# 인증에는 봇 토큰을 쓰거나
headers = {"Authorization": "Bot <my_bot_token>"}
# 아니면 applications.commands.update 스코프의 client credentials 토큰을 써요
headers = {"Authorization": "Bearer <my_credentials_token>"}

r = requests.post(url, headers=headers, json=json)

길드 명령어는 스코프만 특정 guild_id로 바꿔서 등록해요:

url = "https://discord.com/api/v10/applications/<my_application_id>/guilds/<guild_id>/commands"

명령어는 같은 타입과 스코프 안에서 이름이 고유하기 때문에, 같은 이름으로 다시 POST하면 기존 명령어를 **업데이트(upsert)**해요. 삭제는 DELETE, 수정은 PATCH 호출로 해요.

임베드(Embed)

임베드는 메시지에 풍부한(리치) 형식의 콘텐츠를 담아 보여주는 구조예요. 색상, 제목, 설명, 푸터, 필드 등을 이용해 예쁘고 읽기 쉬운 메시지를 만들 수 있어요. 임베드 객체(Embed Object)의 주요 필드는 다음과 같아요:

Field Type Description
title? string 임베드의 제목
description? string 임베드의 설명
url? string 임베드의 URL
timestamp? ISO8601 timestamp 임베드 내용의 타임스탬프
color? integer 임베드의 색상 코드
footer? embed footer object 임베드의 푸터 정보
fields* array of embed field 임베드의 필드 목록
{
  "embeds": [
    {
      "title": "안녕하세요, Discord API",
      "description": "이것은 임베드 예시입니다.",
      "color": 7506394,
      "fields": [
        {
          "name": "필드 이름",
          "value": "필드 값",
          "inline": true
        }
      ]
    }
  ]
}

임베드는 봇이 메시지를 보낼 때 embeds 배열로 전달하거나, 웹훅으로도 보낼 수 있어요. 임베드는 메시지 하나에 여러 개 넣을 수 있고, 서버 관리 알림이나 게임 결과 표시 같은 곳에 아주 유용해요.

사용 예시 요약

  • 메시지 보내기: POST /channels/{channel.id}/messages — 봇 토큰으로 인증.
  • 슬래시 명령어 등록: POST /applications/{application.id}/commands — 로컬 또는 길드 스코프.
  • 실시간 이벤트 수신: wss://gateway.discord.gg/?v=10&encoding=json — Gateway WebSocket 연결.
  • 임베드: /messages 전송 시 embeds 배열에 담아 보냄.
  • 간단한 메시지 전송만 필요할 때: 완전한 봇 대신 웹훅 사용 권장.

성숙한 커뮤니티 라이브러리(discord.js, discord.py 등)를 쓰면 Gateway 연결과 인텐트, 재연결 같은 복잡한 부분을 많이 줄일 수 있어요. 다만 커스텀 구현을 직접 하려면 Gateway 문서를 끝까지 꼼꼼히 읽어야 해요.

더 알아보기 (Learn more)