Claude API 디스코드봇 만들기: discord.js 통합 가이드
Claude API로 디스코드봇을 만들려면 Discord Developer Portal에서 앱을 생성해 봇 토큰을 발급받고, discord.js v14와 @anthropic-ai/sdk를 설치한 뒤 두 클라이언트를 연결하면 됩니다. discord.js v14는 Discord의 공식 Node.js 라이브러리로, 슬래시 커맨드·인터랙션·이벤트 처리를 체계적으로 지원합니다. Claude API는 자연어 질문에 고품질 답변을 생성합니다. 이 가이드에서는 봇 등록부터 서버별 비용 관리, PM2/Docker 프로덕션 배포까지 실전 TypeScript 예제와 함께 단계별로 설명합니다.
봇 등록 및 토큰 발급
1. Discord Developer Portal에서 앱 생성
discord.com/developers/applications에 접속해 New Application을 클릭합니다. 앱 이름을 입력한 뒤 왼쪽 메뉴에서 Bot을 선택하고 Add Bot을 누릅니다.
봇 토큰 발급:
- Reset Token 클릭 → 토큰을 복사해 안전하게 보관
- 토큰은 한 번만 표시되므로 반드시 즉시 저장
Privileged Gateway Intents 설정 (필요한 항목만 활성화):
MESSAGE CONTENT INTENT— 메시지 내용 읽기 (슬래시 커맨드 없이 메시지 수신 시 필요)SERVER MEMBERS INTENT— 멤버 목록 접근 (필요 시만)
2. OAuth2 봇 초대 URL 생성
OAuth2 → URL Generator에서 다음을 설정합니다:
- Scopes:
bot,applications.commands - Bot Permissions:
Send Messages,Use Slash Commands,Read Message History,Embed Links
생성된 URL로 봇을 서버에 초대합니다.
3. 환경변수 설정
DISCORD_BOT_TOKEN=MTI... # Bot 페이지의 토큰
DISCORD_CLIENT_ID=123... # Application의 Application ID
ANTHROPIC_API_KEY=sk-ant-...
discord.js v14 기본 구조
npm install discord.js @anthropic-ai/sdk dotenv
npm install -D typescript @types/node ts-node
// src/index.ts
import { Client, GatewayIntentBits, Events } from 'discord.js';
import Anthropic from '@anthropic-ai/sdk';
import 'dotenv/config';
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent, // Privileged — Portal에서 활성화 필요
],
});
const claude = new Anthropic();
client.once(Events.ClientReady, (c) => {
console.log(`봇 로그인 완료: ${c.user.tag}`);
});
client.login(process.env.DISCORD_BOT_TOKEN);
Claude API 응답 통합
Discord 메시지를 수신해 Claude API를 호출하고 응답을 채널에 전송합니다:
// src/handlers/message.ts
import { Message, Events } from 'discord.js';
import Anthropic from '@anthropic-ai/sdk';
export function registerMessageHandler(client: any, claude: Anthropic) {
client.on(Events.MessageCreate, async (message: Message) => {
// 봇 메시지 무시, 봇 멘션만 응답
if (message.author.bot) return;
if (!message.mentions.has(client.user!)) return;
// 멘션 태그 제거 후 텍스트 추출
const userText = message.content
.replace(/<@!?\d+>/g, '')
.trim();
if (!userText) {
await message.reply('질문을 입력해 주세요.');
return;
}
// 입력 중 표시
await message.channel.sendTyping();
try {
const response = await claude.messages.create({
model: 'claude-haiku-4-5', // 디스코드봇은 Haiku로 비용 절감
max_tokens: 1024,
system: `당신은 디스코드 서버 어시스턴트입니다.
간결하고 명확하게 한국어로 답변하세요.
Discord 마크다운 형식을 사용해도 됩니다.`,
messages: [{ role: 'user', content: userText }],
});
const replyText = response.content[0].type === 'text'
? response.content[0].text
: '응답을 처리할 수 없습니다.';
// Discord 메시지 길이 제한(2000자) 처리
if (replyText.length > 2000) {
const chunks = replyText.match(/.{1,1990}/gs) ?? [];
for (const chunk of chunks) {
await message.reply(chunk);
}
} else {
await message.reply(replyText);
}
} catch (error) {
await message.reply('오류가 발생했습니다. 잠시 후 다시 시도해 주세요.');
}
});
}
디스코드봇 완성본 + 30개 이상의 Claude API 실전 레시피
Agent SDK Cookbook (₩64,000)은 discord.js 봇 전체 소스, 멀티서버 비용 관리, 슬래시 커맨드 패턴, 프로덕션 배포 설정을 포함합니다.
슬래시 커맨드
슬래시 커맨드(Interaction)는 discord.js v14에서 권장하는 방식입니다. 자동완성과 타입 안전성을 제공합니다.
커맨드 등록 스크립트
// src/deploy-commands.ts
import { REST, Routes, SlashCommandBuilder } from 'discord.js';
import 'dotenv/config';
const commands = [
new SlashCommandBuilder()
.setName('ask')
.setDescription('Claude에게 질문합니다')
.addStringOption((option) =>
option
.setName('question')
.setDescription('질문 내용')
.setRequired(true)
),
new SlashCommandBuilder()
.setName('summarize')
.setDescription('텍스트를 요약합니다')
.addStringOption((option) =>
option
.setName('text')
.setDescription('요약할 텍스트')
.setRequired(true)
),
].map((cmd) => cmd.toJSON());
const rest = new REST().setToken(process.env.DISCORD_BOT_TOKEN!);
(async () => {
await rest.put(
Routes.applicationCommands(process.env.DISCORD_CLIENT_ID!),
{ body: commands }
);
console.log('슬래시 커맨드 등록 완료');
})();
커맨드 핸들러
// src/handlers/interaction.ts
import { Interaction, Events } from 'discord.js';
import Anthropic from '@anthropic-ai/sdk';
export function registerInteractionHandler(client: any, claude: Anthropic) {
client.on(Events.InteractionCreate, async (interaction: Interaction) => {
if (!interaction.isChatInputCommand()) return;
const { commandName } = interaction;
if (commandName === 'ask') {
const question = interaction.options.getString('question', true);
// Discord는 3초 내 응답 필요 → 먼저 defer
await interaction.deferReply();
const response = await claude.messages.create({
model: 'claude-haiku-4-5',
max_tokens: 1024,
messages: [{ role: 'user', content: question }],
});
const answer = response.content[0].type === 'text'
? response.content[0].text
: '응답 없음';
await interaction.editReply(`**질문:** ${question}\n\n**답변:** ${answer}`);
}
if (commandName === 'summarize') {
const text = interaction.options.getString('text', true);
await interaction.deferReply();
const response = await claude.messages.create({
model: 'claude-haiku-4-5',
max_tokens: 512,
messages: [{
role: 'user',
content: `다음 텍스트를 3-5문장으로 요약해 주세요:\n\n${text}`,
}],
});
const summary = response.content[0].type === 'text'
? response.content[0].text
: '요약 불가';
await interaction.editReply(`**요약 결과:**\n${summary}`);
}
});
}
슬래시 커맨드는 반드시 3초 이내에 deferReply() 또는 reply()를 호출해야 합니다. Claude API 호출이 길어질 수 있으므로 먼저 deferReply()로 응답을 예약한 뒤 editReply()로 결과를 전송합니다.
서버별 비용 관리
디스코드봇은 여러 서버에 동시 설치될 수 있으므로 서버별 사용량 추적이 중요합니다.
서버 크기별 월 예상 비용 (Haiku 3.5 기준)
| 서버 규모 | 일 평균 호출 | 월 호출 | 입력 토큰 | 출력 토큰 | 월 비용 (USD) | 월 비용 (KRW) |
|---|---|---|---|---|---|---|
| 소형 (100명) | 50회 | 1,500회 | 300,000 | 450,000 | $0.27 | ₩360 |
| 중형 (1,000명) | 300회 | 9,000회 | 1,800,000 | 2,700,000 | $1.62 | ₩2,160 |
| 대형 (10,000명) | 2,000회 | 60,000회 | 12,000,000 | 18,000,000 | $10.80 | ₩14,400 |
| 초대형 (50,000명) | 8,000회 | 240,000회 | 48,000,000 | 72,000,000 | $43.20 | ₩57,600 |
입력 200토큰 + 출력 300토큰 가정, $1=1,340원 기준
서버별 사용량 추적 및 제한
// src/utils/cost-guard.ts
// 서버별 일일 호출 횟수 추적
const serverDailyUsage = new Map<string, number>();
const DAILY_LIMITS: Record<string, number> = {
default: 200, // 기본 서버 일일 한도
premium: 2000, // 프리미엄 서버 한도
};
export function checkServerLimit(guildId: string, tier: 'default' | 'premium' = 'default'): boolean {
const key = `${guildId}:${new Date().toDateString()}`;
const count = serverDailyUsage.get(key) ?? 0;
const limit = DAILY_LIMITS[tier];
if (count >= limit) return false;
serverDailyUsage.set(key, count + 1);
return true;
}
export function getServerUsage(guildId: string): number {
const key = `${guildId}:${new Date().toDateString()}`;
return serverDailyUsage.get(key) ?? 0;
}
비용 최적화 전략에 대한 자세한 내용은 Claude API 비용 모니터링 가이드와 Claude 모델 선택 가이드를 참고하세요. 슬랙봇 패턴과의 비교가 궁금하다면 Claude API 슬랙봇 가이드도 확인하세요.
PM2/Docker 배포
PM2로 배포 (단일 서버)
npm install -g pm2
npx tsc # TypeScript 컴파일
// ecosystem.config.js
module.exports = {
apps: [{
name: 'claude-discord-bot',
script: 'dist/index.js',
env: {
NODE_ENV: 'production',
DISCORD_BOT_TOKEN: process.env.DISCORD_BOT_TOKEN,
DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID,
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
},
restart_delay: 5000,
max_restarts: 10,
watch: false,
}],
};
pm2 start ecosystem.config.js
pm2 save # 재부팅 후 자동 시작
pm2 startup # 시스템 서비스 등록
pm2 logs claude-discord-bot # 로그 확인
Docker로 배포 (컨테이너 환경)
# Dockerfile
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY dist/ ./dist/
ENV NODE_ENV=production
CMD ["node", "dist/index.js"]
# docker-compose.yml
version: '3.8'
services:
discord-bot:
build: .
restart: always
environment:
- DISCORD_BOT_TOKEN=${DISCORD_BOT_TOKEN}
- DISCORD_CLIENT_ID=${DISCORD_CLIENT_ID}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
volumes:
- ./logs:/app/logs
docker-compose up -d # 백그라운드 시작
docker-compose logs -f # 로그 스트리밍
docker-compose restart # 재시작
디스코드봇 전체 소스 + PM2/Docker 설정 + 30개 Claude API 실전 레시피
Agent SDK Cookbook (₩64,000)은 서버별 비용 대시보드, 멀티서버 관리 패턴, 에러 핸들링 전략, 슬래시 커맨드 고급 패턴을 포함합니다.
Frequently Asked Questions
discord.js v14에서 Claude API를 어떻게 연결하나요?
discord.js와 @anthropic-ai/sdk를 모두 설치한 뒤 각각 Client와 Anthropic 인스턴스를 생성합니다. Discord 이벤트 핸들러(Events.MessageCreate, Events.InteractionCreate) 안에서 claude.messages.create()를 호출하면 됩니다. 사용자 메시지 텍스트를 추출해 Claude에 전달하고, 응답을 message.reply() 또는 interaction.editReply()로 Discord에 전송합니다.
슬래시 커맨드가 "This interaction failed" 오류를 반환하는 이유는 무엇인가요?
Discord는 인터랙션 수신 후 3초 이내에 응답을 요구합니다. Claude API 호출 시간이 길어지면 타임아웃이 발생합니다. 해결책은 즉시 interaction.deferReply()로 응답을 예약한 뒤 처리가 완료되면 interaction.editReply()로 결과를 전송하는 것입니다. deferReply()는 Discord에 "처리 중" 상태를 알려 최대 15분까지 시간을 확보합니다.
여러 Discord 서버에서 각각 독립적인 대화 맥락을 유지하려면 어떻게 해야 하나요?
guildId + channelId 또는 guildId + userId 조합을 키로 사용해 Map에 대화 히스토리를 저장합니다. 각 키별로 독립적인 MessageParam[] 배열을 유지하면 서버 간, 채널 간 맥락이 섞이지 않습니다. 서버 재시작 후 히스토리를 유지하려면 Redis나 SQLite에 영구 저장하는 방식을 권장합니다.
디스코드봇에 어떤 Claude 모델이 적합한가요?
일상적인 Q&A와 간단한 요약에는 claude-haiku-4-5가 최적입니다. 응답 속도가 빠르고 비용이 Sonnet의 약 1/50 수준입니다. 코드 분석, 긴 문서 처리, 복잡한 추론이 필요한 커맨드에는 claude-sonnet-4-5로 전환하세요. 모델별 성능과 비용 비교는 Claude 모델 선택 가이드를 참고하세요.
discord.js 봇을 PM2와 Docker 중 어떤 방식으로 배포해야 하나요?
단일 VPS/서버 환경에서는 PM2가 간편합니다. 프로세스 자동 재시작, 로그 관리, 시스템 서비스 등록을 쉽게 설정할 수 있습니다. 컨테이너 환경(AWS ECS, Kubernetes) 이나 여러 봇을 동시에 관리할 때는 Docker가 적합합니다. 환경 격리와 일관된 배포를 보장합니다. 두 방식 모두 .env 파일로 환경변수를 안전하게 관리하세요.