TRENDSHIFT #12 딥다이브 · 2026-04-02 분석

Sherlock 딥다이브
— 아이디 하나로 400여 개 사이트의 계정 흔적을 동시에 추적하는 OSINT 도구

SNS·커뮤니티에 누가 어떤 닉네임을 쓰는지 사람이 일일이 검색하려면 수백 번을 두드려야 합니다. Sherlocksherlock user123 한 줄로 400개가 넘는 플랫폼에 동시에 접속해, 그 아이디가 살아 있는지 몇 초 만에 알려주는 Python CLI 도구입니다. OSINT(공개정보 수집)·펜테스팅·CTF에서 사실상 표준 도구죠. (저장소: sherlock-project/sherlock · ⭐76.6k · Python 97.3% · MIT)
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

Sherlock이 정확히 무엇을 하는 물건인가

Sherlock400개 이상의 소셜 미디어 플랫폼에서 사용자명(username)을 동시에 검색하여 계정 존재 여부를 탐지하는 Python CLI 도구입니다. sherlock user123 한 줄이면 Instagram, Twitter, GitHub, Reddit 등 수백 개 사이트에서 해당 유저네임이 사용 중인지 몇 초 만에 알려줍니다.

한 컷 비유

"한 사람의 이름을, 400개 동네 주민센터에 동시에 조회하는 셈"

보통은 사이트마다 검색창에 닉네임을 넣어 일일이 확인해야 합니다. Sherlock은 400여 곳에 같은 질문을 한꺼번에 보내고, "이 닉네임이 여기 등록돼 있나요?"라는 답만 모아 옵니다.

핵심은 사이트마다 다른 '계정 없음' 신호를 어떻게 읽어내느냐입니다. 어떤 곳은 404를 던지고, 어떤 곳은 본문에 "페이지 없음"이라 적습니다. Sherlock은 이 판별 규칙을 코드가 아니라 데이터(JSON)로 들고 있어, 새 사이트를 코드 수정 없이 추가합니다.

2왜 주목받는가

트렌딩 이유와 경쟁 도구 대비 강점

Sherlock은 OSINT(Open Source Intelligence, 공개정보 수집) 분야의 사실상 표준 도구입니다. 사이버보안, 펜테스팅, CTF 대회에서 빠지지 않는 필수 도구로 자리잡았고, ⭐76.6k·9k 포크로 Python 보안 도구 중 최상위 인기를 자랑합니다. Docker·pipx·패키지 매니저 등 다양한 설치 방식으로 접근성을 극대화했고, {?} 와일드카드 문법으로 유저네임 변형까지 자동 검색합니다.

경쟁 도구 대비 위치

비교 항목SherlockMaigretWhatsMyName
지원 사이트 수400+3000+500+
설치 난이도매우 쉬움 (pipx 한 줄)보통API 의존
커뮤니티 크기⭐76.6k (압도적)⭐12k⭐2k
탐지 정확도보수적 (거짓양성 최소화)공격적중간
Tor 지원✅ 내장
클라우드 실행Apify Actor
Sherlock의 차별점
"많이"가 아니라 "정확히"

사이트 수는 Maigret보다 적지만, 거짓양성(false positive)을 줄이는 데 집중합니다. exclusion 리스트를 적극 관리하고, WAF(웹 방화벽) 감지 로직까지 내장해 "방화벽에 막힌 것"을 "계정 없음"으로 오판하지 않습니다.

3기술 스택 전체 지도

백엔드(핵심 로직) · 데이터 처리/출력 · 인프라/DevOps

① 백엔드 — 핵심 로직

기술역할버전
Python메인 언어3.9+ (권장 3.10~3.13)
requestsHTTP 클라이언트
requests-futures비동기 HTTP (ThreadPoolExecutor 기반)
PySocksSOCKS 프록시 지원 (Tor 연동)
stemTor 제어 프로토콜 라이브러리
colorama터미널 컬러 출력
certifiSSL 인증서 번들

