Discord는 IP 주소 분석, 행동 패턴 및 비율 제한을 사용하는 고급 탐지 시스템을 통해 자동화 및 봇에 대해 적극적으로 대응하고 있습니다. 서버에서 모더레이션, 초대 또는 작업 자동화를 위해 봇을 실행하는 경우, 제대로 설정된 프록시 없이 작업 시작 몇 시간 만에 차단될 수 있습니다. 이 가이드에서는 Discord에 적합한 프록시 유형, IP 회전 설정 방법 및 플랫폼의 보호 메커니즘을 우회하는 방법을 살펴보겠습니다.
Discord가 봇을 차단하는 이유와 보호 작동 방식
Discord는 여러 매개변수를 동시에 분석하는 다층 보호 시스템을 사용합니다. 플랫폼은 단순히 하나의 IP에서 요청 수를 확인하는 것이 아니라, 각 연결의 행동 프로필을 구축하고 이를 정상 사용자 패턴과 비교합니다.
Discord에서 봇을 탐지하는 주요 메커니즘은 다음과 같습니다:
- 비율 제한 — Discord는 시간 단위로 수행할 수 있는 작업 수에 대해 엄격한 제한을 설정합니다. 예를 들어, 하나의 계정에서 5초당 5개 메시지, 분당 50개의 API 요청을 초과할 수 없습니다. 제한을 초과하면 임시 차단이 발생합니다 (HTTP 429).
- IP 주소 분석 — 하나의 IP에서 여러 봇이 작동하거나 의심스러운 활동이 감지되면 (빠른 계정 전환, 대량 작업) Discord는 해당 IP 주소를 몇 시간 또는 며칠 동안 차단할 수 있습니다.
- 연결 지문 인식 — 플랫폼은 기술적 매개변수: User-Agent, 요청 헤더, 라이브러리 버전, 응답 시간을 분석합니다. 매개변수가 일반 Discord 클라이언트와 일치하지 않으면 계정이 의심스럽게 표시됩니다.
- 행동 분석 — Discord는 행동 패턴을 추적합니다: 너무 빠른 반응, 메시지 간의 이상적인 간격, 행동의 무작위성 부족. 엄격한 알고리즘에 따라 작동하는 봇은 더 빨리 탐지됩니다.
프록시 없이 차단되는 일반적인 시나리오는 다음과 같습니다:
- 하나의 가정용 IP에서 3-5개의 봇 실행 — 작업 시작 후 2-6시간 내에 IP 차단
- 서버에 초대 링크 대량 발송 — 10-15개의 초대 링크 전송 후 계정 및 IP 차단
- 자동 모더레이션 (메시지 삭제, 역할 부여) — 하나의 IP에서 시간당 100개 작업 초과 시 차단
- 서버 참가자 파싱 — 200-300개 프로필 스캔 후 탐지 및 차단
프록시는 다양한 IP 주소 간에 요청을 분산시키고 여러 위치의 일반 사용자처럼 보이게 하여 이러한 문제를 해결합니다. 그러나 프록시 유형을 올바르게 선택하고 회전을 설정하는 것이 중요합니다 — 잘못된 구성은 더 빠른 차단으로 이어질 수 있습니다.
Discord 봇에 적합한 프록시 유형
프록시 유형 선택은 봇 수, 요청 빈도, 예산 및 필요한 익명성 수준에 따라 다릅니다. Discord에 적합한 세 가지 주요 프록시 유형과 그 용도를 살펴보겠습니다.
| 프록시 유형 | 장점 | 단점 | 적합한 용도 |
|---|---|---|---|
| 데이터 센터 프록시 | 높은 속도 (핑 10-50ms), 저렴한 가격 ($1-3 per IP/month), 안정성 | Discord가 데이터 센터 IP를 쉽게 인식하며, 대량 작업 시 차단 위험이 높음 | 테스트, 간단한 자동화 (1-2 봇), 대량 요청이 없는 작업 |
| 주거용 프록시 | 실제 가정 사용자 IP, 최소한의 차단 위험, 대규모 주소 풀 (수백만 IP) | 중간 속도 (핑 100-300ms), 높은 가격 ($5-15 per GB traffic), 일부 IP의 불안정성 | 대량 발송, 서버 파싱, 5개 이상의 봇 작업, 장기 프로젝트 |
| 모바일 프록시 | 모바일 통신사 IP (4G/5G), Discord의 최대 신뢰, 동적 IP 변경 | 높은 가격 ($50-150 per IP/month), 작은 주소 풀, 연결 끊김 가능성 | 중요한 계정, 엄격한 차단 우회, 고가치 계정 작업 |
다양한 작업에 대한 선택 권장 사항:
모더레이션 및 서버 관리 (1-3 봇): 고정 IP를 가진 주거용 프록시. 하나의 봇 — 하나의 IP, 회전 없음. 이렇게 하면 Discord가 일반 관리자 사용자로 인식하는 안정적인 연결 프로필이 생성됩니다.
대량 발송 및 초대 (10개 이상의 봇): 5-10분마다 회전하는 주거용 프록시. 부하를 분산하세요: 하나의 IP에서 시간당 20개 작업 이하. 10개의 봇에 대해 50개 이상의 IP 주소 풀을 사용하세요.
참가자 및 서버 파싱: 빠른 회전(1-3분마다) 또는 모바일 프록시를 사용하는 주거용 프록시. 파싱은 가장 위험한 활동 중 하나로, Discord는 스캔 패턴을 쉽게 감지합니다. 요청 간에 무작위 지연(30-120초)을 사용하세요.
테스트 및 개발: 데이터 센터 프록시로 기능을 디버깅하기에 충분합니다. 그러나 프로덕션에 배포하기 전에 반드시 주거용 프록시로 전환하세요 — Discord의 행동은 프록시 유형에 따라 크게 달라질 수 있습니다.
중요한 점: Discord는 특정 국가 및 지역의 IP 주소에 대해 특히 엄격하게 대처합니다. 러시아, 중국, 베트남, 인도의 IP는 스팸 활동이 높기 때문에 더 엄격한 검사를 받습니다. 목표 청중이 미국이나 유럽에 있다면, 해당 지역의 프록시를 사용하세요 — 이는 차단 가능성을 40-60% 줄입니다.
프록시를 통한 Discord 비율 제한 우회 방법
Discord의 비율 제한은 시간 단위로 API 요청 수에 대한 제한입니다. 이들은 두 가지 유형이 있습니다: 글로벌(전체 애플리케이션에 대한) 및 per-route(특정 엔드포인트에 대한). 프록시는 다양한 IP 간에 부하를 분산시키는 데 도움이 되지만, 제한을 무시할 수 있다는 의미는 아닙니다 — Discord는 봇 토큰 수준에서 활동을 추적합니다.
Discord API의 주요 비율 제한:
- 메시지 전송: 하나의 채널에서 5초당 5개 메시지, 봇 전체에서 10초당 50개 메시지
- 채널 생성/삭제: 10분당 50개 요청
- 참가자 역할 변경: 10초당 10개 요청
- 참가자 목록 가져오기: 초당 1개 요청 (가장 엄격한 제한)
- DM(개인 메시지) 전송: 5초당 5개 DM, 낯선 사용자에게 대량 발송 시 차단
제한을 초과하면 Discord는 HTTP 429 (Too Many Requests)와 함께 Retry-After 헤더를 반환하며, 대기 시간을 초 단위로 지정합니다. 이 응답을 올바르게 처리하는 것이 매우 중요합니다.
프록시를 통한 비율 제한 우회 전략:
# 비율 제한 시 프록시 회전 예제 (Python, discord.py)
import discord
from discord.ext import commands
import aiohttp
import asyncio
import random
class ProxyRotator:
def __init__(self, proxy_list):
self.proxies = proxy_list # ['http://user:pass@ip:port', ...]
self.current_index = 0
self.failed_proxies = set()
def get_next_proxy(self):
# 작동하지 않는 프록시 건너뛰기
available = [p for p in self.proxies if p not in self.failed_proxies]
if not available:
self.failed_proxies.clear() # 전체 주기가 끝난 후 초기화
available = self.proxies
proxy = available[self.current_index % len(available)]
self.current_index += 1
return proxy
def mark_failed(self, proxy):
self.failed_proxies.add(proxy)
# 초기화
proxy_rotator = ProxyRotator([
'http://user1:pass1@192.168.1.1:8080',
'http://user2:pass2@192.168.1.2:8080',
# ... 안정적인 작업을 위해 10-20개의 프록시 추가
])
intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents)
async def send_with_retry(channel, message, max_retries=3):
"""비율 제한 자동 처리와 함께 메시지 전송"""
for attempt in range(max_retries):
try:
# 각 시도마다 새로운 프록시를 가져옵니다
proxy = proxy_rotator.get_next_proxy()
# Discord.py는 내부적으로 aiohttp를 사용하므로 프록시를 설정합니다
connector = aiohttp.TCPConnector()
async with aiohttp.ClientSession(connector=connector) as session:
bot.http.connector = connector
bot.http.proxy = proxy
await channel.send(message)
return True
except discord.HTTPException as e:
if e.status == 429: # 비율 제한
retry_after = e.retry_after if hasattr(e, 'retry_after') else 5
print(f"비율 제한! {retry_after}초 대기, 프록시 변경 중...")
# 프록시를 일시적으로 사용 불가능으로 표시
proxy_rotator.mark_failed(proxy)
# 지연에 무작위 추가
await asyncio.sleep(retry_after + random.uniform(1, 3))
else:
print(f"전송 오류: {e}")
await asyncio.sleep(2)
return False
@bot.event
async def on_ready():
print(f'봇이 실행되었습니다: {bot.user}')
# 사용 예
@bot.command()
async def mass_send(ctx):
channels = ctx.guild.text_channels[:5] # 첫 5개 채널
for channel in channels:
success = await send_with_retry(channel, "테스트 메시지")
if success:
print(f"{channel.name}에 전송됨")
# 채널 간 무작위 지연
await asyncio.sleep(random.uniform(3, 7))
비율 제한 우회를 위한 주요 원칙:
- 항상 HTTP 429을 처리하세요: Retry-After 헤더를 무시하지 마세요. Discord는 반복적인 위반 시 차단 시간을 늘립니다 (5초에서 60초 이상).
- 무작위 추가: 요청 간 지연은 무작위여야 합니다 (예: 고정된 3초 대신 2-5초). 이는 사람의 행동을 모방합니다.
- 부하 분산: 10개의 봇과 20개의 프록시가 있다면 각 봇에 대해 2개의 프록시를 할당하세요. 모든 봇에 대해 하나의 프록시를 사용하지 마세요.
- 프록시 품질 모니터링: 일부 IP는 이미 Discord에 의해 차단될 수 있습니다. 403 또는 429를 지속적으로 받는 프록시는 자동으로 제외하세요.
다양한 작업을 위한 IP 회전 전략
프록시 회전은 단순히 N분마다 IP를 무작위로 변경하는 것이 아닙니다. 올바른 전략은 봇의 활동 유형과 Discord의 연결 안정성 요구 사항에 따라 다릅니다. 네 가지 주요 접근 방식을 살펴보겠습니다.
1. 고정 IP (회전 없음)
사용 시기: 모더레이션 봇, 서버 관리 봇, 음악 봇, 서버에 지속적으로 존재하는 봇.
논리: 하나의 봇 = 전체 작업 기간 동안 하나의 IP 주소 (주, 월). Discord는 이러한 연결을 항상 한 장소에서 접속하는 일반 관리자 사용자로 인식합니다.
설정:
# Python (discord.py) - 고정 프록시
import discord
from discord.ext import commands
PROXY = 'http://username:password@192.168.1.100:8080'
intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents, proxy=PROXY)
# 이 봇의 모든 요청에 대해 프록시가 사용됩니다
bot.run('YOUR_BOT_TOKEN')
장점: 최대 안정성, IP 차단 위험 최소화, 간단한 설정.
단점: IP가 차단되면 프록시를 수동으로 변경하고 봇 세션을 재생성해야 합니다.
2. 시간에 따른 회전
사용 시기: 발송 봇, 중간 활동을 가진 봇 (시간당 10-50 작업), 낮은 빈도의 데이터 파싱.
논리: IP는 요청 수와 관계없이 5-15분마다 타이머에 따라 변경됩니다. 이는 인터넷에 재연결하는 사용자(예: 동적 IP를 가진 모바일 인터넷)를 모방합니다.
추천 간격:
- 낮은 활동 (시간당 5-10 작업): 10-15분마다 회전
- 중간 활동 (시간당 20-40 작업): 5-7분마다 회전
- 높은 활동 (시간당 50개 이상의 작업): 2-3분마다 회전 + 비율 제한 시 추가 회전
# JavaScript (discord.js) - 시간에 따른 회전
const { Client, GatewayIntentBits } = require('discord.js');
const HttpsProxyAgent = require('https-proxy-agent');
const proxies = [
'http://user1:pass1@ip1:port',
'http://user2:pass2@ip2:port',
'http://user3:pass3@ip3:port',
];
let currentProxyIndex = 0;
function getProxyAgent() {
const proxy = proxies[currentProxyIndex];
currentProxyIndex = (currentProxyIndex + 1) % proxies.length;
return new HttpsProxyAgent(proxy);
}
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
rest: { agent: getProxyAgent() }
});
// 5분마다 회전
setInterval(() => {
console.log('프록시 변경 중...');
client.rest.setAgent(getProxyAgent());
}, 5 * 60 * 1000);
client.login('YOUR_BOT_TOKEN');
3. 요청 수에 따른 회전
사용 시기: 대량 파싱, 서버 참가자 스크래핑, 자동 초대.
논리: N개의 요청이 완료된 후 IP가 변경됩니다 (예: 20-50 요청마다). 이를 통해 부하를 고르게 분산하고 하나의 IP에서 Discord의 보이지 않는 작업 수 제한을 초과하지 않도록 합니다.
추천 N 값:
- 참가자 파싱: IP당 30-50 요청 (스캔 패턴 탐지를 피하기 위해)
- DM 전송: IP당 10-15 메시지 (Discord는 대량 DM에 대해 특히 엄격합니다)
- 초대 생성: IP당 20-30개의 초대
4. 오류 발생 시 적응형 회전
사용 시기: 중요한 봇, 고가치 계정 작업, 엄격한 차단 우회.
논리: 오류 429 (비율 제한), 403 (금지) 또는 타임아웃 발생 시 IP가 자동으로 변경됩니다. 시스템은 "나쁜" IP를 기억하고 이를 회전에서 일시적으로 제외합니다.
# Python - 블랙리스트와 함께 적응형 회전
import time
from collections import defaultdict
class AdaptiveProxyRotator:
def __init__(self, proxies):
self.proxies = proxies
self.current = 0
self.error_count = defaultdict(int)
self.blacklist_until = {} # {proxy: timestamp}
def get_proxy(self):
now = time.time()
# 블랙리스트에 있는 프록시 필터링
available = [
p for p in self.proxies
if p not in self.blacklist_until or self.blacklist_until[p] < now
]
if not available:
# 모든 프록시가 블랙리스트에 있을 경우 초기화하고 대기
print("모든 프록시가 블랙리스트에 있습니다. 60초 대기 중...")
time.sleep(60)
self.blacklist_until.clear()
available = self.proxies
proxy = available[self.current % len(available)]
self.current += 1
return proxy
def report_error(self, proxy, error_type):
self.error_count[proxy] += 1
# 반복적인 오류 발생 시 임시 차단
if self.error_count[proxy] >= 3:
blacklist_duration = 300 # 5분
self.blacklist_until[proxy] = time.time() + blacklist_duration
print(f"프록시 {proxy}가 {blacklist_duration}초 동안 블랙리스트에 추가되었습니다.")
self.error_count[proxy] = 0 # 카운터 초기화
def report_success(self, proxy):
# 성공적인 요청 - 오류 카운터 초기화
if proxy in self.error_count:
self.error_count[proxy] = max(0, self.error_count[proxy] - 1)
추천 조합 접근법: 기본 시간 회전(5-10분마다) + 오류 발생 시 적응형 회전 사용. 이는 안정성과 문제에 대한 빠른 반응을 보장합니다.
인기 라이브러리에서 프록시 설정: discord.py 및 discord.js
Discord 봇을 생성하기 위한 두 가지 가장 인기 있는 라이브러리에서 프록시를 단계별로 설정하는 방법을 살펴보겠습니다. 이 예시는 대부분의 작업에 적합하며 귀하의 필요에 맞게 쉽게 조정할 수 있습니다.
Discord.py (Python)
Discord.py는 HTTP 요청을 위해 aiohttp를 사용합니다. 프록시는 클라이언트를 생성할 때 proxy 매개변수를 통해 설정하거나 HTTP 세션을 직접 설정하여 구성할 수 있습니다.
1단계: 종속성 설치
pip install discord.py aiohttp aiohttp-socks
# aiohttp-socks는 SOCKS5 프록시에 필요하며, HTTP/HTTPS에는 필수적이지 않습니다.
2단계: 단일 프록시로 기본 설정
import discord
from discord.ext import commands
# 프록시 형식: protocol://username:password@ip:port
PROXY = 'http://user:pass@192.168.1.100:8080'
intents = discord.Intents.default()
intents.message_content = True # 메시지 읽기를 위해
bot = commands.Bot(
command_prefix='!',
intents=intents,
proxy=PROXY # 모든 HTTP 요청에 대한 프록시
)
@bot.event
async def on_ready():
print(f'봇 {bot.user}가 프록시를 통해 연결되었습니다!')
@bot.command()
async def ping(ctx):
await ctx.send(f'핑! 지연: {round(bot.latency * 1000)}ms')
bot.run('YOUR_BOT_TOKEN')
3단계: 프록시 회전 설정
import discord
from discord.ext import commands, tasks
import aiohttp
import random
PROXIES = [
'http://user1:pass1@ip1:port',
'http://user2:pass2@ip2:port',
'http://user3:pass3@ip3:port',
]
class ProxyBot(commands.Bot):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.current_proxy = random.choice(PROXIES)
self.proxy_rotation.start()
@tasks.loop(minutes=5) # 5분마다 회전
async def proxy_rotation(self):
old_proxy = self.current_proxy
self.current_proxy = random.choice([p for p in PROXIES if p != old_proxy])
# 새로운 프록시로 HTTP 세션 재생성
await self.http.close()
connector = aiohttp.TCPConnector(limit=0)
self.http.connector = connector
self.http.__session = aiohttp.ClientSession(connector=connector)
print(f'프록시 변경: {old_proxy} -> {self.current_proxy}')
async def close(self):
self.proxy_rotation.cancel()
await super().close()
intents = discord.Intents.default()
bot = ProxyBot(command_prefix='!', intents=intents)
bot.run('YOUR_BOT_TOKEN')
Discord.js (Node.js)
Discord.js는 프록시를 기본적으로 지원하지 않으므로 https-proxy-agent 또는 socks-proxy-agent 라이브러리를 사용합니다.
1단계: 종속성 설치
npm install discord.js https-proxy-agent
# SOCKS5의 경우: npm install socks-proxy-agent
2단계: 기본 설정
const { Client, GatewayIntentBits } = require('discord.js');
const { HttpsProxyAgent } = require('https-proxy-agent');
const PROXY = 'http://user:pass@192.168.1.100:8080';
const agent = new HttpsProxyAgent(PROXY);
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
],
rest: { agent: agent } // REST API 요청에 대한 프록시
});
client.on('ready', () => {
console.log(`봇 ${client.user.tag}가 프록시를 통해 연결되었습니다!`);
});
client.on('messageCreate', async (message) => {
if (message.content === '!ping') {
await message.reply(`핑! WebSocket 지연: ${client.ws.ping}ms`);
}
});
client.login('YOUR_BOT_TOKEN');
3단계: 프록시 회전 설정
const { Client, GatewayIntentBits } = require('discord.js');
const { HttpsProxyAgent } = require('https-proxy-agent');
const PROXIES = [
'http://user1:pass1@ip1:port',
'http://user2:pass2@ip2:port',
'http://user3:pass3@ip3:port',
];
let currentProxyIndex = 0;
function getNextProxy() {
const proxy = PROXIES[currentProxyIndex];
currentProxyIndex = (currentProxyIndex + 1) % PROXIES.length;
return new HttpsProxyAgent(proxy);
}
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
rest: { agent: getNextProxy() }
});
// 10분마다 회전
setInterval(() => {
const newAgent = getNextProxy();
client.rest.setAgent(newAgent);
console.log('프록시 변경');
}, 10 * 60 * 1000);
client.on('ready', () => {
console.log(`봇 ${client.user.tag}가 실행되었습니다.`);
});
client.login('YOUR_BOT_TOKEN');
중요: WebSocket 연결(실시간 이벤트 수신)은 항상 프록시를 지원하지 않습니다. WebSocket 연결에 문제가 있는 경우, REST API 요청에 대해서만 HTTP 프록시를 사용하고 WebSocket은 프록시 없이 사용하세요. 중요한 경우, WebSocket 연결을 위해 VPN 사용을 고려하세요.
일반적인 실수 및 피하는 방법
올바르게 설정된 프록시를 사용하더라도 일반적인 실수를 범하면 차단될 수 있습니다. 가장 치명적인 실수와 해결 방법을 살펴보겠습니다.
오류 1: 모든 봇에 대해 하나의 프록시 사용
문제: 5-10개의 봇을 하나의 IP 주소를 통해 실행합니다. Discord는 하나의 IP에서 여러 계정의 동시 활동을 감지하고 모든 계정과 IP를 차단합니다.
해결 방법: 안정적인 작업을 위해 "하나의 봇 — 하나의 고유한 IP" 규칙을 따르세요. 10개의 봇이 있다면 최소 10개의 서로 다른 프록시를 사용하세요. 중요한 프로젝트의 경우 50-100% 여유를 두어 (10개의 봇에 대해 15-20개의 프록시) 회전하세요.
오류 2: 너무 빠른 IP 회전
문제: IP를 30-60초마다 변경하여 차단을 방지하려고 합니다. 사실 Discord는 잦은 IP 변경을 의심스러운 활동으로 인식합니다 — 일반 사용자는 매분마다 인터넷에 재연결하지 않습니다.
해결 방법: 최소 회전 간격은 3-5분입니다. 요청의 강도에 따라 5-15분이 최적입니다. 예외는 비율 제한(429) 발생 시 적응형 회전입니다.
오류 3: 프록시의 지리적 위치 무시
문제: 봇이 미국 서버에 있지만 러시아, 중국 또는 인도의 프록시를 사용합니다. Discord는 서버의 위치와 IP 주소 간의 불일치를 감지하여 의심을 높입니다.
해결 방법: Discord 서버나 목표 청중이 있는 국가/지역의 프록시를 사용하세요. 국제 프로젝트의 경우 미국이나 유럽의 프록시를 선택하세요 — 이들은 Discord에서 더 나은 평판을 가지고 있습니다.
오류 4: 오류 처리 부족
문제: 봇이 HTTP 429 (비율 제한)를 받고 요청을 계속 보내어 상황을 악화시킵니다. Discord는 시도할 때마다 차단 시간을 늘립니다.
해결 방법: 항상 오류 코드를 처리하세요:
- 429 (Too Many Requests): Retry-After 헤더를 읽고 지정된 시간 + 1-3초 대기하세요. 프록시를 변경하세요.
- 403 (Forbidden): IP 또는 토큰이 차단되었습니다. 프록시를 변경하고 토큰의 유효성을 확인하세요.
- 401 (Unauthorized): 유효하지 않은 봇 토큰입니다. Discord 개발자 포털에서 토큰을 확인하세요.
- 502/504 (Gateway errors): 프록시 또는 Discord API에 문제가 발생했습니다. 10-30초 대기하고 프록시를 변경하세요.
오류 5: 공개 또는 저렴한 프록시 사용
문제: 무료 또는 저렴한 프록시 ($0.5-1 per IP)는 종종 이미 Discord에 의해 차단되어 있습니다. 이는 수천 개의 다른 봇과 스팸러가 사용했기 때문입니다.
해결 방법: 신뢰할 수 있는 공급자로부터 고품질 주거용 프록시에 투자하세요. 사용하기 전에 IP의 평판을 확인하세요 (AbuseIPDB, IPQualityScore와 같은 서비스). $5-10의 고품질 프록시 하나가 $1의 차단된 프록시 10개보다 낫습니다.
오류 6: 모든 봇에 대해 동일한 User-Agent 사용
문제: 모든 봇이 라이브러리의 기본 User-Agent (예: "DiscordBot (discord.py 2.0)")를 사용합니다. Discord는 이러한 연결을 쉽게 그룹화하고 대량 자동화를 감지합니다.
해결 방법: 봇 간 User-Agent를 다양화하세요. 현실적인 값을 사용하세요:
# Python - 사용자 정의 User-Agent
import discord
class CustomBot(discord.Client):
async def request(self, *args, **kwargs):
# User-Agent 재정의
if 'headers' not in kwargs:
kwargs['headers'] = {}
kwargs['headers']['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Discord/1.0.9015'
return await super().request(*args, **kwargs)
봇 작업 모니터링 및 오류 처리
올바른 모니터링은 문제가 대량 차단으로 이어지기 전에 발견할 수 있게 해줍니다. Discord 봇의 작업을 프록시를 통해 추적하기 위한 주요 메트릭과 도구를 살펴보겠습니다.
추적할 메트릭
| 메트릭 | 추적할 내용 | 치명적인 값 |
|---|---|---|
| 429 오류 빈도 | 시간당 비율 제한 오류 수 | >10시간 — 요청 전략을 재검토하세요 |
| 403 오류 빈도 | IP 또는 토큰 차단 | >3일 — 프록시가 손상되었습니다 |
| 지연 (latency) | 프록시 + Discord API의 응답 시간 | >1000ms — 느린 프록시, 교체하세요 |
| 요청 성공률 | 성공적인 요청의 비율 (HTTP 200-299) | <85% — 프록시 또는 봇 로직에 문제가 있습니다 |
| 프록시 가동 시간 | 문제 없이 프록시가 사용된 시간 | <24시간 — IP가 차단되었을 수 있습니다 |
로그 시스템 예시
# Python - 메트릭을 포함한 고급 로깅
import logging
import time
from collections import defaultdict
import json
class BotMonitor:
def __init__(self):
self.metrics = {
'requests_total': 0,
'requests_success': 0,
'errors_429': 0,
'errors_403': 0,
'errors_other': 0,
'proxy_switches': 0,
'avg_latency': []
}
self.proxy_stats = defaultdict(lambda: {
'requests': 0,
'errors': 0,
'last_error': None
})
# 로거 설정
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('bot_monitor.log'),
logging.StreamHandler()
]
)
self.logger = logging.getLogger('BotMonitor')
def log_request(self, proxy, status_code, latency):
self.metrics['requests_total'] += 1
self.metrics['avg_latency'].append(latency)
self.proxy_stats[proxy]['requests'] += 1
if 200 <= status_code < 300:
self.metrics['requests_success'] += 1
elif status_code == 429:
self.metrics['errors_429'] += 1
self.proxy_stats[proxy]['errors'] += 1
self.logger.warning(f'프록시 {proxy}에서 비율 제한 발생')
elif status_code == 403:
self.metrics['errors_403'] += 1
self.proxy_stats[proxy]['errors'] += 1
self.proxy_stats[proxy]['last_error'] = time.time()
self.logger.error(f'프록시 {proxy}가 차단되었습니다 (403)')
else:
self.metrics['errors_other'] += 1
self.logger.error(f'프록시 {proxy}에서 오류 {status_code} 발생')
def log_proxy_switch(self, old_proxy, new_proxy):
self.metrics['proxy_switches'] += 1
self.logger.info(f'프록시 변경: {old_proxy} -> {new_proxy}')
def get_report(self):
total = self.metrics['requests_total']
if total == 0:
return "데이터 없음"
success_rate = (self.metrics['requests_success'] / total) * 100
avg_latency = sum(self.metrics['avg_latency']) / len(self.metrics['avg_latency'])
report = f"""
=== 봇 모니터링 보고서 ===
총 요청 수: {total}
성공 요청: {self.metrics['requests_success']} ({success_rate:.1f}%)
429 오류 (비율 제한): {self.metrics['errors_429']}
403 오류 (차단): {self.metrics['errors_403']}
기타 오류: {self.metrics['errors_other']}
평균 지연: {avg_latency:.0f}ms
프록시 변경 수: {self.metrics['proxy_switches']}
=== 프록시 통계 ===
"""
for proxy, stats in self.proxy_stats.items():
error_rate = (stats['errors'] / stats['requests'] * 100) if stats['requests'] > 0 else 0
report += f"{proxy}: {stats['requests']} 요청, {stats['errors']} 오류 ({error_rate:.1f}%)\n"
return report