CONTEXT.md)로 정리해 둔, 보기 드문 "설계 교과서"가 딸려 있다. 이 문서는 소스를 직접 클론해 "이 저장소에서 무엇을 배울 수 있는가"를 파고든다.
(저장소: XiaoYouChR/Ghost-Downloader-3 · Python 3.11+ / PySide6(Qt) · GPL v3.0 · 별 약 6.5k · 포크 약 359 · 최신 릴리스 v4.1.1(2026-07-15) · 최신 커밋 2026-07-16 · 저자 XiaoYouChR · TrendShift Daily #12)
Ghost Downloader 3은 "파일을 여러 조각으로 나눠 동시에 받아 속도를 끌어올리고, HTTP뿐 아니라 토렌트·FTP·M3U8·유튜브·비리비리까지 한 창에서 처리하는 크로스플랫폼 다운로드 관리자"다. 저자 XiaoYouChR가 "내 첫 Python 프로젝트"라고 README에 적어둔, 취미로 시작해 별 6.5천 개까지 자란 프로그램이다.
보통 브라우저 다운로드는 서버와 연결 하나로 처음부터 끝까지 받는다. GD3는 파일을 8조각으로 나눠 "바이트 3천만~4천만 번은 네가, 4천만~5천만 번은 네가" 하고 8개의 연결에 동시에 시킨다. 각 일꾼은 자기 담당 구간을 파일의 정확한 그 위치에 직접 써넣기 때문에, 나중에 조각들을 이어 붙이는 "병합" 단계가 아예 없다.
이름의 숫자 "3"은 3세대라는 뜻이다. 초기 버전들은 순수 다운로드 기능에 가까웠고, 지금의 3세대(내부 버전 4.x)는 플러그인 구조·브라우저 확장·안드로이드 앱·aria2 호환 API까지 갖춘 하나의 플랫폼으로 커졌다. 저장소를 클론해 보면 크게 네 덩어리로 나뉜다.
| 구성물 | 정체 | 규모 |
|---|---|---|
| app/ | 플랫폼 공용 "엔진" — 서비스(액터) 계층 + 데이터 모델 + Qt 화면(View) | 핵심 로직 |
| features/ | 프로토콜별 플러그인 12종 (http·bittorrent·ftp·m3u8·ed2k·bili·yt_dlp·github·huggingface·ffmpeg·disk 등) | 기능 확장 |
| browser_extension/ | 브라우저 확장 (TypeScript/React) — 웹페이지 미디어를 낚아채 앱으로 보냄 | 별도 서브프로젝트 |
| android/ | 안드로이드 패키징 (같은 Python 엔진을 모바일 껍데기에 얹음) | 모바일 포트 |
Python·Qt 소스만 약 22만 줄(라이브러리 포함) 규모이고, 라이선스는 GPL v3.0이다. 무료·완전 오픈소스이며 상용 IDM을 대체하려는 성격이 뚜렷하다.
다운로더는 흔한 소프트웨어다. 그런데도 GD3가 주목받는 건 흔한 기능을 흔하지 않게 구현했기 때문이다. 세 가지가 핵심이다.
대부분의 멀티스레드 다운로더는 조각을 file.part1, file.part2처럼 따로 받아뒀다가 마지막에 하나로 이어 붙인다(병합). 큰 파일이면 이 병합만으로도 디스크를 통째로 한 번 더 읽고 쓴다. GD3는 받는 즉시 각 조각을 최종 파일의 정확한 오프셋(offset)에 직접 써넣어 병합 단계를 통째로 없앴다. 리눅스/맥의 pwrite(위치 지정 쓰기)를 그대로 쓰기 때문에 가능한 설계다.
퍼즐을 맞출 때, 조각을 다 모아뒀다가 마지막에 한꺼번에 판에 올리는 방식(병합)과, 조각이 손에 들어오는 즉시 제자리에 바로 끼우는 방식(무병합)의 차이다. 후자는 "다 모으는 시간"과 "따로 쌓아둘 공간"이 필요 없다.
"AI"라는 단어에 거창한 신경망을 떠올리기 쉽지만, 여기서는 속도를 초당 재면서 "조각을 더 쪼개면 실제로 빨라지는지"를 통계적으로 판단하는 자동 튜닝 루프를 말한다. 서버가 연결당 속도를 제한하는 경우(대역폭 throttling)에는 조각을 늘릴수록 총속도가 오른다. GD3는 5초간 속도를 지켜본 뒤 조각을 4개 추가로 쪼개고, "조각을 N% 늘렸는데 속도가 그만큼(0.8배 이상) 안 올랐다"면 더는 이득이 없다고 보고 가속을 멈춘다. 뒤(4장)에서 실제 코드를 뜯어본다.
요즘 서버는 접속자가 "진짜 크롬 브라우저"인지 "스크립트/봇"인지를 TLS 지문(fingerprint)으로 구분해 차단한다. GD3는 wreq 라이브러리로 실제 크롬·파이어폭스의 TLS 악수(handshake) 지문을 흉내 내, 다운로더가 보내는 요청을 브라우저 요청처럼 보이게 만든다. 이건 일반 다운로더에는 거의 없는 기능이다.
여기에 브라우저 확장으로 스트리밍 미디어를 낚아채고, aria2 호환 RPC로 외부 도구가 작업을 밀어 넣게 하고, 같은 엔진으로 안드로이드까지 지원하는 넓은 커버리지가 더해진다. "기능이 많다"가 아니라 "각 기능을 제대로 만들었다"가 트렌딩의 실질적 이유다.
다운로더는 수십 개가 있지만, 무병합 쓰기·자동 가속 휴리스틱·TLS 위장·플러그인 아키텍처를 한 곳에서 깔끔하게 볼 수 있는 오픈소스는 드물다. 신입 개발자에게 "잘 설계된 실전 앱"의 표본으로 특히 값지다.
GD3는 "GUI 앱"이지만 속을 보면 비동기 네트워크 엔진 + Qt 화면 + 12개의 프로토콜 플러그인이 겹쳐진 구조다. 계층별로 어떤 도구를 쓰는지 지도를 그려보자.
| 요소 | 선택 | 왜 이걸 썼나 |
|---|---|---|
| 언어 | Python 3.11+ | 접근성이 높아 향후 플러그인 생태계를 열기 쉬움(저자 명시) |
| 패키지 관리 | uv + pyproject.toml | Rust 기반 초고속 의존성 해결기. uv.lock으로 재현성 확보 |
| 비동기 루프 | asyncio + uvloop(리눅스/맥) / winloop(윈도우) | C로 짠 초고속 이벤트 루프로 수백 개 동시 연결 감당 |
| 배포 컴파일 | Nuitka | Python을 C로 변환·컴파일해 단일 실행파일로 배포(속도·보호) |
| 요소 | 선택 | 역할 |
|---|---|---|
| GUI 프레임워크 | PySide6 (Qt 6.6+) | Qt의 공식 파이썬 바인딩. 크로스플랫폼 네이티브 위젯 |
| 디자인 위젯 | PyQt-Fluent-Widgets | Windows 11 Fluent Design 스타일 컴포넌트 라이브러리 |
| 이벤트 브리지 | Signal / Slot + Coroutine Runner | asyncio(백그라운드 스레드)와 Qt(메인 스레드)를 안전하게 연결 |
| 프로토콜 | 사용 라이브러리 | 메모 |
|---|---|---|
| HTTP/HTTPS | wreq (TLS 지문 위장) | 브라우저 위장 + 바이트 레인지 병렬 수신의 핵심 |
| Magnet / BT | libtorrent (C++ 바인딩) | 비트토렌트 세션·트래커 처리 |
| FTP/FTPS | aioftp (+SOCKS) | 비동기 FTP 클라이언트 |
| M3U8 / MPEG-DASH | m3u8, mpegdash, N_m3u8DL-RE | HLS/DASH 스트리밍·라이브 녹화·실시간 복호화 |
| eD2k | goed2k (내장 서브모듈) | eDonkey 네트워크 지원 |
| YouTube / Bilibili | yt-dlp + 자체 파서 | 재생목록·4K/HDR·자막·로그인 지원 |
| 미디어 처리 | FFmpeg, QuickJS-NG | 변환·병합, JS 실행(사이트 스크립트 파싱) |
| 요소 | 선택 | 역할 |
|---|---|---|
| 브라우저 확장 | TypeScript + React (MV3 서비스워커) | 웹페이지 미디어 스니핑, WebSocket으로 앱과 통신 |
| 외부 API | aria2 호환 JSON-RPC 서버 (Qt TCP) | 서드파티 도구가 작업을 직접 밀어 넣게 함 |
| 로깅 | loguru | 간결한 파이썬 로깅 |
| 알림 | desktop-notifier | 크로스플랫폼 데스크톱 알림 |
| 번역 | Crowdin | 다국어 커뮤니티 번역(1.4만 단어+) |
GD3는 "엔진 룸(app/services) + 계기판(PySide6 UI) + 교체 가능한 어댑터 소켓(features/*_pack)"으로 된 자동차다. 엔진(비동기 다운로드 루프)은 한 대뿐인데, 여기에 HTTP용·토렌트용·유튜브용 어댑터를 소켓에 꽂으면 그 프로토콜을 받을 수 있게 된다. 계기판은 데스크톱/모바일 두 종류로 갈아 끼운다.
GD3의 아키텍처는 CONTEXT.md에 아주 정밀하게 문서화돼 있다. 핵심은 두 가지 축이다 — (A) "액터(actor)"로 나눈 서비스 계층과 (B) HTTP 조각 병렬 수신 엔진. 순서대로 뜯어본다.
이 그림에서 반드시 챙길 두 규칙:
① 단일 공개 창구(single public door). 화면이든 브라우저든 작업을 만들거나 멈추려면 무조건 taskService를 거친다. 작업 목록(TaskStore)과 실행 큐(TaskQueue)는 taskService 안쪽에 숨겨져 있어 아무도 직접 못 만진다. "누가 상태를 바꿀 수 있는가"를 딱 한 곳으로 좁힌 설계다.
② 의존성은 한 방향(leaf → top)으로만 흐른다. coroutineRunner와 speedMeter는 "Task"가 뭔지조차 모른다. 그저 "비동기 작업을 돌려라", "바이트를 세라"는 일반 기능만 한다. 반대로 View는 모든 걸 알고 시그널로 엮는다. 이렇게 하면 아래 계층을 독립적으로 테스트할 수 있다.
task.status는 큐 전이면 taskService가, 최종 결과(완료/실패)면 Step이 쓰고 View는 읽기만 한다. 상태를 누가 언제 바꾸는지 헷갈리는 버그(경쟁 조건)를 원천 차단한다.URL을 붙여넣으면 featureService.parse(options)가 등록된 파서들을 우선순위 낮은 것부터 훑으며 "이 URL 내가 처리할게"라고 처음 손드는 파서에게 맡긴다. 구체적인 것일수록 번호가 작아 먼저 검사되고, 무엇에도 안 걸리면 마지막의 HTTP 파서(100)가 받는다.
재미있는 지점: GitHubParser는 스스로 다운로드하지 않는다. URL을 프록시 주소로 바꾼 뒤 featureService.parse()를 다시 호출한다. 프록시 URL은 더 이상 github 호스트가 아니므로 HTTP 파서가 받는다 — "위임으로 기능을 조합"하는 깔끔한 패턴이다. 무한 재귀도 자연스럽게 피한다.
이제 심장부다. HTTP 파일 하나를 어떻게 8조각으로 나눠 병합 없이 받는지, 실제 features/http_pack/task.py를 보자. 먼저 파일을 조각(Subworker)으로 나누는 부분:
# 파일 크기를 subworkerCount(기본 8)만큼 균등 분할
count = min(self.subworkerCount, self.fileSize)
subworkers = []
for i in range(count - 1):
start = i * chunkSize
end = start + chunkSize - 1
subworkers.append(HttpSubworker(index=i, start=start, end=end))
# 마지막 조각은 파일 끝까지 담당
subworkers.append(HttpSubworker(index=count-1, start=start, end=self.fileSize-1))
각 HttpSubworker는 start(담당 시작 바이트), end(끝 바이트), receivedBytes(지금까지 받은 양)만 든 작은 값이다. position = start + receivedBytes가 "다음에 써야 할 위치"다. 그리고 각 조각을 실제로 받는 _runSubworker는 HTTP Range 요청으로 자기 구간만 달라고 하고, 받은 조각을 pwrite로 파일의 정확한 위치에 바로 쓴다:
# 서버에 "이 바이트 구간만 줘"라고 요청 (Range 헤더)
headers = {**self._effectiveHeaders,
"range": f"bytes={subworker.position}-{subworker.end}"}
async for chunk in response.stream():
# 받은 조각을 "그 위치에" 바로 써넣음 → 병합 불필요
pwrite(fd, chunk, subworker.position) # ← 핵심 한 줄
subworker.receivedBytes += len(chunk)
speedMeter.addSpeed(len(chunk)) # 속도계에 바이트 보고
await speedMeter.waitForSpeedLimit() # 전역 속도제한 준수
Range: bytes=100-200). 서버가 이걸 지원해야 조각 병렬 수신이 가능하다. pwrite는 "파일 포인터를 옮기지 않고 지정한 오프셋에 바로 쓰는" 시스템 콜. 여러 조각이 동시에 서로 다른 위치에 써도 안전하다.2장에서 예고한 자동 가속 루프의 실제 코드다. 1초마다 도는 감시자(_supervise)가 _autoSpeedUp()을 호출한다. 로직을 우리말로 풀면:
# 1) 최근 5초 속도를 모아 평균과 변동폭 계산
if maxDeviation > 0.15: # 속도가 15% 넘게 출렁이면 판단 보류 (불안정)
return
# 2) 첫 판단: 기준 속도/조각수 기록하고 조각 4개 추가 분할
if self._accelCheckTime == 0:
self._accelInitialWorkers = len(self.subworkers)
self._accelInitialSpeed = avgSpeed
for _ in range(4):
self._reassignSubworker() # 가장 느린 조각을 반으로 쪼갬
else:
# 3) 5초 뒤 재평가: 조각을 N% 늘렸는데 속도는 얼마나 올랐나?
workerRatio = (지금조각수 - 초기조각수) / 초기조각수
speedRatio = (지금속도 - 초기속도) / 초기속도
if speedRatio < 0.8 * workerRatio:
self.isAccelerated = True # 효과 없음 → 가속 종료
else:
self._accelCheckTime = 0 # 효과 있음 → 다음 라운드 계속
여기서 _reassignSubworker()는 "남은 양이 가장 많은(=가장 느린) 조각"을 찾아 그 구간을 반으로 쪼개고, 새 조각을 TaskGroup에 즉시 던져 넣는다. 즉 느린 조각을 실시간으로 더 잘게 나눠 병렬성을 높이는 방식이다. "AI"라는 이름과 달리 신경망은 없지만, 피드백을 측정해 스스로 파라미터를 조절하는 제어 루프라는 점에서 자동화된 튜닝이 맞다.
무작정 조각을 늘리면 서버 연결 수 제한이나 CPU 오버헤드로 오히려 느려질 수 있다. GD3는 "늘린 만큼 빨라지지 않으면 즉시 멈춘다"는 간단한 규칙으로 과최적화를 스스로 방지한다. 복잡한 AI 없이도 실용적 자동 튜닝이 가능함을 보여주는 좋은 예다.
다운로드를 껐다 켜도 이어받으려면 "어디까지 받았는지"를 디스크에 남겨야 한다. GD3는 감시자가 1초마다 각 조각의 (start, position, end) 삼중값을 이진 형식(struct.pack, 리틀엔디안 64비트)으로 파일명.ghd에 덮어쓴다. 다시 켜면 이 .ghd를 읽어 각 조각을 멈춘 지점부터 되살린다. 텍스트 JSON이 아니라 고정폭 이진이라 쓰기가 빠르고 파싱이 단순하다.
여러 사람이 각자 다른 층에서 계단을 오르다 정전이 됐을 때, "누가 몇 층 몇 계단에 서 있었는지"를 종이 한 장(.ghd)에 초마다 갱신해 두는 것과 같다. 전기가 들어오면 각자 적힌 자리로 돌아가 이어서 오른다.
구조에서 읽어야 할 것: 플랫폼 공용 로직(app)과 프로토콜별 확장(features)이 확실히 분리돼 있고, 팩마다 manifest.toml이 있어 "이 팩이 무엇을 의존하고 무엇을 제공하는가"를 선언한다. featureService.load()가 이 매니페스트들을 읽어 의존성 순서대로(위상 정렬) 임포트한다. 새 프로토콜을 추가하려면 features/ 아래 폴더 하나만 만들면 되는 구조다.
manifest.toml). 위상 정렬은 "A가 B를 의존하면 B를 먼저"처럼 의존 관계를 지켜 순서를 정하는 알고리즘. 플러그인들을 올바른 순서로 로드할 때 쓴다.GUI 앱의 고질적 난제 — 무거운 네트워크 작업을 하면 화면이 멈춘다. GD3는 coroutineRunner가 별도 QThread에서 asyncio 루프를 돌리고, 결과만 Qt 메인 스레드로 콜백을 넘겨 화면 갱신을 안전하게 한다. "이벤트 루프 두 개(asyncio + Qt)를 어떻게 공존시키나"의 실전 정답지다.
PySide6 + asyncio로 "URL을 넣으면 백그라운드에서 파일 크기를 HEAD 요청으로 알아내 라벨에 표시하는" 최소 앱을 만들어 보라. coroutine_runner.py가 쓰는 패턴(스레드 분리 + 콜백 전달)을 따라 하면 화면이 안 멈추는 걸 체감할 수 있다.
4장의 무병합 엔진은 그 자체로 훌륭한 학습 주제다. Range 헤더로 구간을 요청하고 os.pwrite로 오프셋에 쓰는 것만 알면, 100줄 안팎의 미니 병렬 다운로더를 스스로 만들 수 있다. 서버가 Range를 지원하지 않을 때(단일 스트림)의 폴백 처리까지 보면 실전 감각이 완성된다.
CONTEXT.md는 그 자체로 대규모 앱을 어떻게 층으로 나누고, 상태 소유권을 어떻게 못 박는지에 대한 교과서다. "매니저·컨트롤러·프로바이더 같은 구조적 이름을 쓰지 말고, 도메인 개념으로 이름 지어라(taskService, speedMeter)" 같은 명명 철학까지 담겨 있다. 협업 코드의 이름 짓기로 고민해 본 개발자에게 특히 값지다.
매니페스트 선언 → 위상 정렬 → 우선순위 기반 라우팅으로 이어지는 featureService는 "확장 가능한 앱"의 표본이다. 파서가 스스로 하지 않고 parse()를 재귀 호출해 위임하는 GitHubParser·MergeParser의 조합 패턴도 눈여겨볼 만하다.
확장은 WebSocket 프로토콜 v3(hello → hello_ack → subscribe → snapshot)로 앱과 대화하고, 연결이 끊기면 작업을 큐에 쌓아뒀다 재연결 시 흘려보낸다. "브라우저 ↔ 네이티브 앱"을 잇는 실전 아키텍처를 통째로 읽을 수 있다.
| 배울 기술 | 관련 파일 | 난이도 |
|---|---|---|
| asyncio ↔ Qt 브리지 | services/coroutine_runner.py | 중 |
| 병렬 Range 다운로드 | features/http_pack/task.py | 중~상 |
| 액터·소유권 설계 | CONTEXT.md, services/task_service.py | 중 |
| 플러그인 로딩 | services/feature_service.py, models/pack.py | 중 |
| TLS 지문 위장 | client.py (wreq) | 상 |
| MV3 확장 ↔ 앱 | browser_extension/, services/browser_service.py | 상 |
| 플랫폼 | 최소 버전 | 아키텍처 |
|---|---|---|
| Windows | 10 이상 | x86_64 / arm64 |
| macOS | 13.0 이상 | x86_64 / arm64(애플 실리콘) |
| Linux | glibc 2.35 이상 | x86_64 / arm64 |
| Android | 10.0 이상 | arm64-v8a |
2013년 이전의 아주 오래된 CPU라면 실행이 안 될 수 있다. 또 Arch Linux는 커뮤니티 AUR 패키지(ghost-downloader-bin·ghost-downloader-git)로도 설치 가능하다.
# 1) uv 설치 후 저장소 클론
git clone https://github.com/XiaoYouChR/Ghost-Downloader-3.git
cd Ghost-Downloader-3
# 2) uv가 pyproject.toml/uv.lock 보고 가상환경+의존성 자동 구성
uv sync
# 3) 데스크톱 진입점 실행
uv run python Ghost-Downloader-3.py
플랫폼 조건부 의존성이 자동 처리된다 — 윈도우면 winloop·libtorrent-windows-dll, 맥/리눅스면 uvloop, 맥이면 pyobjc가 각각 설치된다. 배포판을 직접 만들려면 nuitka로 컴파일하며, FFmpeg·N_m3u8DL-RE 같은 외부 바이너리는 앱이 필요할 때 Binary Runtime으로 내려받아 설치한다.
Python httpx + os.pwrite만으로 "파일을 4조각으로 나눠 Range 요청으로 동시에 받아 병합 없이 저장하는" 스크립트를 작성하라. GD3의 _runSubworker를 축약판으로 재현하는 것이다. 서버가 Range를 지원하는지 Accept-Ranges 헤더로 먼저 확인하는 분기를 넣어 보라.
위 스크립트에 "진행 파일(.progress)" 저장을 추가하라. 각 조각의 (start, position, end)를 struct.pack으로 1초마다 기록하고, 중단 후 재실행 시 이 파일을 읽어 이어받게 하라. GD3의 _supervise가 하는 일을 그대로 축소 구현하는 과제다.
PySide6로 진행률 바를 만들고, 백그라운드 스레드의 asyncio 다운로드가 시그널로 진행률을 화면에 밀어 넣게 하라. 화면이 절대 멈추지 않아야 한다. GD3의 coroutine_runner.py 패턴을 참고하라.
4장의 _autoSpeedUp 로직(5초 관찰 → 조각 추가 → workerRatio 대비 speedRatio 평가)을 자신의 다운로더에 이식하고, 대역폭 제한이 걸린 테스트 서버에서 실제로 속도가 오르는지 측정하라. "언제 멈춰야 하는가"의 임계값(0.8)을 바꿔가며 실험해 보라.
GD3를 클론해 features/에 새 팩 폴더를 만들고, manifest.toml + TaskParser를 정의해 특정 사이트 URL을 처리하는 파서를 등록하라. featureService의 우선순위 라우팅에 내 파서가 올바르게 끼어드는지 확인하는 것이 목표다.
| 주차 | 주제 | 핵심 질문 · 실습 |
|---|---|---|
| 1주차 | HTTP 심화 | Range 요청·조건부 요청(If-Range)·청크 전송·Content-Disposition 파싱. 브라우저 개발자도구 Network 탭으로 실제 헤더를 관찰 |
| 2주차 | 파이썬 비동기 | asyncio 이벤트 루프·TaskGroup·CancelledError 취소 전파. uvloop이 왜 빠른지. GD3의 coroutine_runner 읽기 |
| 3주차 | Qt/PySide6 GUI | 시그널·슬롯, 스레드 간 통신, 가상 스크롤(TaskPage). 화면 안 멈추게 만드는 원칙 |
| 4주차 | 아키텍처·확장성 | 액터/단일 작성자·플러그인 로딩·의존성 방향. CONTEXT.md 전체를 정독하고 내 프로젝트에 이름 규칙 적용 |
여력이 되면 보너스로 TLS 지문(JA3/JA4)과 비트토렌트 프로토콜(libtorrent 세션·트래커·조각 교환)을 각각 하루씩 파보면, GD3가 왜 그렇게 많은 라이브러리를 조합했는지 전모가 보인다.
| 용어 | 뜻 |
|---|---|
| 멀티스레드 다운로드 | 파일을 여러 조각으로 나눠 동시 연결로 받아 속도를 높이는 방식 |
| 무병합(no-merge) | 조각을 따로 받았다 합치지 않고, 받는 즉시 최종 파일의 제 위치에 직접 쓰는 설계 |
| Subworker | HTTP/FTP 작업에서 한 바이트 구간을 담당하는 분할 전송 단위 |
| HTTP Range 요청 | 파일의 특정 바이트 구간만 달라고 서버에 요청하는 표준 기능(Range: bytes=a-b) |
| pwrite | 파일 포인터를 옮기지 않고 지정 오프셋에 바로 쓰는 시스템 콜(동시 쓰기 안전) |
| AI 스마트 가속 | 속도를 측정해 조각 수를 자동 조절하는 피드백 튜닝 루프(신경망 아님) |
| TLS 지문 위장 | 다운로더 요청을 실제 브라우저의 TLS 악수처럼 보이게 해 봇 차단을 피하는 기법 |
| 액터(actor) | 특정 상태를 독점 소유하고 그 상태의 유일한 작성자가 되는 서비스 객체 |
| 단일 공개 창구 | 작업 생성·변경을 taskService 한 곳으로만 통하게 좁힌 규율 |
| FeaturePack | 프로토콜별 기능을 담은 플러그인 번들(파서·카드·런타임·페이지 기여) |
| 파서 우선순위 | URL을 어떤 파서가 처리할지 낮은 번호부터 검사해 첫 매치가 이기는 라우팅 |
| .ghd 진행 파일 | 각 조각의 (start,position,end)를 이진으로 저장해 재개를 가능케 하는 파일 |
| aria2 RPC | 인기 다운로더 aria2와 호환되는 JSON-RPC 인터페이스(외부 도구 연동용) |
| MV3 서비스워커 | 크롬 확장 매니페스트 v3의 백그라운드 실행 단위. 미디어 스니핑·앱 통신 담당 |
| 자료 | 링크 · 설명 |
|---|---|
| GitHub 저장소 | github.com/XiaoYouChR/Ghost-Downloader-3 — 소스·이슈·릴리스 |
| 공식 문서 | gd.xychr.com/en/docs/ — 사용 설명서(한/영/중) |
| CONTEXT.md | 저장소 루트 — 아키텍처·용어·명명 규칙 정리(필독) |
| wreq | github.com/0x676e67/wreq-python — TLS 지문 위장 HTTP 클라이언트 |
| libtorrent | github.com/arvidn/libtorrent — 비트토렌트 C++ 구현 |
| yt-dlp | github.com/yt-dlp/yt-dlp — 유튜브 등 미디어 다운로드 엔진 |
| PyQt-Fluent-Widgets | github.com/zhiyiYo/PyQt-Fluent-Widgets — Fluent 스타일 위젯 |
| uvloop | github.com/MagicStack/uvloop — 초고속 asyncio 이벤트 루프 |