TrendShift 딥다이브 · 2026-07-03 · Daily #3

douyin-downloader 딥다이브
— 무수익 오픈소스가 보여주는 "웹 스크래핑 엔지니어링"의 교과서

douyin-downloader는 중국판 틱톡인 抖音(더우인) 영상·이미지·음악·라이브를 링크 한 줄로 일괄 내려받는 파이썬 CLI 도구다. 단순 다운로더처럼 보이지만, 내부는 요청 서명(X-Bogus/A-Bogus) 위조 · 비동기 동시성 · 속도 제한 · 지수 백오프 재시도 · SQLite 중복제거 · 브라우저 폴백까지 갖춘, "봇을 막으려는 서버"와 "긁으려는 클라이언트"의 공방을 코드로 배우기 딱 좋은 표본이다. 파이썬 asyncio + aiohttp 기반, 전략(Strategy)·팩토리(Factory) 패턴으로 6종 다운로드 모드를 깔끔히 분리했다. (저장소: jiji262/douyin-downloader · Python · MIT · v2.0.0 · TrendShift 오늘 Daily 3위, 모멘텀 817)
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

이 저장소가 대체 무엇인가.

douyin-downloader는 抖音(Douyin, 중국 본토판 TikTok)의 콘텐츠를 터미널 명령 한 줄 또는 설정 파일 하나로 대량 수집하는 파이썬 도구다. 단일 영상부터 특정 크리에이터의 전체 게시물·좋아요·컬렉션·음악·즐겨찾기까지, 그리고 라이브 방송 녹화까지 다룬다.

한 줄 개념
스크래핑(Scraping) 다운로더
공식 다운로드 버튼이 없는(또는 워터마크가 박히는) 콘텐츠를, 웹사이트가 내부적으로 쓰는 비공개 API를 흉내내어 원본 파일을 받아오는 프로그램. 브라우저가 하는 요청을 코드로 재현하는 게 핵심.
비유로 이해하기

"자판기 뒤로 돌아가 재고 트럭에서 직접 받기"

앱에서 영상을 보는 건 자판기 앞에서 버튼을 눌러 캔을 받는 것과 같다. 하지만 자판기(앱)는 캔에 스티커(워터마크)를 붙이고, 한 번에 하나씩만 준다. 이 도구는 자판기가 재고를 채울 때 쓰는 뒷문(내부 API)을 찾아, 스티커 붙기 전의 원본 캔을 트럭째 받아온다.

문제는 그 뒷문에 "직원만 아는 암호 노크"(요청 서명)가 걸려 있다는 것. 이 프로젝트 코드의 절반은 그 노크 소리를 정확히 재현하는 데 쓰인다.

버전은 2.0.0이며, CLI 도구 + REST API 서버 모드 + (베타) 데스크톱 GUI(Douzy) 세 형태를 같은 파이썬 백엔드로 공유한다. 라이선스는 관대한 MIT. 저자는 README에 "무료! 무료! 무료!"를 반복하며 상업적 의도가 없음을 강조한다.

먼저 짚고 갈 것 — 법적/윤리적 주의
"기술을 배우는 것"과 "함부로 쓰는 것"은 다르다

이 도구는 비공개 API를 역이용하고 워터마크(저작자 표시)를 제거한다. 이는 대상 플랫폼의 이용약관 위반일 수 있고, 남의 창작물을 무단 재배포하면 저작권 침해가 된다. 이 문서는 스크래핑·비동기·안티봇 우회의 소프트웨어 엔지니어링을 학습하기 위한 자료이지, 무단 수집을 권하는 것이 아니다. 실제 사용은 본인이 올린 콘텐츠 백업 등 합법적 범위로 한정할 것.

2왜 주목받는가

트렌딩 이유와, 흔한 "다운로더 스크립트"와의 결정적 차이.

① 단순 스크립트가 아니라 "제대로 설계된 애플리케이션"

GitHub에 널린 다운로더 대부분은 requests.get() 한 뭉치의 스파게티 스크립트다. 이 프로젝트는 다르다. 109개 파이썬 파일이 core / control / storage / auth / config / utils로 계층 분리돼 있고, 60개 이상의 테스트 파일(property-based 테스트 포함)과 GitHub Actions CI, Docker, 심지어 각 폴더마다 AGENTS.md(AI 코딩 에이전트용 규칙서)까지 있다.

비교