② 데이터 처리 & 출력

기술역할
pandas결과 데이터 구조화
openpyxlExcel(.xlsx) 출력
csv (stdlib)CSV 출력
json (stdlib)사이트 매니페스트 파싱
argparse (stdlib)CLI 인자 파싱

③ 인프라 & DevOps

기술역할
DockerPython 3.12-slim-bullseye 기반 멀티스테이지 빌드
Poetry빌드 시스템 (poetry-core.masonry.api)
pytest테스트 프레임워크
pytest-xdist병렬 테스트 실행
tox다중 Python 버전 테스트
jsonschema사이트 데이터 스키마 검증
Apify클라우드 실행 플랫폼 (선택)

빌드 시스템 구조

pyproject.toml ├── [build-system] → poetry-core >= 1.2.0 ├── [tool.poetry] → 메타데이터(name, version, python 등) ├── [tool.poetry.dependencies] → 의존성 ├── [tool.poetry.scripts] → sherlock = sherlock_project.sherlock:main └── [tool.poetry.dev-dependencies] → pytest 등 개발 의존성

핵심 포인트: pyproject.toml 하나에 빌드·의존성·스크립트·메타데이터를 모두 통합하는 현대적 Python 패키징 방식입니다. setup.pysetup.cfg 없이 pyproject.toml만으로 패키지를 관리합니다.

4아키텍처 심화 분석

시스템 구조도와 4가지 핵심 설계 패턴

시스템 구조도

┌─────────────────────────────────────────────────────┐ │ CLI (main) │ │ argparse로 인자 파싱 → 설정 구성 │ └──────────┬──────────────────────────────┬─────────────┘ │ │ ▼ ▼ ┌─────────────────────┐ ┌──────────────────────────┐ │ SitesInformation │ │ multiple_usernames() │ │ ┌─────────────────┐ │ │ {?} 와일드카드 확장 │ │ │ data.json (400+) │ │ └──────────┬───────────────┘ │ │ exclusions.txt │ │ │ │ │ NSFW 필터링 │ │ │ │ └─────────────────┘ │ │ └──────────┬──────────┘ │ │ │ ▼ ▼ ┌──────────────────────────────────────────────────────┐ │ sherlock() — 핵심 엔진 │ │ ┌────────────────────────────────────────────────┐ │ │ │ SherlockFuturesSession (ThreadPoolExecutor) │ │ │ │ Site1 ▸ Site2 ▸ Site3 ▸ … ▸ SiteN (Future) │ │ │ │ ▼ get_response() 수집 │ │ │ └────────────────────────────────────────────────┘ │ │ ▼ │ │ 탐지 로직 체인(4단계): WAF → 에러메시지 → 상태코드 → URL│ │ ▼ │ │ QueryResult (CLAIMED / AVAILABLE / UNKNOWN / ILLEGAL / WAF)│ └──────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────┐ │ 출력: 터미널(colorama) · CSV · XLSX(하이퍼링크) · TXT │ └──────────────────────────────────────────────────────┘

패턴 1 — Future 기반 동시성

# SherlockFuturesSession — requests-futures 확장
class SherlockFuturesSession(FuturesSession):
    def request(self, method, url, hooks=None, *args, **kwargs):
        start = time.monotonic()
        def timing_hook(r, *h_args, **h_kwargs):
            r.elapsed = time.monotonic() - start
        # 기존 훅 체인에 추가 (덮어쓰지 않음!)
        hooks["response"] = hooks.get("response", []) + [timing_hook]
        return super().request(method, url, hooks=hooks, *args, **kwargs)
배울 점
requests-futures진짜 asyncio가 아니라 ThreadPoolExecutor(스레드 풀) 기반 비동기입니다. 최대 20개 워커로 400+개 사이트에 동시 요청을 보내죠. 기존 requests API를 그대로 쓰면서 비동기 효과를 얻는 게 장점입니다.

패턴 2 — Chain-of-Responsibility (탐지 로직)

