온라인 베팅, 재판매 예치금, 리워드 앱 등 돈이 오가는 서비스엔 예외 없이 허위 운영과 먹튀 시도가 붙는다. 커뮤니티에선 제보가 쏟아지고, 피해 사례는 유사한 패턴으로 반복된다. 수작업으로 링크를 열어보는 방식으로는 규모와 속도를 따라잡기 어렵다. 자동화는 이 틈을 메운다. 크롤링과 정적 분석, 결제 경로 추적, 정책 문구 파싱, 평판 데이터 결합을 통합하면 의심 사이트를 초기 단계에서 걸러낼 확률을 높일 수 있다. 몇 달 간 600개 도메인을 감시하도록 구성한 작은 파이프라인만으로도, 신규 등록 도메인 중 20% 가까이가 일주일 내 폐기 또는 리디렉션된 사실을 확인했다. 신속한 경보와 증적 보존이 피해를 줄였다.
이 글은 먹튀검증 자동화의 뼈대와 실무 도구, 스크립트 예시, 운영 중 맞닥뜨리는 애매한 지점을 다룬다. 자동화는 과대평가도, 과소평가도 금물이다. 반복 가능한 관찰을 기계에 맡기고, 모순과 애매함, 법적 책임이 얽힌 판단은 사람이 책임지는 구도를 설계하는 것이 핵심이다.
자동화가 유효한 범위, 그리고 인간의 몫
자동화로 잘 풀리는 작업은 반복과 수량에서 가치가 난다. 도메인 등록 정보 조회, 네임서버와 SSL 체인 확인, 페이지 로드와 스크린샷, 정적 텍스트에서 의심 키워드 탐지, 결제 주소와 머천트 아이디의 교차 검증 같은 절차가 여기에 속한다. 수천 건을 동일 기준으로 훑고 변화 추세를 기록하는 데 적합하다.
반대로, 면책 조항의 문맥 판별, 커뮤니티 글의 신뢰도 평가, 오퍼 구조의 기만성 판단은 여전히 인간의 영역에 가깝다. 예를 들어 환전 수수료를 숨기는 표현을 우회적으로 섞는다든지, 규제 회피를 암시하는 문구를 교묘히 쓰는 경우가 그렇다. 자동화는 이런 지점을 후보로 떠올려 주는 역할을 한다. 스코어가 높다고 해서 바로 단정하지 않는 절제도 필요하다.
툴 스택, 최소 구성과 확장 포인트
아래는 필드에서 안정적으로 굴러간 구성을 기준으로, 처음부터 과하지 않게 시작하는 데 도움이 되는 스택이다.
- 수집: Python, aiohttp 또는 httpx, Playwright 혹은 Selenium, dnspython, python-whois 분석: pandas, DuckDB 또는 SQLite, 정규식, python-levenshtein, tldextract 보안/네트워크: OpenSSL CLI, sslyze, curl, torify(합법적 범위 내), rate limit 프록시 오케스트레이션: Prefect 또는 Apache Airflow, Docker, GitHub Actions 저장/리포팅: S3 호환 스토리지, Parquet, Grafana 또는 Metabase, WeasyPrint로 PDF 생성
절대 필수는 아니다. 환경과 예산, 팀 역량에 따라 바꾸면 된다. 다만 수집과 분석, 오케스트레이션, 증적 보존의 네 레이어를 분리해두면 나중에 확장과 유지보수가 수월해진다.
도메인, DNS, SSL 체인으로 시작하는 1차 스크리닝
먹튀 사이트 상당수는 짧은 수명과 잦은 리브랜딩을 보인다. 그래서 기본기는 의외로 강력하다. WHOIS 데이터에서 등록 시점과 만료일, 프라이버시 보호 여부, 레지스트라 패턴을 잡는다. 네임서버가 특정 값대에 쏠리거나, CDN을 통해 원 IP를 철저히 가리는지, SSL 인증서가 무료 발급이라도 빈번히 교체되는지 확인한다. 이런 신호를 단독으로 단정하지는 않지만, 여러 개가 겹치면 가중치를 부여한다.
파이썬으로 WHOIS, DNS, SSL을 묶는 최소 예시는 다음과 같다.
import asyncio, ssl, socket, json import whois import dns.resolver from datetime import datetime from OpenSSL import crypto def fetch_whois(domain: str): try: w = whois.whois(domain) return "created": str(w.creation_date[0] if isinstance(w.creation_date, list) else w.creation_date), "expires": str(w.expiration_date[0] if isinstance(w.expiration_date, list) else w.expiration_date), "registrar": w.registrar, "privacy_protected": any("privacy" in str(x).lower() for x in [w.org, w.emails, w.name]), except Exception as e: return "whois_error": str(e) def fetch_dns(domain: str): out = for rtype in ["A", "AAAA", "NS", "MX", "TXT"]: try: answers = dns.resolver.resolve(domain, rtype) out[rtype] = [a.to_text() for a in answers] except Exception: out[rtype] = [] return out def fetch_cert(domain: str, port=443): try: ctx = ssl.create_default_context() with socket.create_connection((domain, port), timeout=8) as sock: with ctx.wrap_socket(sock, server_hostname=domain) as ssock: der = ssock.getpeercert(True) x509 = crypto.load_certificate(crypto.FILETYPE_ASN1, der) return "issuer": dict(x509.get_issuer().get_components()).get(b'O', b'').decode(), "subject_cn": dict(x509.get_subject().get_components()).get(b'CN', b'').decode(), "not_before": x509.get_notBefore().decode(), "not_after": x509.get_notAfter().decode(), "serial": format(x509.get_serial_number(), 'x') except Exception as e: return "cert_error": str(e) def baseline(domain: str): return "domain": domain, "ts": datetime.utcnow().isoformat(), "whois": fetch_whois(domain), "dns": fetch_dns(domain), "cert": fetch_cert(domain), if __name__ == "__main__": print(json.dumps(baseline("example.com"), ensure_ascii=False, indent=2))이 스니펫은 프로덕션 품질은 아니지만 변수를 어떻게 묶을지 감을 준다. 운영에선 타임아웃과 재시도, 캐시, 레이트 리미트, 예외 유형별 핸들링을 더해야 한다. 또, 인증서 체인을 sslyze로 점검해 취약한 스위트나 만료 근접을 잡아내면 추가 신호가 된다.
HTTP 레이어, 헤더와 리디렉션의 디테일
응답 헤더는 운영 성숙도를 드러낸다. HSTS 설정, 보안 관련 헤더의 유무, CDN 캐시 키 구성, 서버 지문이 노출되는지 등을 본다. 302 리디렉션이 다단으로 이어지거나, 국가 별 IP 범위에 따라 전혀 다른 랜딩으로 보내는지, User-Agent 별로 UI가 갈리는지 확인한다. 간단한 방법은 다양한 에이전트를 흉내 내며 GET을 반복하고, 차이를 해시로 비교하는 것이다.
import httpx, hashlib UAS = [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X)", "curl/7.88.1" ] def fetch_variant(url: str): out = [] for ua in UAS: r = httpx.get(url, headers="User-Agent": ua, follow_redirects=True, timeout=10) body_hash = hashlib.sha256(r.text.encode('utf-8', errors='ignore')).hexdigest() out.append( "ua": ua, "status": r.status_code, "final_url": str(r.url), "hsts": "strict-transport-security" in r.headers, "body_hash": body_hash, "len": len(r.text), ) return out
먹튀 사이트는 봇을 따돌리기 위해 빈 페이지, 혹은 의도적으로 오류를 던지는 경우가 있다. 그래서 헤드리스 브라우저가 필요하다. Playwright로 렌더링 후 스크린샷과 DOM 스냅샷을 저장하면, 정적 요청만으로 놓치는 동적 로딩과 차단 메커니즘을 관찰할 수 있다.
import asyncio, json, hashlib from playwright.async_api import async_playwright async def render_and_capture(url: str): async with async_playwright() as p: browser = await p.chromium.launch(headless=True, args=["--no-sandbox"]) page = await browser.new_page() await page.route("**/*", lambda route: route.continue_()) await page.goto(url, wait_until="networkidle", timeout=30000) html = await page.content() shash = hashlib.sha256(html.encode('utf-8')).hexdigest() await page.screenshot(path="shot.png", full_page=True) logs = [] page.on("console", lambda msg: logs.append("type": msg.type, "text": msg.text)) await browser.close() return "dom_hash": shash, "html_len": len(html), "logs": logs asyncio.run(render_and_capture("https://example.com"))실전에서는 지연 주입, 랜덤 지점 클릭, 입력 폼에 임의 문자열을 넣어 반응을 기록한다. 차단 우회는 합법적 범위를 지키되, 과도한 요청이 되지 않도록 주기와 대상을 조절한다.
정책 문구, 보너스 조건, 출금 제한의 자동 파싱
먹튀 의심 신호 중 가장 높은 가중치를 주는 항목은 약관과 공지의 실질 내용이다. 출금 가능 시간대를 제한한다든지, 베팅 롤링 조건을 과도하게 설정한다든지, 고객센터 채널을 특정 메신저로만 국한한다든지 하는 패턴은 반복된다. 자연어 처리를 거창하게 도입할 필요는 없다. 규칙 기반의 표현식과 단어 사전을 정교하게 다듬으면 충분히 높은 재현율을 낼 수 있다.
import re patterns = 환전).0,10(가능 def extract_signals(text: str): text = re.sub(r"\s+", " ", text) out = for k, pat in patterns.items(): m = pat.search(text) if m: out[k] = m.groups() return out한두 줄로 끝낼 수 없는 애매한 조항이 문제다. 예를 들어 보너스와 관련해 최소 배당 제한을 섞어놓거나, 계정 휴면 규정과 출금 제한을 같은 절에 걸어 중의적 해석의 여지를 만든다. 이런 경우 텍스트 블록을 스팬 단위로 잘라, 핵심 키워드 근방 100자 내에서 상호배타적 용어가 함께 등장하는지를 확인한다. 상충 신호가 보이면 스코어를 크게 올리지 말고 담당자 리뷰 큐로 보낸다. 자동화는 리뷰 대상을 추려주는 게 목적이다.
결제 경로, 머천트 아이디, 온체인 흔적
먹튀 사이트가 남기는 가장 분명한 단서는 결제 채널이다. 카드 결제면 머천트 아이디와 가맹점명이 반드시 어딘가에 흔적으로 남고, 가상계좌나 간편결제면 중계 사업자와 패턴이 보인다. 최근엔 테더 등 스테이블코인을 받는 곳도 늘었다. 이쪽은 주소를 한 번 노출하면 재사용 흔적이 남아 분석이 수월해진다.
머천트 아이디는 결제 창 HTML이나 네트워크 탭을 보면 종종 드러난다. 레거시 PG의 경우 결제 승인 단계에서 리다이렉트 URL에 매개변수로 포함되기도 한다. 합법적 범위에서 자동화된 브라우저로 결제 직전 단계까지 진행하고, 네트워크 요청을 캡처해 저장한 뒤 값의 재사용 여부를 추적한다.
온체인 주소가 보이면 공개 익스플로러 API로 트랜잭션 빈도, 첫 발생 시점, 상호 거래 주소를 수집한다. 트론이나 BSC는 API rate limit이 엄격하지 않아 초기 분석에 적합하다. 다음은 간단한 주소 조회 예시다.
import httpx def tron_tx_count(address: str, api_key: str): url = "https://api.trongrid.io/v1/accounts//transactions".format(address) r = httpx.get(url, headers="TRON-PRO-API-KEY": api_key, params="limit": 1) data = r.json() return data.get("meta", ).get("total", 0)거래가 특정 시퀀스로 빠르게 반복되고, 수취 이후 즉시 스플릿 전송이 이어지면 리스크 점수가 올라간다. 다만 합법적 서비스도 프로세스상 유사한 패턴을 보일 수 있다. 결제 신호만으로 성급히 판정하지 말고, 정책 문구와 도메인 정보 같은 정적 신호와 함께 본다.
평판 데이터, 제보, 검색 결과의 안전한 활용
검색 엔진을 직접 긁는 행위는 서비스 약관 위반 소지가 있어 추천하지 않는다. 합법적 서드파티 SERP API를 쓰거나, 커뮤니티의 RSS와 공개 API, 언론 보도 데이터베이스를 활용하는 편이 안전하다. 텔레그램, 디스코드, 포럼의 경우 콘텐츠 수집이 개인정보 처리와 충돌할 수 있으니 반드시 법무 검토를 거쳐 범위와 보관 기간을 정한다.
제보는 품질의 편차가 크다. 동일 IP 대역에서 일정 시간에 몰려드는 같은 서술, 동일 스크린샷 템플릿, 과도한 감정 표현 등을 신호로 잡아 가중치를 낮춘다. 반대로 여러 커뮤니티에서 시차를 두고 동일 머천트나 계좌, 주소가 반복 언급되면 강한 신호로 취급한다. 이 교차 확인만으로도 오탐을 크게 줄일 수 있다.
변동 감시, 스크린샷 디프, 취약한 링크 구조
운영자가 아침과 저녁에 서로 다른 약관을 띄우는 수법은 오래됐다. 하루 단위가 아니라 6시간 주기로 크롤링해 DOM 해시와 주요 섹션 텍스트를 비교하면 이런 교체를 잡아낼 수 있다. 스크린샷 디프는 헤드리스 브라우저의 뷰포트와 폰트를 고정하고, 동일 요소의 스크롤 위치를 맞춘 뒤 픽셀 레벨 차이를 수치화한다. 응답이 느려지는 시간대, 에러 페이지 비율이 갑자기 튀는 현상도 알람을 붙여두면 유용하다.
한 사례로, 특정 사이트가 새벽 2시부터 4시 사이 특정 국가 IP에서만 출금 페이지를 502로 내렸다. 네트워크 레이어만 보면 CDN 이슈처럼 보였지만, 정책 문구에서 출금 가능 시간대를 은근히 시사하는 문장이 포착되었다. 둘을 결합하니 고의성 신호가 명확해졌다.
파이프라인, 스코어링, 증적 보존
머리로만 그리면 복잡해 보이지만, 단계는 단순하다. 입력은 도메인 혹은 URL 세트, 출력은 리스크 스코어와 근거다. 중간 결과와 증적을 꼼꼼히 남겨, 나중에 언제든 재현 가능하게 만드는 것이 운영의 절반이다.
- 수집: WHOIS, DNS, SSL, 정적/동적 페이지, 네트워크 캡처, 스크린샷 분석: 규칙 기반 텍스트 파싱, 헤더/리디렉션 패턴, 결제 경로 식별, 온체인 조회 스코어링: 신호별 가중 합산, 상충 신호 감점, 최소 근거 개수 충족 조건 검토: 스코어 상위만 샘플링 수기 검토, 사례 라이브러리 업데이트 리포팅: 대시보드, 주간 PDF, 증적 해시와 원본 저장, 법무 공유본 별도 생성
스코어링은 선형 가중 합산부터 시작하되, 신호 간 상호작용을 한두 개 도입하면 성능이 훌륭해진다. 예를 들어 신규 등록 도메인이면서, 텔레그램 전용 고객센터만 공개하고, 출금 시간대를 제한하는 문구가 있으면 가중치를 추가한다. 반대로 조직명과 사업자 등록 정보가 일치해 보이고, 결제 채널이 정상 PG로 일관되며, 6개월 이상 동일 인증서 체인을 유지했다면 동일 조건에서도 점수를 내린다.
증적은 변경 불가능성을 확보해야 한다. 각 크롤링 순간의 HTML, 스크린샷, 응답 헤더를 Parquet와 이미지 원본으로 저장하고, SHA-256 해시를 함께 기록한다. 해시 목록은 별도 저장소에 2중 보관한다. 외부 공유가 필요할 때는 민감 정보를 블러 처리하고, 원본과의 매칭을 위해 해시만 남겨둔다.
오케스트레이션과 코스트 관리
작은 규모면 크론탭으로도 굴러간다. 다만 사이트 수가 수백을 넘고 주기가 짧아지면, 의존성과 실패 재시도, 부분 재실행이 필요하다. Prefect는 파이썬 코드에 데코레이터로 플로우를 얹는 방식이라 진입이 쉽다. Airflow는 DAG가 명시적이고 스케줄링이 강력하지만 운영 난도가 높다. 둘 다 Docker로 러너를 격리하고, 네트워크 이그레스 제한과 시크릿 관리를 붙이면 예측 가능한 환경이 된다.
비용은 트래픽과 렌더링 수에 비례한다. 사례를 기준으로, 500개 도메인을 6시간 주기로 정적 요청 4회, 동적 렌더링 1회를 수행하면 월 트래픽이 대략 150~250GB, 클라우드 egress 비용은 지역에 따라 10~40달러 수준이었다. 헤드리스 브라우저는 CPU를 많이 잡아먹으니, 한 번에 4~8개 워커로 제한하고 큐를 늘리는 편이 총비용을 줄였다. 저장은 Parquet로 압축해 S3 호환 스토리지에 두면 월 수 달러 수준으로 관리 가능했다.
안정성과 실패 전략, 현장에서 겪은 문제들
- 레이트 리미트와 IP 차단: 프록시를 덮어씌우는 식의 단기 처방은 근본 해결이 아니다. 요청을 분산하고, 중복 리소스 캐시, 변경 없는 정적 자원은 해시 기준으로 재요청을 막는다. 로컬에 7일 캐시를 두고, 변동 감시만 집중하면 충분히 줄어든다. 타임아웃과 부분 데이터: 스텝별로 타임아웃을 엄격히 걸고, 실패한 스텝의 상태를 함께 기록한다. 분석 단계는 수집 결과가 비어도 동작하게 방어적으로 짠다. 파서의 취약성: 약관 구조가 바뀌면 파서가 망가진다. 규칙 기반 로직을 여러 개로 쪼개고, 각 규칙의 트리거율을 로그로 남겨 기이한 하락이 보이면 얼리워닝을 띄운다. 다국어와 우회 문자열: 공백을 섞거나 한자, 특수문자 유사체를 끼워 넣는다. 정규화 단계에서 유사 문자 맵을 적용하고, 공백과 제어문자를 정리해 비교한다. 엣지 케이스: 정상 서비스가 일시적 장애로 오탐되는 경우가 있다. 스코어의 가중치를 시계열로 스무딩하고, 단발 이벤트에 덜 민감하도록 이동 평균을 반영한다.
리포팅, 대시보드, 커뮤니케이션
자동화의 가치는 알람에서 결정된다. 담당자가 볼 대시보드는 단순해야 한다. 리스크 상위 N개, 지난 24시간 내 스코어 급등 항목, 신규 도메인, 결제 경로 변경 감지, 정책 문구 변경 감지를 첫 화면에 둔다. 각 항목을 클릭하면 증적 타임라인이 열리고, 스크린샷과 주요 신호가 시간순으로 배치된다. 필요할 때 PDF로 내보내면 된다. WeasyPrint나 Puppeteer 기반으로 템플릿 하나만 잡아도 일관성이 좋아진다.
보안팀, 법무, 고객지원과 공유하는 자료는 관점이 다르다. 법무에는 근거 중심의 보수적 서술, 고객지원엔 고객 안내에 필요한 사실 요약, 보안팀엔 기술적 징후와 재현 방법이 유용하다. 자동화가 이 차이를 인지해 리포트를 다르게 찍어내면 협업 속도가 빨라진다.

법적, 윤리적 고려
먹튀검증은 소비자 보호라는 명분이 있지만, 수집과 분석 과정은 법과 윤리의 틀 안에서 이뤄져야 한다. robots.txt와 사이트 약관을 준수하고, 과도한 요청으로 서비스에 피해를 주지 않는다. 제보자의 개인정보는 수집 목적과 보관 기간을 명확히 공지하고 동의를 확보한다. 제3자 데이터 소스는 라이선스를 확인하고, 상업적 이용 여부를 살핀다.
증적은 무결성과 프라이버시가 동시에 지켜져야 한다. 예치금 화면 스크린샷처럼 민감한 정보는 마스킹하고, 원본 접근 권한을 엄격히 관리한다. 외부 공유 시 해시를 동봉해 진위 검증이 가능하게 하는 습관이 중요하다.
소규모 팀을 위한 현실적 출발선
처음부터 모든 것을 자동화하려 들면 금세 과부하가 온다. 도메인과 SSL, 정적 페이지 수집, 정책 문구 파싱, 스코어링과 알람, 이 다섯 가지만 2주 안에 작동하게 만들면 좋다. 이후 결제 경로와 온체인 파트를 얹고, 헤드리스 렌더링 빈도를 올린다. 매주 10건의 수기 검토를 통해 규칙의 정밀도를 조정하면 한 달 내 체감 성과가 난다.
규칙 업데이트는 형상관리에 넣어, 어떤 변경이 리콜과 프리시전을 어떻게 바꿨는지 기록한다. 운영상 가장 아까운 실수는 규칙을 손으로 고치고 효과를 체계적으로 측정하지 않는 것이다. 리스크 스코어의 히스토그램이 시간에 따라 어떻게 움직이는지 시각화하면, 오탐이 늘거나 과도한 보수성이 끼어들 때 바로 느낄 수 있다.
확장 아이디어, 하지만 필요할 때만
키워드 사전과 정규식으로 충분한 정확도를 낸 뒤에야 복잡한 모델을 고민한다. 도메인 생성 패턴이나 약관 문구의 변형을 분류하는 경량 모델은 도움이 되지만, 데이터와 운영을 견딜 여력이 없다면 유지보수만 늘어난다. 이미지 기반 UI 템플릿 매칭으로 테마 재활용을 탐지하는 방법, 지리적 라우팅 변화로 지역별 차별 운영을 잡아내는 방법, 인증서 안전놀이터 투명성 로그를 스트리밍으로 구독해 신속 탐지하는 방법도 훌륭한 보강 포인트다. 다만 전부를 한 번에 하지 않는다.
사례에서 배운 것
한 분기 동안 관찰한 600개 도메인 중, 등록 30일 내 소멸 혹은 대체 도메인으로 리디렉션된 비율은 대략 18~22%였다. 이들 중 70%가 텔레그램 전용 고객센터를 표방했고, 약 40%가 출금 가능 시간대를 명시 또는 암시했다. 결제 경로는 가상계좌가 55%, 암호자산이 25%, 카드가 20%였다. 암호자산 주소를 재사용한 비율은 30%대였는데, 재사용 주소군을 묶어 관찰하니 도메인 간 운영 공통점이 여럿 보였다. 자동화가 없었다면 이런 상관관계를 찾기 어려웠을 것이다.
반대로 오탐도 있었다. 소규모 합법 서비스가 일시적 장애로 야간 출금 처리가 지연되었고, 규칙이 과하게 반응했다. 시계열 스무딩과 수동 검토 단계를 추가해 해결했다. 자동화는 방아쇠다. 방아쇠가 곧 판정이 되면 곤란해진다.
마무리 메모
먹튀검증의 자동화는 기술 그 자체보다 운영의 문제다. 신호를 모으고, 근거를 보존하고, 사람의 시간을 아껴 가장 의심스러운 소수만 테이블 위에 올리는 작업이다. 작은 파이프라인이 꾸준히 데이터를 쌓을수록, 규칙은 날카로워지고 오탐은 줄어든다. 도구는 교체해도 된다. 남는 것은 축적된 케이스와 증적, 그리고 팀이 공유하는 판단의 기준이다. 이 기준이 있으면 신규 유형이 나타나도 좌표를 잃지 않는다. 자동화는 그 기준을 하루에도 수십 번 되살아 움직이게 하는 엔진에 가깝다.