보통 다운로더 = 라면 하나 끓이는 즉석 조리. 이 프로젝트 = 주방을 구역별로 나누고(전처리·조리·플레이팅), 레시피를 문서화하고, 위생 점검(테스트)까지 통과시킨 영업용 주방. 배우기엔 후자가 압도적으로 값지다.

② "안티봇 vs 스크래퍼" 공방을 실물로 보여준다

더우인 서버는 자동화 요청을 막으려고 요청마다 X-Bogus·A-Bogus라는 서명 파라미터를 요구한다. 브라우저가 자바스크립트로 만들어 붙이는 값인데, 이 프로젝트는 그 알고리즘을 파이썬으로 포팅(이식)해 두었다(utils/xbogus.py, utils/abogus.py). 여기에 더해:

즉, "서버가 막으면 어떻게 우회하나"의 여러 계층을 한 코드베이스에서 관찰할 수 있다.

③ 무료·자기호스팅·프라이버시

비슷한 상용 서비스는 유료 구독이거나, 사용자의 링크를 자기네 서버로 보낸다. 이 도구는 내 컴퓨터에서 로컬 실행되어 데이터가 밖으로 안 나간다. 자기호스팅(Self-hosted)·프라이버시 선호 흐름과 맞물려 TrendShift 상위권에 올랐다. 중국어권 개발자 커뮤니티(linux.do 등)에서의 화제성도 모멘텀에 기여했다.

배움 관점 핵심
"이 레포에서 무엇을 얻는가"

대상이 더우인이라는 점은 부차적이다. 진짜 가치는 비동기 네트워크 프로그래밍 · 안티봇 우회 · 견고한 재시도/속도제어 · 계층형 아키텍처 · 전략/팩토리 패턴실전 규모의 코드로 통째로 볼 수 있다는 것.

3기술 스택 전체 지도

무엇으로 만들어졌나 — 계층별로.

핵심 런타임 / 비동기

기술역할왜 이걸 썼나
Python ≥3.9전체 언어스크래핑 생태계(요청·파싱) 풍부, 3.9~3.12 지원
asyncio동시성 엔진수백 개 다운로드를 스레드 없이 동시 처리(I/O 대기 시간 활용)
aiohttp비동기 HTTP 클라이언트API 호출·파일 다운로드를 논블로킹으로
httpx보조 HTTPstorage/file_manager.py가 런타임에 사용(요구사항에 명시 고정)
aiofiles비동기 파일 I/O디스크 쓰기도 이벤트 루프를 막지 않게
aiosqlite비동기 SQLite다운로드 이력 DB를 async로 조회/기록

서명 위조 / 인증

기술역할
xbogus.pyX-Bogus 서명 생성(구형 엔드포인트용). Evil0ctal 프로젝트 기반 Apache-2.0 이식
abogus.pyA-Bogus 서명 + 브라우저 지문(fingerprint) 생성(신형 엔드포인트용, 선택적)
gmssl중국 국산 암호(SM3 등) — 서명 알고리즘 내부 해시에 필요
auth/cookie_manager, ms_token_manager쿠키·ms_token 로드/정제/갱신, 민감 쿠키 차단 목록 관리

제어 계층 (안정성)

모듈역할
control/rate_limiter.py초당 요청 수 제한(기본 2 req/s) + 랜덤 지터로 봇 탐지 회피
control/retry_handler.py지수 백오프 재시도(1s→2s→5s, 기본 3회)
control/queue_manager.py동시 다운로드 개수 제한(기본 5) — 세마포어식 큐

저장 / 미디어 / 부가

기술역할
SQLite (aiosqlite)다운로드 이력·중복제거·증분 다운로드의 단일 진실원
rich터미널 진행바·컬러 로그(예쁜 CLI UX)
imageio-ffmpeg (0.6.0 고정)번들 ffmpeg 정적 바이너리 — 음성 추출 후 전사(transcription)에 사용
PyYAMLconfig.yml 설정 파싱
Playwright optional [browser]실제 브라우저 폴백(페이지네이션 차단·CAPTCHA 대응)
openai-whisper optional [transcribe]영상 음성 → 자막 텍스트 전사
FastAPI + uvicorn optional [server]--serve REST API 서버 모드
pytest + hypothesis + ruff [dev]테스트(속성기반 포함) + 린트
용어
Optional dependencies (선택 의존성)
기본 설치엔 안 들어가고, 필요할 때만 pip install "douyin-downloader[browser]"처럼 대괄호로 골라 까는 추가 패키지 묶음. 무거운 Playwright·Whisper를 안 쓰는 사람은 안 깔아도 되게 하는 배려.