계정 존재 여부를 판단하는 4단계 체인입니다.

요청 응답 수신 │ ├─ 1단계: WAF 감지 → Cloudflare/PerimeterX/AWS 핑거프린트 매칭 │ → 매칭되면 → QueryStatus.WAF (건너뜀) ├─ 2단계: 에러 메시지 검사 → 본문에 "not found" 류 존재? │ → 있으면 AVAILABLE / 없으면 CLAIMED ├─ 3단계: HTTP 상태 코드 → 예상 에러코드와 비교 │ → 일치하면 AVAILABLE / 불일치면 CLAIMED └─ 4단계: 리다이렉트 URL → 에러 URL 패턴과 일치? → 일치하면 AVAILABLE / 불일치면 CLAIMED

각 사이트의 errorType 설정에 따라 어떤 단계를 쓸지 결정됩니다. 이것이 데이터 주도 설계(Data-Driven Design)의 핵심 — 탐지 로직을 코드가 아니라 data.json 설정으로 제어합니다.

패턴 3 — 옵저버 패턴 (알림 시스템)

class QueryNotify:          # 추상 베이스
    def start(self, message): ...
    def update(self, result): ...
    def finish(self, message): ...

class QueryNotifyPrint(QueryNotify):  # 구체 구현
    def update(self, result):
        if result.status == QueryStatus.CLAIMED:
            print(f"[+] {site_name}: {url}")   # 초록색
        elif self.print_all:
            print(f"[-] {site_name}: Not Found")  # 빨간색

이 패턴 덕분에 터미널 출력을 웹소켓 알림·로그 파일 등으로 쉽게 교체할 수 있습니다.

패턴 4 — 재귀적 문자열 보간

def interpolate_string(input_object, username):
    if isinstance(input_object, str):
        return input_object.replace("{}", username)
    elif isinstance(input_object, dict):
        return {k: interpolate_string(v, username) for k, v in input_object.items()}
    elif isinstance(input_object, list):
        return [interpolate_string(item, username) for item in input_object]
    return input_object

중첩된 딕셔너리/리스트 안의 모든 {}를 유저네임으로 치환합니다. JSON 설정 파일에서 동적 값을 주입할 때 매우 유용한 패턴입니다.

5디렉토리 구조 해부

어디에 무엇이 있는가 — 핵심 파일 중심으로
sherlock/ ├── .actor/ # Apify 클라우드 실행 설정 ├── .github/ # CI/CD 워크플로우, 이슈 템플릿 ├── devel/ # 개발자 도구, 유틸리티 스크립트 ├── docs/ # 문서 (Mintlify 기반 웹사이트 소스) ├── sherlock_project/ # 🔑 메인 패키지 │ ├── __init__.py # 버전 정보, 패키지 초기화 │ ├── __main__.py # python -m sherlock_project 진입점 │ ├── sherlock.py # 🔑 핵심 엔진 (sherlock() + main()) │ ├── sites.py # 사이트 데이터 로딩/관리 (SitesInformation) │ ├── result.py # QueryStatus Enum + QueryResult 데이터 클래스 │ ├── notify.py # 옵저버 패턴 알림 시스템 │ ├── py.typed # PEP 561 타입 힌트 마커 │ └── resources/ │ ├── data.json # 🔑 400+ 사이트 매니페스트 (103KB) │ └── data.schema.json # JSON Schema 검증 규칙 ├── tests/ │ ├── conftest.py # pytest 픽스처 + 동적 파라미터화 │ ├── test_manifest.py # data.json 스키마 검증 테스트 │ ├── test_probes.py # 실제 HTTP 요청 탐지 테스트 │ ├── test_ux.py # CLI UX 테스트 │ └── test_version.py # 버전 일관성 테스트 ├── Dockerfile # 멀티스테이지 Docker 빌드 ├── pyproject.toml # 빌드/의존성/스크립트 통합 설정 ├── pytest.ini # pytest 설정 └── tox.ini # 다중 Python 버전 테스트 설정

