
왜 굳이 '봇(Bot)'을 만들었나?
안녕하세요. MT-LAB(먹튀랩)의 백엔드 리드 개발자입니다. 우리 팀은 매일 수십 개의 신규 사이트가 생기고 사라지는 이 시장에서, "어떻게 하면 인간의 주관을 배제하고 오직 데이터로만 안전성을 검증할 수 있을까?"를 고민했습니다.
사람은 잠을 자고, 실수를 합니다. 하지만 서버는 24시간 깨어 있습니다. 그래서 우리는 전 세계 3,000개 이상의 사설 서버를 실시간으로 핑(Ping) 체크하고, HTML 구조 변경을 감지하는 자동화 봇 'Watchdog'을 개발했습니다.
오늘은 그 개발 과정에서 겪은 동시성(Concurrency) 문제 해결과 안티 크롤링 우회 기법에 대해 기술적으로 공유하려 합니다.
Language: Python 3.11 (Type Hinting 적극 활용)
Crawling: aiohttp (비동기 요청), Selenium (동적 페이지 렌더링)
Queue: Redis (URL 스케줄링 및 중복 제거)
Database: PostgreSQL (메타 데이터), InfluxDB (시계열 로그 데이터)
Deploy: AWS Lambda + CloudWatch (Serverless 아키텍처)
우리는 이를 asyncio와 aiohttp를 이용한 완전 비동기(Fully Asynchronous) 구조로 리팩토링했습니다.
Python
import asyncio
import aiohttp
import time
from typing import List
async def fetch_status(session: aiohttp.ClientSession, url: str):
try:
async with session.get(url, timeout=10) as response:
# 200 OK가 아니면 서버 이상 징후로 판단
return url, response.status
except Exception as e:
return url, 500 # 서버 다운으로 간주
async def main(urls: List[str]):
async with aiohttp.ClientSession() as session:
tasks = [fetch_status(session, url) for url in urls]
# 3000개 요청을 동시에 병렬 처리 (Concurrent)
results = await asyncio.gather(*tasks)
return results
if name == "main":
start = time.time()
asyncio.run(main(target_site_list))
print(f"Completed in {time.time() - start} seconds")
이 코드를 통해 우리는 3분 간격으로 전 세계 모든 타겟 사이트의 생존 여부(Heartbeat)를 체크할 수 있게 되었습니다.
우리는 이를 우회하기 위해 Undetected-Chromedriver와 User-Agent 로테이션 기술을 적용했습니다.
[핵심 로직]
헤더 위장: 매 요청마다 User-Agent를 최신 버전의 Chrome, Firefox, Edge 등으로 랜덤 교체합니다.
헤드리스 탐지 우회: navigator.webdriver 플래그를 false로 조작하여 브라우저인 척 연기합니다.
Python
from selenium import webdriver
from selenium_stealth import stealth
def create_stealth_driver():
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_argument("--headless")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options)
# 셀레니움 스텔스 적용 (봇 탐지 스크립트 무력화)
stealth(driver,
languages=["en-US", "en"],
vendor="Google Inc.",
platform="Win32",
webgl_vendor="Intel Inc.",
renderer="Intel Iris OpenGL Engine",
fix_hairline=True,
)
return driver
이 기술 덕분에 MT-LAB의 봇은 일반 유저와 100% 동일한 환경으로 인식되어, 관리자 페이지나 숨겨진 로그인 페이지까지 접근하여 데이터를 수집할 수 있습니다.
Case A. 팝업창 키워드 분석
BeautifulSoup으로 사이트의 모든 텍스트를 긁어온 뒤, NLP(자연어 처리) 모듈을 돌립니다.
"긴급 점검", "계좌 변경", "디도스 공격" 같은 단어의 빈도수가 평소보다 급증하면 위험 등급을 [Warning]으로 격상합니다.
Case B. 도메인 리다이렉트 (Domain Redirect)
response.history를 추적합니다.
어제까지 site-a.com이었던 곳이 오늘 갑자기 site-b.com으로 리다이렉트 된다면? 이는 도메인 세탁(Domain Washing)의 전형적인 수법입니다. 봇은 이를 놓치지 않고 DB에 '이력'으로 남깁니다.
Python
if response.history:
original_url = response.history[0].url
final_url = response.url
if original_url != final_url:
print(f"[ALERT] 도메인 변경 감지: {original_url} -> {final_url}")
# DB에 '먹튀 의심' 태그 추가 및 슬랙 전송
send_slack_alert(channel="#security-log", msg=f"도메인 세탁 의심: {final_url}")
서버 응답 속도가 느려지기 시작하는 시점
고객센터 게시판 글 리젠 속도가 줄어드는 시점
입금 보너스 배너가 3개 이상 늘어나는 시점
이 모든 데이터가 교차하는 순간, 우리 시스템은 해당 사이트를 [SCAM CONFIRMED] 상태로 변경하고 블랙리스트에 등재합니다.
"친절하다", "빠르다"는 주관적인 평가는 믿을 수 없습니다. 오직 서버가 뱉어내는 HTTP Status Code 200과 Latency(지연 시간), 그리고 블록체인 트랜잭션만이 진실을 말해줍니다.
우리가 만든 이 봇은 지금 이 순간에도 전 세계의 사설 서버를 24시간 감시하고 있습니다. MT-LAB이 제공하는 정보는 누군가의 '카더라'가 아닌, 수백만 줄의 로그 데이터에서 정제된 기술적 팩트입니다.
혹시 자동화된 검증 시스템의 전체 데이터가 궁금하신가요? 저희 기술 블로그가 아닌, 실제 서비스 페이지에서 그 결과를 확인하실 수 있습니다.