4아키텍처 심화 분석

데이터가 링크 한 줄에서 파일까지 흐르는 전 과정.

전체 파이프라인 (한 눈에)

[사용자] "douyin-dl --url https://v.douyin.com/xxxx" │ ▼ ┌─────────────────────────────────────────────────────────┐ │ cli/main.py ── 인자 파싱 · 설정 로드 · 재로그인 래퍼 │ └─────────────────────────────────────────────────────────┘ │ resolve_short_url() (단축링크 → 실제 URL) ▼ ┌──────────────────┐ URL 종류 판별(정규식) │ core/url_parser │──► video / user / collection / │ URLParser.parse │ gallery / music / live └──────────────────┘ │ {type, aweme_id | sec_uid | mix_id ...} ▼ ┌──────────────────────────────────────────────┐ │ core/downloader_factory.py │ ← 팩토리 패턴 │ type → 알맞은 Downloader 인스턴스 생성 │ └──────────────────────────────────────────────┘ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ Video User Mix Music Live Downloader Downloader ... ... Downloader │ │ 공유 도구를 주입(DI)받아 실제 일 수행 ▼ ┌───────────────┬───────────────┬────────────────────────┐ │ APIClient │ control/* │ storage/* │ │ (서명+요청) │ (속도·재시도· │ (파일·메타·DB 중복제거) │ │ │ 동시성 큐) │ │ └───────────────┴───────────────┴────────────────────────┘ │ ▼ Downloaded/작성자명/YYYY-MM-DD_제목/ ← 파일 + JSON + 매니페스트

핵심 설계 패턴 ① — 팩토리(Factory)

DownloaderFactory.create(url_type, ...)가 URL 종류에 따라 알맞은 다운로더 객체를 만들어 돌려준다. 호출부(cli/main.py)는 "어떤 다운로더가 필요한지" 몰라도 되고, 새 종류(예: 라이브)를 추가할 때 팩토리에 분기 한 줄만 더하면 된다.

# core/downloader_factory.py — 타입 → 객체 매핑 (핵심만)
if url_type == "video":   return VideoDownloader(**common_args)
elif url_type == "user":    return UserDownloader(**common_args)
elif url_type == "collection": return MixDownloader(**common_args)
elif url_type == "music":   return MusicDownloader(**common_args)
elif url_type == "live":    return LiveDownloader(**common_args)
# common_args = config·api_client·file_manager·database·
#               rate_limiter·retry_handler·queue_manager ... (의존성 주입)

핵심 설계 패턴 ② — 전략(Strategy) : 유저 모드 분리

한 크리에이터를 긁을 때도 게시물(post) · 좋아요(like) · 컬렉션(mix) · 음악(music) · 즐겨찾기(collect)는 API 엔드포인트와 페이지네이션 규칙이 제각각이다. 이걸 core/user_modes/ 아래 전략 클래스로 하나씩 떼어냈다. base_strategy.py가 공통 뼈대, 각 *_strategy.py가 모드별 차이만 구현한다.

비유

전략 패턴은 "교체형 드릴 비트"다. 드릴 본체(UserDownloader)는 하나지만, 나무용·콘크리트용·금속용 비트(전략)를 상황에 맞게 갈아 끼운다. 새 재질이 나와도 비트만 새로 만들면 본체는 안 건드린다.

핵심 설계 패턴 ③ — 의존성 주입(DI)으로 "공유 도구" 재사용

APIClient·RateLimiter·RetryHandler·Database 같은 무거운 객체는 한 번 만들어 모든 다운로더에 주입한다. 덕분에 속도 제한이 전체에 일관 적용되고, DB 커넥션도 공유된다. common_args 딕셔너리가 그 주입 통로다.

안정성 3종 세트가 맞물리는 방식

각 API 요청마다: RateLimiter.acquire() ──► "초당 2회" 지키고 0~0.5s 랜덤 지터 대기 │ (봇처럼 규칙적이지 않게 = 탐지 회피) ▼ RetryHandler.execute_with_retry(fn) │ 시도1 실패 → 1s 대기 → 시도2 실패 → 2s → 시도3 → 5s ▼ QueueManager ──► 동시에 최대 5개만 (서버 과부하·차단 방지)
# control/rate_limiter.py — 지터가 "락 안"에 있는 이유
async with self._lock:
    # 최소 간격(1/2초) 못 채웠으면 그만큼 대기
    if time_since_last < self.min_interval:
        await asyncio.sleep(self.min_interval - time_since_last)
    # 지터도 락 안에서 — 다음 요청이 "실제 발사 시각" 기준으로 대기하도록
    await asyncio.sleep(random.uniform(0, 0.5))
    self.last_request = time.time()
디테일이 살아있는 지점
주석이 "왜"를 설명한다

지터를 락 밖에 두면 두 요청이 거의 동시에 나갈 수 있다 — 코드 주석이 이 함정을 정확히 짚는다. pyproject.toml조차 "imageio-ffmpeg 0.6.0은 macOS arm64 휠을 처음 제공하는 버전이라 고정" 같은 결정의 이유를 남긴다. 협업·유지보수를 진지하게 고려한 코드베이스라는 신호.

로그인 필요 감지 → 자동 재로그인

더우인이 status_code == 2483(또는 "请先登录=먼저 로그인하세요")를 주면 LoginRequiredError가 발생하고, cli/main.py_run_with_relogin 래퍼가 이를 잡아 대화형 재로그인 후 자동 재시도한다. 긴 배치 작업 중 세션이 끊겨도 멈추지 않게 하는 실전 배려다(docs/superpowers/specs/2026-06-25-auto-relogin-design.md에 설계 문서까지 있음).

5디렉토리 구조 해부

폴더 이름만 봐도 책임이 보이도록 나눴다.

douyin-downloader/ ├── cli/ # 진입점 · 인자 파싱 · 진행바 · 로그인 흐름 · 전사 │ ├── main.py (오케스트레이터: download_url, main_async) │ ├── login_flow.py (대화형 로그인) │ └── progress_display.py(rich 진행바) ├── core/ # ★ 다운로드 두뇌 — 종류별 다운로더 + URL 파싱 + API │ ├── api_client.py (서명 붙여 요청, 로그인필요 감지) │ ├── url_parser.py (정규식으로 URL 종류/ID 추출) │ ├── downloader_factory.py (타입→다운로더 매핑) │ ├── video/mix/music/live/user_downloader.py │ └── user_modes/ (post·like·mix·music·collect 전략) ├── control/ # 안정성 3종 — 속도제한·재시도·동시성 큐 ├── storage/ # 파일 저장 · 메타데이터 · SQLite(중복제거/증분) │ ├── file_manager.py (다운로드·무결성 검증) │ ├── metadata_handler.py(JSON 부가정보) │ └── database.py (이력 DB, 커버 미러 정렬 등) ├── auth/ # 쿠키·ms_token 관리(민감 쿠키 차단) ├── config/ # YAML 로드 + 기본 설정 + 검증 ├── utils/ # 서명(xbogus/abogus)·네이밍·검증·알림·로거 ├── tools/ # cookie_fetcher(브라우저에서 쿠키 자동 추출) ├── server/ # FastAPI 앱 + 잡(job) 관리 (REST API 모드) ├── tests/ # 60+ 테스트(속성기반 hypothesis 포함) ├── AGENTS.md # AI 코딩 에이전트용 프로젝트 규칙(폴더마다 존재) ├── Dockerfile · config.example.yml · pyproject.toml
읽는 요령

core = 무엇을 받나, control = 어떻게 안전하게 받나, storage = 어디에 어떻게 쌓나, auth = 어떻게 서버를 통과하나. 이 4개 폴더만 이해하면 전체가 손에 잡힌다. 나머지(cli·config·utils·server)는 이들을 감싸는 껍데기·도구.

주목할 관례: 폴더마다 AGENTS.md가 있어 Claude Code 같은 AI 에이전트가 그 폴더를 수정할 때 지켜야 할 규칙을 명시한다. 또 CLAUDE.md는 이 CLI가 데스크톱 앱과 백엔드 코드를 공유하니 "공유 로직을 고치면 양쪽에 똑같이 반영하라"고 지시한다. "사람+AI 협업"을 전제로 설계된 최신 리포의 전형.

6학습 포인트 (기술별)

이 코드에서 구체적으로 무엇을 훔쳐 배울 수 있나.

① 비동기(asyncio) 실전

튜토리얼의 asyncio.sleep 예제를 넘어, 실제 네트워크·파일·DB를 전부 async로 엮은 코드를 볼 수 있다. aiohttp(요청)·aiofiles(디스크)·aiosqlite(DB)가 한 이벤트 루프 위에서 협력한다. asyncio.Lock으로 공유 상태(마지막 요청 시각)를 보호하는 법도 rate_limiter에서 배운다.

② 안티봇 우회의 원리

용어
요청 서명 (Request Signing) — X-Bogus / A-Bogus
클라이언트가 요청 파라미터+시각+브라우저 지문을 특정 알고리즘으로 뒤섞어 만든 짧은 문자열. 서버는 같은 알고리즘으로 검산해 "진짜 웹페이지에서 온 요청"인지 판별한다. 자동화 스크립트는 이 값을 못 만들면 거절당한다.

utils/xbogus.py는 커스텀 문자셋("Dkdpgh4ZKsQB80/Mfvw...")과 자체 base64·해시로 서명을 조립한다. "브라우저 JS가 하는 일을 서버 언어로 재현"하는 리버스 엔지니어링의 살아있는 예다. (이 파일은 Evil0ctal의 Douyin_TikTok_Download_API 프로젝트에서 온 Apache-2.0 코드다.)

③ 견고한 네트워크 클라이언트 만들기

실서비스 스크래퍼가 반드시 갖춰야 할 속도 제한 + 지수 백오프 재시도 + 동시성 제한 + 지터를 각각 독립 모듈로 구현한 참고서. 이 패턴은 더우인뿐 아니라 어떤 API 클라이언트에도 그대로 이식 가능하다.

④ 테스트 가능한 설계

팩토리·전략·DI 덕에 각 부품을 가짜(mock)로 갈아끼워 단위 테스트할 수 있다. tests/의 60여 개 파일, 특히 hypothesis 기반 속성 기반 테스트(무작위 입력 수천 개로 불변식 검증) — test_notifier_redactor_property.py(민감정보 마스킹이 항상 성립하는가), test_proxy_validator_parity.py 등을 읽어볼 것.

실습 아이디어(가벼운 것)
rate_limiter만 떼어 내 프로젝트에

control/rate_limiter.py는 40줄 남짓이고 외부 의존이 없다. 내가 만든 아무 API 호출 루프에 붙여 "초당 N회 + 지터"를 걸어보고, 지터를 락 밖으로 빼면 어떻게 동시 발사가 생기는지 로그로 확인해보라.

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

돌리는 데 뭐가 필요한가.

항목요구
Python3.9 ~ 3.12
OSWindows / macOS / Linux (크로스플랫폼). Docker 이미지 제공
기본 설치pip install -e . — aiohttp·httpx·rich·SQLite 등 경량
디스크다운로드 대상만큼. 도구 자체는 수십 MB(ffmpeg 정적 바이너리 포함)
브라우저 폴백[browser] 설치 + Playwright 크로미움(수백 MB)
전사(자막)[transcribe] Whisper — CPU로도 되나 GPU면 빠름. OpenAI 호환 전사 API 키(선택)
필수 준비물더우인 쿠키(로그인 상태). 즐겨찾기·좋아요 등은 로그인 필수
네트워크중국 서비스라 지역/프록시 설정이 필요할 수 있음(proxy 설정 지원)

핵심은 무겁지 않다는 것. GPU도, 대용량 RAM도 기본 사용엔 불필요하다. 병목은 오직 네트워크 대역폭과 서버의 속도 제한이다 — 그래서 코드가 속도제한·재시도에 그토록 공을 들인다.

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

난이도별로 — 코드를 읽고 손대며 배우기. (합법적 범위: 본인 콘텐츠·공개 학습용 소규모로)

LV.1 · 코드 읽기

URL 파서 정규식 해독하기 쉬움

core/url_parser.py_extract_video_id 등 정규식이 /video/(\d+) 같은 패턴으로 ID를 뽑는 과정을 따라가고, 각 URL 타입(video·user·collection·gallery·music·live)이 어떤 ID로 매핑되는지 표로 정리해보라.

LV.2 · 실행

단일 공개 영상 하나 받아보기 쉬움~보통

config.example.yml을 복사해 쿠키를 넣고, 본인 계정에 올린 테스트 영상 링크 하나로 douyin-dl --url ...을 실행. Downloaded/작성자/날짜_제목/ 폴더 구조와 함께 저장되는 *.json 메타데이터·download_manifest.jsonl을 열어 내용을 확인하라.

LV.3 · 실험

속도제한을 바꿔 서버 반응 관찰 보통

설정에서 rate_limit과 동시성(concurrency)을 낮췄다/높였다 하며 로그의 재시도 빈도를 비교. retry_handler의 백오프가 실제로 1s→2s→5s로 늘어나는지 로그로 검증하라. (과도한 요청은 계정 차단 위험 — 소규모로만.)

LV.4 · 확장

새 알림 채널(Notifier) 추가 보통~어려움

utils/notifier.py는 Bark·Telegram·Webhook을 지원한다. 이를 참고해 Slack 또는 Discord 웹훅 알림을 추가하고, test_notifier_redactor_property.py 스타일로 "토큰이 로그에 노출되지 않는가"를 검증하는 테스트를 작성하라.

LV.5 · 심화

전략 패턴으로 새 유저 모드 붙이기 어려움

core/user_modes/base_strategy.py를 상속해 새 수집 전략(예: 특정 해시태그·검색 결과 기반)을 구현하고 user_mode_registry.py에 등록. 기존 다운로더 본체를 건드리지 않고 기능이 붙는 "개방-폐쇄 원칙(OCP)"을 몸으로 체감하라.

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

이 레포를 발판 삼아 어디로 뻗어갈까 — 4주 코스.

주차주제학습 내용 · 연결점
1주차파이썬 비동기 기초coroutine · event loop · async/await · asyncio.gather · Semaphore/Lock. → 이 레포의 core·control 재독
2주차HTTP·웹 스크래핑 원리요청/응답 헤더·쿠키·User-Agent · 개발자도구 Network 탭으로 비공개 API 관찰 · robots.txt·이용약관의 의미
3주차안티봇 & 리버스 엔지니어링요청 서명·브라우저 지문·CAPTCHA · Playwright로 헤드리스 브라우저 제어 · 왜 서명 알고리즘을 포팅하나
4주차견고성 & 아키텍처지수 백오프·서킷브레이커·idempotency · 팩토리/전략/DI 패턴 · pytest + hypothesis 속성기반 테스트 작성
확장 프로젝트 제안

배운 걸 종합해 "내가 좋아하는 합법적 공개 API(예: GitHub·Reddit·공공데이터)용 견고한 수집기"를 만들어보라. 이 레포의 control·storage 계층을 뼈대로 재사용하면, 대상만 바꿔 곧바로 프로덕션급 클라이언트가 나온다.

10핵심 키워드 사전

이 문서에 나온 용어 총정리.

용어
스크래핑웹사이트/앱의 데이터를 프로그램으로 자동 수집하는 것
비공개 API앱 내부에서만 쓰라고 만든, 문서화되지 않은 서버 엔드포인트
X-Bogus / A-Bogus더우인이 요청 진위를 검증하려 요구하는 서명 파라미터. 이 레포가 파이썬으로 재현
ms_token세션마다 발급되는 보안 토큰. 만료되면 요청 거절 → 자동 갱신 필요
워터마크 제거서버가 붙이기 전의 원본(무워터마크) 소스를 선택해 받는 것
Rate limiting초당 요청 수 제한. 서버 과부하·차단 방지 + 봇 탐지 회피용 지터 동반
지수 백오프재시도 간격을 1→2→5초처럼 점점 늘리는 전략
지터(jitter)대기 시간에 섞는 무작위 값. 요청이 기계처럼 규칙적이지 않게
팩토리 패턴입력에 따라 알맞은 객체를 대신 만들어주는 설계
전략 패턴교체 가능한 알고리즘(모드)을 클래스로 캡슐화해 갈아끼우는 설계
DI(의존성 주입)필요한 객체를 밖에서 만들어 넣어주는 것 — 테스트·재사용에 유리
속성 기반 테스트수천 개 무작위 입력으로 "항상 성립해야 할 규칙"을 검증(hypothesis)
브라우저 폴백API가 막히면 실제 브라우저(Playwright)를 띄워 우회/CAPTCHA 대응
증분 다운로드이미 받은 것은 건너뛰고 새 것만 받기(SQLite 이력 기반)
AGENTS.mdAI 코딩 에이전트가 해당 폴더 작업 시 지켜야 할 규칙 문서

11참고 링크

더 파고들 곳.