주요 파일별 역할

파일줄 수(추정)핵심 역할
sherlock.py~930전체 흐름: 인자 파싱 → 사이트 로드 → 동시 요청 → 결과 수집
sites.py~260데이터 소스 추상화: URL/파일/기본값에서 사이트 정보 로드
result.py~905가지 상태를 가진 Enum + 결과 컨테이너
notify.py~280옵저버 패턴으로 결과 출력 분리
data.json~103KB모든 사이트의 URL 패턴, 탐지 방법, 에러 메시지 등

6학습 포인트 (기술별)

이 레포에서 실제로 배울 수 있는 것들

6-1. Python 동시성 프로그래밍

스레드 풀 기반 비동기 HTTP — 동기 방식과 비교하면 차이가 한눈에 보입니다.

# 일반적인 동기 요청 (느림)
for site in sites:
    response = requests.get(site.url)        # 하나씩 순서대로

# Sherlock의 방식 (빠름)
session = SherlockFuturesSession(max_workers=20)
futures = {}
for site in sites:
    futures[site] = session.get(site.url)    # 즉시 반환 (Future)
for site, future in futures.items():
    response = future.result()               # 여기서 대기
실습 아이디어
100개 URL 목록의 상태 코드를 동기/비동기로 각각 체크해보고 소요 시간을 비교해보세요.

6-2. 데이터 주도 설계 (Data-Driven Design)

탐지 로직을 코드가 아니라 JSON 데이터로 제어합니다.

{
  "GitHub": {
    "url": "https://www.github.com/{}",
    "errorType": "status_code",
    "errorCode": 404,
    "username_claimed": "torvalds"
  },
  "Instagram": {
    "url": "https://www.instagram.com/{}",
    "errorType": "message",
    "errorMsg": "Sorry, this page isn't available.",
    "username_claimed": "instagram"
  }
}

사이트마다 탐지 방식이 다릅니다 — 어떤 곳은 404, 어떤 곳은 본문 메시지. if문으로 하드코딩하면 400개마다 분기가 필요하지만, JSON 매니페스트로 분리하면 코드 한 줄 안 바꾸고 새 사이트를 추가할 수 있습니다.

6-3. JSON Schema 검증

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": {
    "required": ["url", "urlMain", "errorType", "username_claimed"],
    "if":   { "properties": { "errorType": { "const": "message" } } },
    "then": { "required": ["errorMsg"] }
  }
}

errorType이 "message"이면 errorMsg가 필수 — 이런 조건부 검증을 스키마로 표현하고, CI에서 PR마다 자동 검증해 잘못된 데이터 머지를 막습니다.

6-4. 현대적 Python 패키징

