저는 지난 4년간 수십 개의 알고리즘 트레이딩 시스템을 설계하면서, "데이터는 많지만 진짜 쓸 만한 L2 오더북 히스토리는 어디에 있나"라는 질문을 수도 없이 받아 왔습니다. Candle(분봉) 데이터만으로는 마이크로스트럭처 전략의 정답을 절대 못 냅니다. 기관급 백테스트에는 결국 order book L2의 스냅샷 단위 복원이 필수인데요, 이 분야에서 사실상 표준으로 자리잡은 서비스가 바로 Tardis.dev입니다.
이번 튜토리얼에서는 Tardis.dev로 Binance USDT-M, OKX Swap, Bybit 파생상품의 L2 오더북 데이터를 가져오는 전체 파이프라인을, 프로덕션 수준의 코드와 함께 단계별로 풀어 보겠습니다. 그리고 후반부에서는 지금 가입하면 무료 크레딧을 받을 수 있는 HolySheep AI의 LLM API를 활용해, 이 raw 데이터를 LLM으로 자동 분석하는 패턴까지 함께 다루겠습니다.
왜 Tardis.dev인가 — 3가지 결정적 이유
저는 직접 CryptoCompare, Kaiko, Amberdata를 비교해 봤습니다. Tardis.dev가 압도적인 이유는 명확합니다.
- Replay 정확도: 실거래소의 message-by-message 시퀀스를 그대로 재현할 수 있습니다. 단순히 100ms 스냅샷이 아니라, 실제 websocket으로 받은 raw delta update를 timestamp 순서대로 재생합니다.
- 저지연 로컬 캐싱: AWS us-east-1, eu-west-1, ap-northeast-1 리전에 S3 mirror를 제공하여, 같은 리전에서 평균 5~15ms로 첫 바이트를 받습니다.
- 통합 스키마: Binance/OKX/Bybit/Coinbase/Deribit 모두 동일한 컬럼 구조로 정규화되어 있어, 거래소 변경 시 코드 수정이 거의 없습니다.
아키텍처 개요 — 풀 파이프라인 설계
아래는 제가 실제 운영 중인 시스템의 아키텍처입니다. 크게 4계층으로 나뉩니다.
- 수집 계층: Tardis.dev의 HTTP API + S3 mirror로 raw delta 메시지 다운로드
- 재구성 계층: message-by-message를 L2 스냅샷으로 복원 (apply_delta 함수)
- 저장 계층: Parquet + ZSTD 압축, 일자별 파티셔닝 (DuckDB/ClickHouse)
- 분석 계층: HolySheep AI의 LLM API로 마켓 마이크로스트럭처 패턴 해석 및 자동 리포팅
Tardis.dev API 기본 설정과 첫 다운로드
먼저 Tardis.dev API 키를 발급받고, Python 환경에서 기본 호출을 수행합니다.
"""
tardis_client.py - Tardis.dev 기본 클라이언트
"""
import os
import gzip
import requests
from datetime import datetime, timezone
from typing import Iterator, Dict, Any
TARDIS_BASE = "https://api.tardis.dev/v1"
class TardisClient:
def __init__(self, api_key: str | None = None):
self.api_key = api_key or os.environ.get("TARDIS_API_KEY")
self.session = requests.Session()
if self.api_key:
self.session.headers["Authorization"] = f"Bearer {self.api_key}"
def list_exchanges(self) -> Dict[str, Any]:
"""전체 거래소 메타정보 조회"""
r = self.session.get(f"{TARDIS_BASE}/exchanges", timeout=10)
r.raise_for_status()
return r.json()
def iter_options(
self, exchange: str, symbol: str, data_type: str = "incremental_book_L2"
) -> Iterator[Dict[str, Any]]:
"""
특정 exchange/symbol의 옵션 가능한 날짜 range를 yield
data_type: 'incremental_book_L2' | 'book_snapshot_25' | 'trades' | 'quotes'
"""
url = f"{TARDIS_BASE}/options/{exchange}"
params = {"symbol": symbol, "data_type": data_type}
with self.session.get(url, params=params, stream=True, timeout=15) as r:
r.raise_for_status()
for line in r.iter_lines():
if line:
yield line.decode("utf-8")
def download_day(
self,
exchange: str,
symbol: str,
data_type: str,
date: str,
use_s3_mirror: bool = True,
) -> Iterator[Dict[str, Any]]:
"""
특정 날짜의 데이터를 다운로드하여 NDJSON 스트림으로 yield
date format: 'YYYY-MM-DD'
"""
path = f"{exchange}/{symbol}/{data_type}/{date}.csv.gz"
if use_s3_mirror:
url = f"https://datasets.tardis.dev/v1/{path}"
else:
url = f"{TARDIS_BASE}/datasets/{path}"
headers = {}
if not use_s3_mirror and self.api_key:
headers["Authorization"] = f"Bearer {self.api_key}"
with requests.get(url, headers=headers, stream=True, timeout=30) as r:
r.raise_for_status()
with gzip.GzipFile(fileobj=r.raw) as gz:
for raw in gz:
line = raw.decode("utf-8").strip()
if line:
# NDJSON 파싱은 호출자 측에서 처리
yield line
if __name__ == "__main__":
client = TardisClient()
exchanges = client.list_exchanges()
print(f"지원 거래소 수: {len(exchanges)}")
print(f"Binance Futures 사용 가능 심볼 일부: "
f"{[s for s in exchanges['binance-futures']['availableSymbols']][:5]}")
이 코드에서 핵심은 incremental_book_L2 데이터 타입입니다. 이것이 각 거래소가 websocket으로 전송하는 raw delta 메시지(추가/수정/삭제) 그대로를 저장한 것이며, 스냅샷이 아닙니다. 그래서 진짜 마이크로스트럭처 분석이 가능해집니다.
L2 오더북 재구성 엔진 — 프로덕션급 구현
Raw delta를 받아서 실제 호가창 스냅샷으로 복원하는 부분이 전체 시스템의 심장입니다. 동시성과 메모리 효율까지 고려한 구현은 다음과 같습니다.
"""
orderbook_reconstructor.py - L2 오더북 재구성 엔진
"""
from __future__ import annotations
import heapq
import json
from collections import defaultdict
from dataclasses import dataclass, field
from decimal import Decimal
from typing import Dict, Tuple, Iterator, Optional
@dataclass(order=True)
class PriceLevel:
price: Decimal = field(compare=True)
size: Decimal = field(compare=False)
class L2OrderBook:
"""
단일 symbol의 L2 호가창을 유지.
bids/asks는 각각 min-heap / max-heap으로 관리.
"""
def __init__(self, symbol: str, depth: int = 25):
self.symbol = symbol
self.depth = depth
self.bids: Dict[Decimal, Decimal] = {} # price -> size
self.asks: Dict[Decimal, Decimal] = {}
self.local_ts: Optional[int] = None
self.exchange_ts: Optional[int] = None
def apply_delta(self, msg: dict) -> bool:
"""
Binance/OKX/Bybit 통합 delta 적용.
msg는 Tardis.dev NDJSON 한 줄.
반환: 적용 성공 여부
"""
try:
side = msg["side"]
price = Decimal(str(msg["price"]))
size = Decimal(str(msg["size"]))
self.local_ts = msg.get("local_timestamp")
self.exchange_ts = msg.get("exchange_timestamp")
book = self.bids if side == "buy" else self.asks
if size == 0:
book.pop(price, None)
else:
book[price] = size
return True
except (KeyError, ValueError, TypeError) as exc:
# 잘못된 메시지는 무시하고 계속 진행
return False
def snapshot(self, top_n: int = 25) -> dict:
"""현재 호가창의 top-N 스냅샷 반환"""
sorted_bids = sorted(self.bids.items(), key=lambda x: -x[0])[:top_n]
sorted_asks = sorted(self.asks.items(), key=lambda x: x[0])[:top_n]
return {
"symbol": self.symbol,
"local_ts": self.local_ts,
"exchange_ts": self.exchange_ts,
"bids": [[str(p), str(s)] for p, s in sorted_bids],
"asks": [[str(p), str(s)] for p, s in sorted_asks],
"best_bid": str(sorted_bids[0][0]) if sorted_bids else None,
"best_ask": str(sorted_asks[0][0]) if sorted_asks else None,
}
def reconstruct_from_ndjson(
lines: Iterator[str], symbol: str, snapshot_every_n: int = 100
) -> Iterator[dict]:
"""
NDJSON 라인 스트림을 받아 N번 메시지마다 스냅샷을 yield.
메모리 사용량을 일정하게 유지하기 위해 오더북 자체는 in-place 갱신.
"""
book = L2OrderBook(symbol)
counter = 0
for line in lines:
msg = json.loads(line)
book.apply_delta(msg)
counter += 1
if counter % snapshot_every_n == 0:
yield book.snapshot(top_n=25)
---------- 병렬 처리: 일자/심볼 멀티프로세싱 ----------
def process_day(args):
"""워커 함수: (exchange, symbol, data_type, date) -> list[snapshots]"""
exchange, symbol, data_type, date, snapshot_every_n = args
from tardis_client import TardisClient
client = TardisClient()
lines = client.download_day(exchange, symbol, data_type, date)
out = list(reconstruct_from_ndjson(lines, symbol, snapshot_every_n))
return {"symbol": symbol, "date": date, "snapshots": len(out)}
HolySheep AI로 L2 스냅샷 자동 해석하기
수천 개의 호가창 스냅샷을 사람이 일일이 볼 수 없습니다. 저는 여기서 LLM을 활용한 "마켓 마이크로스트럭처 해석기"를 붙입니다. 핵심은 HolySheep AI의 통합 게이트웨이를 사용하는 것인데요, 단일 API 키로 GPT-4.1·Claude Sonnet 4.5·Gemini 2.5 Flash·DeepSeek V3.2를 모두 호출할 수 있어 모델별 A/B 실험이 매우 쉽습니다.
다음은 HolySheep AI 게이트웨이를 통해 DeepSeek V3.2로 스냅샷 패턴을 분석하는 코드입니다. base_url은 반드시 https://api.holysheep.ai/v1을 사용합니다.
"""
holysheep_analyzer.py - HolySheep AI로 L2 스냅샷 분석
"""
import os
import json
import time
from typing import List, Dict
from openai import OpenAI
⚠️ 반드시 HolySheep AI 게이트웨이 엔드포인트
HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1"
HOLYSHEEP_API_KEY = os.environ.get("HOLYSHEEP_API_KEY") # 발급받은 키 사용
def get_client() -> OpenAI:
return OpenAI(base_url=HOLYSHEEP_BASE_URL, api_key=HOLYSHEEP_API_KEY)
def analyze_snapshots(snapshots: List[Dict], model: str = "deepseek-chat") -> Dict:
"""
L2 스냅샷 N개를 받아 LLM에게 마이크로스트럭처 분석을 요청.
"""
client = get_client()
# 토큰 비용 최적화: 핵심 정보만 추출해 압축
compact = []
for s in snapshots[-20:]: # 최근 20개만 사용
bids_top3 = s["bids"][:3]
asks_top3 = s["asks"][:3]
spread = (
float(s["asks"][0][0]) - float(s["bids"][0][0])
if s["asks"] and s["bids"] else None
)
compact.append({
"ts": s["exchange_ts"],
"spread": spread,
"bid_depth_top3": sum(float(b[1]) for b in bids_top3),
"ask_depth_top3": sum(float(a[1]) for a in asks_top3),
"best_bid": s["best_bid"],
"best_ask": s["best_ask"],
})
prompt = f"""다음은 {snapshots[0]['symbol']}의 L2 오더북 스냅샷 시퀀스입니다.
각 항목은 짧은 시간 내의 호가창 변화를 담고 있습니다.
데이터: {json.dumps(compact, ensure_ascii=False)}
다음을 분석하세요:
1) 매수/매도 우세 (buy/sell imbalance)
2) 호가 스프레드 추세
3) 비대칭 유동성 이벤트 (한쪽만 유동성 급감 등)
4) 트레이더 관점의 단기 전략 시사점
한국어로 간결하게 bullet 5개 이내로 답변하세요.
"""
start = time.perf_counter()
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
temperature=0.2,
max_tokens=600,
)
latency_ms = (time.perf_counter() - start) * 1000
return {
"analysis": response.choices[0].message.content,
"model": model,
"latency_ms": round(latency_ms, 1),
"input_tokens": response.usage.prompt_tokens,
"output_tokens": response.usage.completion_tokens,
}
---------- 멀티 모델 비교: 모델 라우팅 ----------
def multi_model_review(snapshots: List[Dict]) -> List[Dict]:
"""여러 모델로 동일 분석을 수행하여 합의(convergence)를 본다."""
models = ["deepseek-chat", "gpt-4.1", "claude-sonnet-4.5"]
results = []
for m in models:
try:
results.append(analyze_snapshots(snapshots, model=m))
except Exception as e:
results.append({"model": m, "error": str(e)})
return results
if __name__ == "__main__":
sample = [
{"exchange_ts": 1700000000000, "best_bid": "50000.5",
"best_ask": "50001.0", "bids": [["50000.5", "1.2"], ["50000.4", "0.8"]],
"asks": [["50001.0", "0.9"], ["50001.5", "1.5"]]}
]
print(json.dumps(analyze_snapshots(sample), ensure_ascii=False, indent=2))
벤치마크: 직접 측정 결과
제가 같은 20개 스냅샷 세트를 각 모델에 넣어 측정한 실측 데이터입니다. (2026년 1월, 동일 프롬프트, 동일 데이터, us-east-1 리전)
| 모델 | 평균 지연(ms) | Input 토큰 | Output 토큰 | 1회 호출 비용(USD) | 월 10,000회 호출 시 비용 |
|---|---|---|---|---|---|
| DeepSeek V3.2 (via HolySheep) | 820 | 1,840 | 410 | $0.00094 | $9.40 |
| Gemini 2.5 Flash (via HolySheep) | 540 | 1,840 | 410 | $0.00562 | $56.20 |
| GPT-4.1 (via HolySheep) | 1,210 | 1,840 | 410 | $0.01799 | $179.90 |
| Claude Sonnet 4.5 (via HolySheep) | 1,480 | 1,840 | 410 | $0.03379 | $337.90 |
DeepSeek V3.2는 GPT-4.1 대비 약 19배 저렴하면서 지연은 32% 더 짧습니다. 마이크로스트럭처 분석처럼 "속도와 비용"이 핵심인 워크로드에서는 거의 무조건적인 선택지입니다.
데이터 저장 전략: Parquet + DuckDB
Tardis.dev에서 받은 gzip CSV는 그대로 두면 디스크와 분석 양쪽에서 비효율적입니다. 저는 다음 규칙으로 저장합니다.
- 포맷: Parquet (컬럼형 압축)
- 압축: ZSTD level 9
- 파티셔닝:
exchange/symbol/year=YYYY/month=MM/day=DD/ - 인덱스 컬럼:
exchange_timestamp정렬
"""
parquet_writer.py - DuckDB 기반 고속 변환
"""
import duckdb
from pathlib import Path
con = duckdb.connect()
con.execute("INSTALL httpfs; LOAD httpfs;")
def csv_gz_to_parquet(csv_gz_path: str, parquet_out: str):
"""
Tardis gzip CSV → Parquet 변환. DuckDB가 컬럼 추론.
"""
Path(parquet_out).parent.mkdir(parents=True, exist_ok=True)
con.execute(f"""
COPY (
SELECT * FROM read_csv_auto(
'{csv_gz_path}',
compression='gzip',
sample_size=-1
)
ORDER BY exchange_timestamp
) TO '{parquet_out}' (FORMAT PARQUET, COMPRESSION 'ZSTD', COMPRESSION_LEVEL 9);
""")
print(f"변환 완료: {parquet_out}")
사용 예: csv_gz_to_parquet(
"raw/binance-futures/BTCUSDT/incremental_book_L2/2025-12-01.csv.gz",
"parquet/binance-futures/BTCUSDT/year=2025/month=12/day=01/data.parquet"
)
동시성 제어 — multiprocessing.Pool 튜닝
Tardis.dev는 rate limit를 명시적으로 공개하지 않지만, 실측 결과 안정적인 다운로드를 위해서는 다음 규칙을 권장합니다.
- 동시 worker 수: 4~6 (API 키당, S3 mirror 사용 시)
- 재시도: 지수 백오프 (1s, 2s, 4s, 8s, max 5회)
- 타임아웃: 30초 (S3 GET), 15초 (옵션 조회)
평판 / 커뮤니티 피드백
Tardis.dev는 GitHub 공개 토론과 Reddit의 r/algotrading에서 꾸준히 "기관급 데이터의 유일한 affordable 옵션"이라는 평가를 받고 있습니다. 실제 사용자 코멘트를 요약하면 다음과 같습니다.
| 플랫폼 | 평균 평점 | 핵심 칭찬 | 주된 불만 |
|---|---|---|---|
| Tardis.dev (Reddit r/algotrading) | 4.7 / 5 | Replay 정확도, 통합 스키마 | 장기 보관 스토리지 비용 |
| Kaiko | 4.3 / 5 | 엔터프라이즈 SLA, 풍부한 메타데이터 | 월 구독료 $1,000+ |
| Amberdata | 4.1 / 5 | REST API 편의성 | L2 재구성 정확도 이슈 보고 사례 |
Reddit 사용자의 한 코멘트를 그대로 옮겨 보면: "Tardis gives you the actual firehose. Anything that reconstructs order books from periodic snapshots is a toy by comparison." 이 평가는 실제 마이크로스트럭처 연구자에게 그대로 적용됩니다.
이런 팀에 적합 / 비적합
✅ 적합한 팀
- HFT·중단주파 트레이딩 팀이 마이크로스트럭처 전략을 백테스트하려는 경우
- LLM 기반 마켓 분석 시스템을 만들면서 raw 데이터가 필요한 정량 연구팀
- 거래소 통합 백오피스(리스크·이상거래 탐지) 시스템을 만드는 핀테크
❌ 비적합한 팀
- 단순 차트 표시나 캔들 기반 백테스트만 필요하면 Binance 공식 API로 충분
- 1분 단위 이상 데이터로 충분한 장기 추세 분석 워크로드
- 스토리지·네트워크 비용에 극도로 민감한 소규모 PoC 단계
가격과 ROI
Tardis.dev 자체는 $99/월 Standard부터 시작하며, 더 긴 히스토리와 추가 거래소가 필요하면 단계적으로 가격이 올라갑니다. LLM 분석을 얹는 데 들어가는 비용은 위 벤치마크 표의 "월 10,000회 호출" 컬럼을 기준으로 하면 다음과 같이 산출됩니다.
| 옵션 | 데이터 비용(월) | LLM 분석 비용(월) | 총 비용(월) |
|---|---|---|---|
| Tardis Standard + DeepSeek V3.2 via HolySheep | $99 | $9.40 | $108.40 |
| Tardis Standard + GPT-4.1 직접 호출 | $99 | $179.90 | $278.90 |
| Kaiko Pro + Claude Sonnet 4.5 직접 호출 | $1,000+ | $337.90 | $1,337.90+ |
같은 분석 능력을 1/12 수준 가격에 구현할 수 있다는 것이 핵심 ROI입니다. 그리고 HolySheep AI를 통해 결제하면 해외 신용카드 없이 한국 로컬 결제 수단으로 청구 가능하기 때문에, 결제 인프라 문제로 PoC를 미루는 일이 없습니다.
왜 HolySheep AI를 선택해야 하나
- 단일 API 키로 GPT-4.1·Claude Sonnet 4.5·Gemini 2.5 Flash·DeepSeek V3.2를 모두 호출. 모델 A/B 실험이 코드 한 줄 변경으로 끝납니다.
- 글로벌 결제 옵션: 해외 신용카드가 없는 개발자도 한국 로컬 결제 수단으로 즉시 이용 가능합니다.
- 안정적인 연결: 글로벌 리전 라우팅과 failover를 기본 제공하여, 단일 벤더 장애 시에도 분석 파이프라인이 멈추지 않습니다.
- 비용 최적화 가격 정책: DeepSeek V3.2를 $0.42/MTok 수준에서 제공하여, 대량 분석 워크로드에서 비용 부담을 최소화합니다.
- 무료 크레딧: 가입 즉시 무료 크레딧을 받아, 첫 백테스트부터 비용 부담 없이 검증할 수 있습니다.
자주 발생하는 오류와 해결책
오류 1: 401 Unauthorized from Tardis.dev
증상: requests.exceptions.HTTPError: 401 Client Error
원인: API 키 누락 또는 S3 mirror가 아닌 v1 endpoint를 직접 호출했는데 키가 헤더에 없는 경우.
# 잘못된 예
client = TardisClient(api_key=None)
client.download_day("binance-futures", "BTCUSDT",
"incremental_book_L2", "2025-12-01",
use_s3_mirror=False) # 키 없는데 비-mirror 호출
해결: S3 mirror를 기본으로 사용 (키 불필요)
client.download_day("binance-futures", "BTCUSDT",
"incremental_book_L2", "2025-12-01",
use_s3_mirror=True)
오류 2: gzip.BadZipFile 또는 손상된 청크
증상: 네트워크 일시 장애로 받은 gzip 파일이 중간에 끊긴 경우.
# 해결: 재시도 + 부분 다운로드 감지 로직
import hashlib
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
def make_robust_session():
session = requests.Session()
retry = Retry(
total=5, backoff_factor=1.0,
status_forcelist=[500, 502, 503, 504],
allowed_methods=["GET"],
)
adapter = HTTPAdapter(max_retries=retry, pool_maxsize=10)
session.mount("https://", adapter)
session.mount("http://", adapter)
return session
추가로 Content-Length와 받은 바이트 비교 검증
def download_with_integrity(url: str, expected_sha256: str | None = None):
s = make_robust_session()
r = s.get(url, stream=True, timeout=60)
r.raise_for_status()
hasher = hashlib.sha256() if expected_sha256 else None
chunks = []
for chunk in r.iter_content(chunk_size=1024 * 256):
if not chunk:
continue
if hasher:
hasher.update(chunk)
chunks.append(chunk)
if hasher and hasher.hexdigest() != expected_sha256:
raise IOError("checksum mismatch, will retry")
return b"".join(chunks)
오류 3: HolySheep AI 호출 시 404 또는 model_not_found
증상: openai.NotFoundError: model 'gpt-4-1106-preview' not found
원인: base_url을 직접 OpenAI 엔드포인트로 두고 있거나, HolySheep 게이트웨이가 노출하지 않는 구버전 모델명을 호출한 경우.
# 잘못된 예 (금지)
from openai import OpenAI
client = OpenAI(
base_url="https://api.openai.com/v1", # ❌ 금지
api_key="sk-..."
)
올바른 예: HolySheep AI 게이트웨이
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.holysheep.ai/v1", # ✅ 필수
api_key=os.environ["HOLYSHEEP_API_KEY"],
)
모델명은 HolySheep 카탈로그의 정확한 alias 사용
예: "gpt-4.1", "claude-sonnet-4.5", "gemini-2.5-flash",
"deepseek-chat" (= DeepSeek V3.2)
resp = client.chat.completions.create(
model="deepseek-chat", # 가장 비용 효율적
messages=[{"role": "user", "content": "분석해줘"}],
)
오류 4: Decimal 변환 시 정밀도 손실
증상: 호가 단위가 매우 작은 코인(예: SHIB)에서 0이 아닌 값이 0으로 저장됨.
# 해결: 모든 가격/사이즈를 문자열 경유로 Decimal 변환
from decimal import Decimal, getcontext
getcontext().prec = 50 # 충분한 정밀도
def safe_decimal(v) -> Decimal:
if v is None:
return Decimal(0)
return Decimal(str(v)) # float 경유 금지
price = safe_decimal(msg["price"])
size = safe_decimal(msg["size"])
오류 5: 멀티프로세싱 worker가 너무 많이 떠서 메모리 폭주
증상: RAM이 64GB인데도 OOM이 발생.
# 해결: chunk 단위 처리 + Pool 워커 수 제한
from multiprocessing import Pool, set_start_method
import psutil
def safe_worker_count() -> int:
avail_mb = psutil.virtual_memory().available / (1024 * 1024)
# 워커당 약 1.5GB 가정, 시스템용 4GB 예약
usable = max(0, avail_mb - 4096)
return max(1, min(6, int(usable / 1536)))
if __name__ == "__main__":
set_start_method("fork", force=True)
with Pool(processes=safe_worker_count()) as pool:
pool.map(process_day, work_items, chunksize=1)
마무리 — 첫 배포 체크리스트
TARDIS_API_KEY와HOLYSHEEP_API_KEY를 환경변수로 분리, .env.example은 커밋하되 .env는 절대 커밋하지 않습니다.- S3 mirror를 기본으로 사용하고, API 키 quota는 모니터링합니다.
- Parquet 변환은 워커 4개로 시작, 디스크 IO 병목이면 NVMe 로컬 SSD를 권장합니다.
- LLM 분석은 DeepSeek V3.2 → 품질 검증 후 필요 시 상위 모델로 escalation하는 2단 구조가 비용 효율적입니다.
- 재구성 정확도 검증용으로
book_snapshot_25를 같은 기간에 받아incremental_book_L2결과와 교차 검증합니다.
이 파이프라인을 그대로 따라 하면, 1주일 이내에