자체 호스팅 서버
고객은 자체 하드웨어에서 GameVox를 운영할 수 있고, 봇도 거기서 동작합니다. 클라우드 API가 Discord 형태의 REST와 게이트웨이 이벤트를 고객의 제어 채널로 전달하면, 자체 호스팅 서버가 로컬 데이터베이스에서 실행하고 같은 경로로 응답이 돌아옵니다. 대부분의 엔드포인트는 투명하게 동작하며, 지원되지 않는 것은 아래에 정리했습니다.
동작 방식
봇이 GET /guilds/{id}나 POST /channels/{id}/messages를 호출하면, 클라우드 봇 API가 대상 서버의 등급을 확인합니다. 자체 호스팅이라면 요청(메서드, 경로, 쿼리, 본문, bot_user_id)을 직렬화해, 고객의 서버가 계속 열어 두는 제어 채널 WebSocket으로 보냅니다. 자체 호스팅 프로세스가 자신의 SQLite 데이터베이스에서 같은 핸들러를 실행하고 응답 봉투를 돌려주면, 저희는 그것을 그대로 봇에 전달합니다.
전달은 봇 API 계층에서 이루어지므로 라이브러리는 이를 전혀 알지 못합니다. 다른 토큰도, 다른 게이트웨이 URL도, 다른 SDK도 필요 없습니다. 길드가 클라우드에 있든 자체 호스팅이든, 봇은 같은 gateway.gamevox.com에 연결하고 같은 bot-api.gamevox.com을 호출합니다.
지연
왕복 시간은 고객의 WAN 회선과 SQLite 질의 시간에 좌우되며, 보통 클라우드 호출에 30~300 ms가 더해집니다. 전체 12 초의 기한이 적용됩니다. 자체 호스팅 서버가 응답하지 않으면(오프라인, 업그레이드 중, 네트워크 단절 등) 기한으로부터 1초 안에 봇이 504 Gateway Timeout을 받습니다.
동작하는 것
아래 항목은 모두 자체 호스팅 서버의 로컬 데이터에 대해 실행되며, 클라우드와 같은 응답 형태를 반환합니다.
- 메시지: 목록, 조회, 전송, 편집, 삭제, 일괄 삭제.
- 반응: 추가, 본인 것 제거, 다른 사람 것 제거, 전체 제거, 이모지별 전체 제거, 사용자 목록.
- 고정: 고정, 해제, 목록.
- 입력 표시:
POST /channels/{id}/typing. - 채널: 조회, 수정, 삭제, 목록, 생성, 순서 변경.
- 서버(길드): 조회, 수정(이름과 설명).
- 구성원: 목록, 검색,
@me, 조회, 수정, 별명 변경, 추방, 역할 추가·제거. - 차단: 목록, 조회, 설정, 해제.
- 역할: 목록, 조회, 생성, 수정, 순서 변경, 삭제, 그리고 역할 권한.
- 이모지: 목록, 조회(서버 소유).
- 사운드보드: 목록, 조회(서버 소유).
- 감사 로그:
GET /guilds/{id}/audit-logs. 봇과 관련된 항목만. - 베니티 URL: GET(항상 빈 형태).
- 음성 상태: GET(SFU에서 실시간), PATCH(음소거, 이동, 연결 해제).
- 웹훅: 완전한 CRUD와 실행. 레코드는 클라우드에 저장되고, 만들어진 메시지는 봇 전송과 같은 전달 경로로 자체 호스팅 채널에 기록되므로 채널 표시도 정상적으로 갱신됩니다.
501을 반환하는 것(수용하지만 미구현)
deaf를 담은PATCH .../voice-states/*. 서버에 의한 스피커 음소거는 현재 자체 호스팅 SFU에 없는 기능입니다. 음소거, 이동(channel_id), 연결 해제(channel_id: null)는 모두 동작합니다.PUT .../channels/{id}/permissions/{oid}. 자체 호스팅은 채널별 오버라이드 대신 그룹 단위 권한을 쓰므로 Discord 오버라이드를 적용할 대상이 없습니다.DELETE는204를 반환합니다(없는 오버라이드를 지우는 것은 아무 일도 하지 않습니다).PATCH .../guilds/{id}/vanity-url. 자체 호스팅 서버에는 베니티 URL이 없습니다.
404를 반환하는 것(자체 호스팅으로 라우팅되지 않음)
이 엔드포인트들은 클라우드 인프라에만 존재하는 리소스를 다룹니다. 봇에 필요하다면 클라우드 길드에서 다시 시도하세요.
- 모든
/interactions/*, 후속 응답, 원본 응답 엔드포인트. - 애플리케이션 명령어의 모든 CRUD(
/applications/{id}/commands와 길드용 변형). - DM 채널 생성(
POST /users/@me/channels). - 서버를 넘나드는 사용자 조회(
GET /users/{id},GET /users/by-name/{name}). GET /users/@me/guilds.
게이트웨이 이벤트
자체 호스팅 서버는 클라우드가 내보내는 이벤트 가운데 일부를 게시합니다. 봇은 같은 게이트웨이 세션으로 받으며, 구독 모델도 달라지지 않습니다.
현재 자체 호스팅에서 발생하는 것:
MESSAGE_CREATE,MESSAGE_UPDATE,MESSAGE_DELETE,MESSAGE_DELETE_BULKMESSAGE_REACTION_ADD,MESSAGE_REACTION_REMOVECHANNEL_CREATE,CHANNEL_UPDATE,CHANNEL_DELETECHANNEL_PINS_UPDATEGUILD_UPDATE(이름 / 설명 변경)GUILD_MEMBER_ADD,GUILD_MEMBER_REMOVE,GUILD_MEMBER_UPDATE(별명 또는 역할 변경)GUILD_BAN_ADD,GUILD_BAN_REMOVEGUILD_ROLE_CREATE,GUILD_ROLE_UPDATE,GUILD_ROLE_DELETE(서버의 권한 모델이 바뀔 때 발생)TYPING_STARTVOICE_STATE_UPDATE(참여, 나가기, 본인/서버 음소거, 스피커 음소거)
자체 호스팅에서 아직 발생하지 않는 것:
PRESENCE_UPDATE. 자체 호스팅 쪽에 새로운 프레즌스 브로드캐스터가 필요합니다.- DM 메시지 이벤트. 자체 호스팅에는 서버 간 DM이 없습니다.
INTERACTION_CREATE. 자체 호스팅에서의 명령어 호출은 아직 전달되지 않습니다.
알려진 차이
- 본인 음소거와 서버 음소거: 자체 호스팅 SFU는 Discord처럼
self_mute와mute를 나누지 않고, 참가자마다 음소거 비트를 하나만 둡니다.VOICE_STATE_UPDATE는 같은 값을 두 필드에 모두 넣기 때문에, 서버 음소거를 해제하면 본인 음소거도 함께 해제한 것처럼 보일 수 있습니다. 둘 중 한 필드만 읽는 봇은 문제가 없지만, 두 값을 섞어 상태를 관리하는 봇이라면 조정용 전환에는mute를 우선하는 편이 좋습니다. - 이동은 이벤트를 두 번 발생시킵니다: Discord에서 새
channel_id를 담아voice-states/{uid}에 PATCH하면VOICE_STATE_UPDATE가 한 번만 발생하지만, 자체 호스팅에서는 이동이 나가기 + 다시 참여로 구현되어 대상의channel_id가 잠깐null이 되었다가 새 채널로 바뀝니다. 같은 사용자에 대해 수백 밀리초 안에 연속으로 온 업데이트는 하나의 이동으로 처리하세요.
자체 호스팅 감지하기
현재 guild 객체에는 “자체 호스팅”을 나타내는 플래그가 없습니다(Discord와 바이트 단위로 같게 유지하기 위해서입니다). 봇에서 분기해야 한다면, 위 엔드포인트 중 하나에서 오는 501이나 404가 확실한 신호이며 JSON 오류 본문은 다음과 같습니다.
{ "code": 0, "message": "voice-state modify not supported on self-hosted yet" } 더 가벼운 감지가 필요한 봇이 많아지면 길드 페이로드에 features 항목(예: "SELF_HOSTED")을 추가하겠습니다. 도움이 될 것 같다면 애플리케이션의 지원 탭에서 의견을 남겨 주세요.
오류
502 Bad Gateway. 자체 호스팅 서버가 잘못된 응답을 반환했습니다. 드물며, 대개 업그레이드 중의 버전 불일치입니다.503 Service Unavailable. 제어 채널이 현재 연결되어 있지 않습니다. 백오프를 두고 다시 시도하세요.504 Gateway Timeout. 서버가 12 초 안에 응답하지 않았습니다.