[build-system]
requires = ["poetry-core>=1.2.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "sherlock-project"

[tool.poetry.dependencies]
python = "^3.9"

[tool.poetry.scripts]
sherlock = "sherlock_project.sherlock:main"

이 한 파일로 빌드 시스템 지정·의존성 관리·CLI 엔트리포인트 등록·메타데이터 관리를 모두 처리합니다.

6-5. 테스트 전략 — pytest 동적 파라미터화

def pytest_generate_tests(metafunc):
    if "chunked_sites" in metafunc.fixturenames:
        sites = fetch_local_manifest()
        metafunc.parametrize("chunked_sites",
                             list(sites.items()),
                             ids=[s for s in sites])

사이트 하나당 테스트 케이스 하나가 자동 생성됩니다. pytest --chunked-sites=GitHub,Instagram처럼 특정 사이트만 골라 테스트할 수도 있습니다.

6-6. Docker 멀티스테이지 빌드

# Stage 1: pip 업그레이드만 수행
FROM python:3.12-slim-bullseye AS build
RUN pip install --upgrade pip

# Stage 2: 런타임 환경 — pip install로 직접 설치 (Stage 1 파일 복사 없음)
FROM python:3.12-slim-bullseye
RUN pip install sherlock-project==${VERSION_TAG}
WORKDIR /sherlock
ENTRYPOINT ["sherlock"]

6-7. WAF 감지 패턴

보안 도구 설계 통찰
WAF는 '우회'가 아니라 '감지' 대상

Sherlock은 응답 본문에서 Cloudflare·PerimeterX·AWS WAF의 고유 핑거프린트를 검사합니다. WAF에 막힌 결과를 "계정 없음"으로 오판하면 안 되기 때문에, 막혔다는 사실 자체를 별도 상태(WAF)로 분류합니다.

7하드웨어 / 시스템 요구사항

돌리는 데 필요한 최소·권장 사양
항목최소권장
Python3.93.12+
RAM256MB512MB+
네트워크인터넷 필수안정적인 브로드밴드
디스크~50MB~100MB (Docker 이미지 포함)
OSLinux/macOS/WindowsLinux (Docker 또는 WSL)

Tor 사용 시: Tor 서비스 설치 필요 (sudo apt install tor).

8직접 해볼 수 있는 실습 과제

난이도별 5개 — 손으로 익히는 게 가장 빠릅니다
과제 1 ⭐ 초급

기본 실행과 결과 분석

# 설치
pipx install sherlock-project

# 자신의 유저네임 검색
sherlock 내유저네임 --print-all --csv

# 결과 CSV 분석
python -c "
import pandas as pd
df = pd.read_csv('내유저네임.csv')
print(f'발견: {len(df[df.status == \"Claimed\"])}개')
print(f'미발견: {len(df[df.status == \"Available\"])}개')
"
과제 2 ⭐⭐ 중급

나만의 사이트 추가하기

data.json에 새 사이트를 추가하고 --json local_data.json 옵션으로 로드해 테스트해보세요.

{
  "DCInside": {
    "url": "https://gallog.dcinside.com/{}",
    "urlMain": "https://www.dcinside.com",
    "errorType": "status_code",
    "errorCode": 404,
    "username_claimed": "test",
    "tags": ["community"]
  }
}
과제 3 ⭐⭐⭐ 고급

탐지 로직 개선 — aiohttp로 교체

스레드 풀(requests-futures) 대신 진짜 async(aiohttp) 프로토타입을 만들어 성능을 벤치마크해보세요.

import aiohttp, asyncio

async def check_site(session, site_name, url):
    try:
        async with session.get(url, timeout=aiohttp.ClientTimeout(total=30)) as resp:
            return site_name, resp.status, await resp.text()
    except Exception as e:
        return site_name, 0, str(e)

async def sherlock_async(username, sites):
    async with aiohttp.ClientSession() as session:
        tasks = [check_site(session, name, url.format(username))
                 for name, url in sites.items()]
        return await asyncio.gather(*tasks)
과제 4 ⭐⭐⭐ 고급

결과 시각화 대시보드

Flask + SSE(Server-Sent Events)로 검색 결과를 실시간 스트리밍하는 웹 대시보드를 만들어보세요.

from flask import Flask, Response
import json
app = Flask(__name__)

def generate_results(username):
    for site_name, result in sherlock(username):
        yield f"data: {json.dumps({'site': site_name, 'status': result.status.value})}\n\n"

@app.route('/search/<username>')
def search(username):
    return Response(generate_results(username), mimetype='text/event-stream')
과제 5 ⭐⭐ 중급

CLI 도구 패키징 연습

Sherlock의 pyproject.toml 구조를 참고해 자신만의 CLI 도구를 PyPI에 배포해보세요.

1. pyproject.toml 작성 (build-system, project, scripts)
2. pipx install .  로 로컬 테스트
3. TestPyPI 배포:
   pip install build twine
   python -m build
   twine upload --repository testpypi dist/*

9관련 기술 심화 학습 로드맵

5주 코스 — Sherlock을 분해하며 배우는 길

1주차 · Python 동시성 기초

학습 내용
1–2threading vs multiprocessing vs asyncio 개념 이해
3–4concurrent.futures (ThreadPoolExecutor, ProcessPoolExecutor) 실습
5requests-futures 소스 읽기 — Sherlock이 이걸 어떻게 활용하는지
6–7미니 프로젝트: 100개 URL 상태 체커 (동기 vs 비동기 비교)

2주차 · 현대적 Python 패키징

학습 내용
1–2pyproject.toml 상세 스펙 (PEP 517, 518, 621)
3–4Poetry vs Hatch vs PDM 비교, 각각으로 프로젝트 셋업
5pipx로 CLI 도구 배포하는 전체 플로우
6–7TestPyPI에 실제 패키지 배포

3주차 · 테스트 전략 심화

학습 내용
1–2pytest 고급: fixture scope, parametrize, conftest
3–4tox로 다중 Python 버전 테스트 환경 구성
5–6JSON Schema 검증: jsonschema 라이브러리 + CI 통합
7Sherlock 테스트 코드 전체 분석 및 커버리지 측정

4주차 · Docker & 배포

학습 내용
1–2Docker 멀티스테이지 빌드 패턴
3–4GitHub Actions CI/CD 파이프라인 작성
5–6Apify Actor 등 서버리스 플랫폼에 CLI 도구 배포
7전체 워크플로우 통합: 코드 → 테스트 → Docker → 배포

5주차 · OSINT & 보안 도구 개발

학습 내용
1–2OSINT 방법론 개요, Tor/프록시 네트워크 이해
3–4WAF 탐지 기법, HTTP 핑거프린팅
5–6나만의 미니 OSINT 도구 만들기 (예: 도메인 정보 수집기)
7윤리적 해킹/보안 연구 가이드라인 학습

10핵심 키워드 사전

모르고 지나치기 쉬운 용어 정리
용어설명
OSINTOpen Source Intelligence. 공개된 정보원에서 유용한 정보를 수집·분석하는 기법
WAFWeb Application Firewall. 웹 앞단에서 악성 트래픽을 차단하는 보안 장치 (Cloudflare, AWS WAF 등)
Future아직 완료되지 않은 비동기 작업의 결과를 나타내는 객체. future.result()로 결과를 가져옴
ThreadPoolExecutor스레드 풀을 관리해 여러 작업을 병렬 실행하는 Python 표준 라이브러리 클래스
requests-futuresrequests에 Future 패턴을 적용한 라이브러리. 요청을 보내면 Future를 반환
pyproject.toml빌드 시스템·의존성·메타데이터를 통합 관리하는 설정 파일 (PEP 518/621)
PoetryPython 의존성 관리 + 패키지 빌드 도구. pyproject.toml 기반
pipxPython CLI 도구를 격리된 가상환경에 설치하는 도구. 시스템 Python을 더럽히지 않음
JSON SchemaJSON 데이터의 구조와 유효성을 정의하는 표준. API 문서화·데이터 검증에 사용
Chain-of-Responsibility처리 가능한 핸들러 체인을 만들어 첫 번째로 처리 가능한 핸들러가 처리하는 디자인 패턴
옵저버 패턴객체의 상태 변화를 구독자에게 자동 통지하는 디자인 패턴. 결과 알림에 사용
멀티스테이지 빌드Docker에서 빌드 환경과 런타임을 분리해 최종 이미지 크기를 줄이는 기법
TorThe Onion Router. 여러 노드를 거쳐 IP를 숨기는 익명 네트워크
SOCKS 프록시TCP 수준에서 동작하는 범용 프록시 프로토콜. Tor는 SOCKS5 사용
핑거프린팅시스템/서비스의 고유 특성을 분석해 종류·버전을 식별하는 기법
데이터 주도 설계동작을 코드 로직이 아니라 외부 데이터(JSON/YAML 등)로 제어하는 설계 방식
PEP 561Python 패키지의 타입 힌트 지원을 선언하는 표준. py.typed 마커 파일 사용

11참고 링크

더 깊이 파고들 때 보면 좋은 자료