개요
디스코드 봇은 Discord API와 WebSocket연결을 기반으로 동작하는 Event-driven(이벤트기반) 라이브러리이다.
디스코드상에서 이뤄지는 모든 이벤트는 실시간으로 감지를 할 수 있는데, 모든 이벤트를 상시적으로 감시하게 되면 당연히 리소스의 낭비가 심해진다. 또한 모든 이벤트에 대해 감지를 함으로써 민감한 데이터에 접을 할 수 있는 경우가 생길 수 있다.
이러한 이유로 인해 DiscordAPI v8부터는 개발자 인증제도와 Gateway Intent가 도입이 되었는데, 봇을 개발하다 보면 이 부분으로 인해 가끔 작동되어야 할 부분이 작동되지 않는 경우가 발생하기도 한다.
그렇다면 Gateway Intent는 도대체 무엇일까?
Gateway Intent란?
Discord Gateway Intent는 봇을 개발할 때, 봇이 Discord 서버에서 어떤 이벤트를 받을지 설정하는 기능이다. Intent를 통해 필요한 이벤트만 수신해서 리소스를 절약하고, 개인 정보 보호와 관련된 데이터를 제한적으로 받게 하는 기능이다.
Discord API에서는 이벤트를 몇 가지 그룹으로 나누어 Intent라는 형태로 관리하고 있다.
예를 들어:
- 메시지 이벤트만 필요하면 MESSAGE_CREATE 관련 Intent만 활성화하면 된다.
- 유저 상태(온라인/오프라인) 관련 데이터가 필요하면 PRESENCE_UPDATE Intent를 사용한다.
JavaScript에서 Intent 설정
(1) Discord.js를 사용할 때
Discord.js는 Intent를 미리 정의해 둔 GatewayIntentBits로 관리한다. 봇을 초기화할 때 필요한 Intent를 배열로 넘겨줄 수 있다.
아래는 인텐트를 부여하는 예제이다.
const { Client, GatewayIntentBits } = require("discord.js");
const client = new Client({
intents: [
GatewayIntentBits.Guilds, // 서버(Guild) 관련 이벤트
GatewayIntentBits.GuildMessages, // 메시지 관련 이벤트
GatewayIntentBits.MessageContent // 메시지 내용 접근
]
});
client.once("ready", () => {
console.log(`Logged in as ${client.user.tag}`);
});
client.login("your_bot_token");
(2) WebSocket을 통해 직접 구현할 때
WebSocket을 직접 사용할 경우, Identify 메시지에 비트 플래그로 Intent 값을 설정한다.
const WebSocket = require("ws");
const ws = new WebSocket("wss://gateway.discord.gg/?v=10&encoding=json");
const BOT_TOKEN = "your_bot_token";
const INTENTS = (1 << 0) | (1 << 9); // GUILDS + MESSAGE_CREATE
ws.on("open", () => {
const identifyPayload = {
op: 2,
d: {
token: BOT_TOKEN,
intents: INTENTS,
properties: {
$os: "linux",
$browser: "my_library",
$device: "my_library"
}
}
};
ws.send(JSON.stringify(identifyPayload));
console.log("Identify Payload Sent");
});
사실상 Discord.js 나 Discord.py 등 과 같이 보통은 잘 완성된 라이브러리 통해서 봇을 구현하게 될 것이다.
그러나 굳이 WebSocket을 통해 보여준 의도는 Intents의 상세한 작동 구조에 대해 설명을 할 필요가 있기 때문이다.
잘 보면 WebSocket의 방법에는 const INTENTS = (1 << 0) | (1 << 9); 라는 구문이 보이는데 구문에서 << 나 >>는 비트 시프트 연산자로 자세한 내용은 아래 블로그 글에서 정리를 해뒀다.
[Javascript] 비트 시프트 연산자 <<, >> (BitWise Shift <<, >>)
개요자바스크립트에서는 다양한 연산자가 있다. & (AND 논리 연산자)| (OR 논리 연산자)^ (배타 논리 연산자)~ (부정 논리 연산자)>> (오른쪽 비트 시프트 연산자)>>> (부호 없는 오른쪽 비트 시프트
cajava.tistory.com
비트 시프트 연산자를 통해 Discord API에서 Gateway Intent는 비트 플래그로 관리가 이뤄지고 있다는 것이다.
주요 Intent와 설명
Intent는 비트 플래그로 관리된다. 각 Intent는 2의 제곱수로 정의되며, 필요한 것들을 OR 연산(|)으로 결합해 사용한다.
※ 일반 Intent (기본 제공)
Intent | 비트 값 | 설명 |
GUILDS | 1 << 0 (1) | 서버 생성/삭제, 역할 및 채널 업데이트 등 |
GUILD_MESSAGES | 1 << 9 (512) | 메시지 생성, 수정, 삭제 관련 이벤트 |
DIRECT_MESSAGES | 1 << 12 (4096) | DM(개인 메시지) 이벤트 |
※ Privileged Intent (특권 필요)
일부 민감한 데이터에 접근하려면 Privileged Intent를 활성화해야 하며, Discord의 승인이 필요할 수 있다.
Intent | 비트 값 | 설명 |
GUILD_MEMBERS | 1 << 1 (2) | 서버 멤버 관련 이벤트(입장, 퇴장, 업데이트 등) |
GUILD_PRESENCES | 1 << 8 (256) | 멤버의 상태(온라인/오프라인 등) 업데이트 |
MESSAGE_CONTENT | 1 << 15 (32768) | 메시지 내용 접근 |
※ Intent 계산 예시
예시: GUILDS + GUILD_MESSAGES
const INTENTS = (1 << 0) | (1 << 9); // GUILDS + GUILD_MESSAGES
console.log(INTENTS); // 513
예시: MESSAGE_CONTENT 추가
const INTENTS = (1 << 0) | (1 << 9) | (1 << 15); // GUILDS + GUILD_MESSAGES + MESSAGE_CONTENT
console.log(INTENTS); // 33281
※ Privileged Intent 사용 시 주의사항
특권 Intent(GUILD_MEMBERS, MESSAGE_CONTENT 등)를 사용하려면:
- Discord 개발자 포털에서 해당 옵션을 활성화해야 한다.
- 특정 조건에서는 Discord의 승인을 받아야 한다.
Discord.js로 Privileged Intent를 활성화하려면 다음처럼 설정한다.
const client = new Client({
intents: [
GatewayIntentBits.GuildMembers, // Privileged Intent
GatewayIntentBits.MessageContent
]
});
Intent 사용 시 권장사항
- 필요한 Intent만 활성화
필요하지 않은 Intent를 활성화하면 리소스 낭비가 심하다. 필요한 기능만 선택해서 설정하는 것이 좋다. - Privileged Intent 최소화
민감한 정보(예: GUILD_MEMBERS, MESSAGE_CONTENT)는 승인 절차가 필요할 수 있다. 기본적으로 가능한 Intent만 사용하고, 필요할 때 추가로 요청한다. - Discord 개발자 문서 참고
최신 Intent 값이나 정책은 Discord의 공식 문서를 참조한다.
'⚙️ Node.js' 카테고리의 다른 글
[Javascript] 비트 시프트 연산자 <<, >> (BitWise Shift <<, >>) (0) | 2024.12.04 |
---|---|
[NodeJS] 엑셀의 차트, 함수, 그래프 유지하며 저장하기 with xlsx-populate (0) | 2024.10.04 |
[NodeJS] 아주 쉽게 타입스크립트 적용하기 (1) | 2024.09.05 |
[DiscordJS] 10분만에 디스코드 봇 제작하기 (14) | 2024.09.05 |
[NestJS] Async, 비동기로 인한 프로세스 중단 방지 (0) | 2024.08.21 |