MinerU가 무엇을 해결하는가.
학술 논문, 계약서, 재무제표, 슬라이드… 세상의 중요한 정보 대부분은 PDF에 갇혀 있다. 그냥 LLM에게 넘기면? 표가 뭉개지고, 수식은 기호 덩어리가 되고, 다단 레이아웃은 순서가 엉킨다. MinerU는 그 PDF를 레이아웃 감지 → OCR → 수식/표 인식 → Markdown/JSON 변환까지 자동 파이프라인으로 처리해, RAG나 에이전트가 바로 집어먹을 수 있는 깔끔한 텍스트로 내보낸다.
한마디로: 복잡한 문서를 LLM 친화적 구조로 바꾸는 오픈소스 OCR+파싱 엔진. PDF뿐 아니라 DOCX·PPTX·XLSX·이미지도 지원하고, 109개 언어 OCR, 수식 → LaTeX, 표 → HTML 변환이 내장돼 있다.
트렌딩 이유 · 기존 PDF 파서 대비 차이점.
PDF 파싱은 오래된 문제다. 그런데 왜 지금 MinerU가 ★26k를 넘겼을까? 세 가지 흐름이 겹쳤다.
① RAG·에이전트 붐 — 기업들이 사내 PDF 문서를 LLM에 먹이려다 "파싱이 병목"임을 깨달았다. 기존 pymupdf, pdfminer 같은 텍스트 추출 도구는 이미지 기반 PDF나 수식이 있으면 손을 못 댄다. ② 정확도 격차 — OmniDocBench 기준 pipeline 백엔드 86.47점, hybrid/vlm 백엔드 95점 이상. 유사 상용 도구와 비교해도 상위권이다. ③ 라이선스 전환 — 2026년 4월 AGPLv3에서 Apache 2.0 기반 커스텀 라이선스로 전환해 기업 도입 장벽이 낮아졌다.
PyPDF, pdfminer 같은 고전적 파서는 텍스트 레이어가 있는 PDF에선 잘 작동하지만, 스캔 PDF·이미지 PDF·수식·복잡한 표를 만나면 쓸 수 없는 쓰레기 텍스트가 나온다. 다단 레이아웃은 열 순서가 뒤섞이고, 수식은 "∫∞−∞f(x)dx" 같은 특수문자 덩어리가 된다. RAG 파이프라인에 이런 노이즈가 들어가면 LLM 응답 품질이 곤두박질친다.
MinerU는 텍스트 레이어를 그냥 추출하는 게 아니라, 페이지를 이미지로 렌더링한 뒤 레이아웃 감지 → 읽기 순서 복원 → OCR/수식/표 전문 모델로 각 블록을 처리한다. 수식은 LaTeX로, 표는 HTML로, 스캔 텍스트는 PP-OCRv6로 변환된다. 결과물은 헤더·단락·코드블록이 명확한 구조화 Markdown이다.
| 비교 항목 | 기존 텍스트 파서 | MinerU |
|---|---|---|
| 스캔 PDF | 빈 텍스트 또는 깨짐 | PP-OCRv6로 109개 언어 인식 |
| 수식 | 깨진 특수문자 | UnimerNet/PP-FormulaNet → LaTeX |
| 표 | 셀 경계 무시, 텍스트 뭉침 | SLANet+/UNet → HTML 표 |
| 다단 레이아웃 | 열 순서 뒤섞임 | PP-DocLayoutV2로 읽기 순서 복원 |
| CPU 전용 환경 | 대부분 가능 | pipeline 백엔드로 CPU만으로도 작동 |
| RAG 통합 | 직접 연결 없음 | LangChain·LlamaIndex·Dify 기본 지원 |
| MCP 서버 | 없음 | Claude Desktop·Cursor에 바로 연결 |
어떤 기술들이 조합되어 있나.
| 역할 | 구성 요소 | 설명 |
|---|---|---|
| PDF 렌더링 | pypdfium2, pypdf | PDF를 페이지 이미지로 변환 / 텍스트 레이어 추출 |
| 문서 분류 | magika (Google) | 입력 파일 형식 자동 감지 (PDF/DOCX/PPTX/XLSX/이미지) |
| 레이아웃 감지 | PP-DocLayoutV2 (YOLO 계열) | 제목·본문·표·그림·수식 영역 바운딩 박스 탐지 |
| OCR | PaddleOCR (PP-OCRv6) | 109개 언어, PyTorch 포트로 내장 |
| 수식 인식 | UnimerNet-small / PP-FormulaNet-Plus-M | 수식 이미지 → LaTeX 변환 |
| 표 인식 (유선) | UNet 기반 구조 모델 (.onnx) | 유선 표(격자가 있는 표) 구조 파악 |
| 표 인식 (무선) | SLANet-Plus (.onnx, PaddleOCR) | 격자 없는 표 인식 |
| 표 분류 | PP-LCNet_x1_0 (.onnx) | 표가 유선/무선/회전 중 어느 타입인지 분류 |
| 추론 엔진 | PyTorch / onnxruntime | pipeline 백엔드; GPU(CUDA/MPS) 또는 CPU |
| 역할 | 구성 요소 | 설명 |
|---|---|---|
| 기본 VLM 모델 | MinerU2.5-Pro-2605-1.2B | 1.2B 파라미터 비전-언어 모델, 다국어 OCR 내장 |
| 로컬 서빙 (Linux) | vLLM ≥ 0.10.1 | CUDA GPU 서버용 고성능 추론 |
| 로컬 서빙 (Windows) | LMDeploy ≥ 0.10.2 | Windows GPU 환경용 VLM 서빙 |
| 로컬 서빙 (macOS) | mlx-vlm ≥ 0.3.3 | Apple Silicon (M1/M2/M3) 네이티브 |
| 외부 API 서버 | OpenAI 호환 HTTP 클라이언트 | Qwen, GPT-4V 등 외부 API 연결 |
| 역할 | 구성 요소 | 설명 |
|---|---|---|
| REST API 서버 | FastAPI + uvicorn | 동기(POST /file_parse) + 비동기(POST /tasks) 엔드포인트 |
| 라우터/로드밸런서 | mineru-router | 다중 GPU/서비스 간 작업 분산, mineru-api 인터페이스 호환 |
| WebUI | Gradio ≥ 5.49 | 로컬 브라우저 인터페이스, 로그인 불필요 |
| CLI | Click 기반 mineru 커맨드 | 단일 파일 / 디렉토리 배치 파싱 |
| 컨테이너화 | Docker (vllm 베이스 이미지) | Linux/WSL2, GPU Compute Capability 7.0~12.1 |
| 오브젝트 스토리지 | boto3 (S3) | 선택적 S3 버킷 입출력 지원 |
| 모델 배포 | HuggingFace Hub / ModelScope | 자동 소스 선택, 로컬 캐시 재사용 |
| 형식 | 라이브러리 | 특이사항 |
|---|---|---|
| DOCX | python-docx + mammoth | PDF 변환 없이 네이티브 파싱, 수십 배 빠름 |
| PPTX | pypptx-with-oxml | 슬라이드 텍스트·그림 추출 |
| XLSX | openpyxl | 시트·셀 구조 파싱 |
문서가 Markdown이 되기까지 — 파이프라인 내부 구조.
ModelSingleton 클래스가 모델 인스턴스를 전역으로 하나만 유지한다. 다중 스레드 환경에서 같은 모델을 중복 로드하지 않도록 threading.RLock()으로 보호된 PIPELINE_MODEL_INIT_LOCK을 쓴다. 멀티 스레드 동시 추론이 3.0에서 완성됐고, 환경변수 MINERU_ENABLE_PIPELINE_INFERENCE_LOCKS로 추론 단계 락을 on/off할 수 있다.
수만 페이지짜리 긴 문서를 통째로 메모리에 올리면 OOM(메모리 부족)이 발생한다. MinerU 3.0+는 슬라이딩 윈도우 메커니즘으로 문서를 구간별로 처리하고, 처리 완료된 결과는 디스크에 스트리밍 기록한다. 덕분에 "문서를 직접 쪼개서 넘겨야 했던" 과거 방식 없이 초대형 문서를 안정적으로 처리한다.
pipeline은 전통적 ML 모델 조합 (layout → OCR → MFR → TabRec), CPU 가능, 정확도 86.47점. hybrid는 pipeline의 네이티브 텍스트 추출 + VLM 보완, GPU 필요, 95점대. vlm-engine은 VLM이 페이지를 직접 읽음, GPU 필요, 95점대. 사용자는 -b pipeline|hybrid|vlm으로 선택한다. hybrid --effort medium이 현재 기본값으로, 속도·정확도 균형점이다.
mineru CLI는 이제 로컬 오케스트레이션 클라이언트다. --api-url을 지정하지 않으면 자동으로 임시 mineru-api 프로세스를 띄운다. 이렇게 분리되면 mineru-router가 여러 서버에 작업을 분산할 수 있고, 멀티 GPU 배포가 단순해진다.
어디에 무엇이 있는가.
중요한 파일 3개를 집중 파악하면 구조 전체가 보인다.
| 파일 | 역할 |
|---|---|
| mineru/utils/enum_class.py | ModelPath 클래스 — HuggingFace/ModelScope 모델 경로 상수 관리. 이 파일 하나에 어떤 모델을 쓰는지 다 나온다. |
| mineru/backend/pipeline/model_init.py | 싱글턴 패턴으로 레이아웃·OCR·수식·표 모델 초기화. 멀티스레드 안전성 락도 여기 정의. |
| mineru.template.json | LaTeX 수식 구분자, LLM 보조 기능(제목 교정에 Qwen3 활용 등), 모델 디렉토리 경로 설정. 복사해 ~/mineru.json으로 사용. |
MinerU를 통해 무엇을 배울 수 있는가.
MinerU는 현대 문서 AI 파이프라인의 교과서다. 레이아웃 분석(Document Layout Analysis)이 핵심인데, 이는 컴퓨터 비전의 객체 탐지를 문서 도메인에 적용한 것이다. PP-DocLayoutV2 소스(PaddleOCR 생태계)를 읽으면 YOLO 계열 모델이 어떻게 문서 블록 좌표를 예측하는지, 그 예측을 어떻게 읽기 순서로 변환하는지 배울 수 있다.
MinerU는 PaddleOCR을 PyTorch로 포팅한 pytorch_paddle.py를 쓴다. 이것이 흥미로운 이유: 원본 PaddleOCR은 PaddlePaddle 프레임워크 의존성이 있어 배포가 까다로운데, PyTorch 포트를 직접 만들어 의존성을 제거했다. 프레임워크 이식(porting)의 실제 사례로 공부할 수 있다. PP-OCRv6는 3.4에서 정확도가 11% 개선됐고 처리 속도가 2배 빨라졌다.
수식 인식은 이미지 → LaTeX 변환 문제다. MinerU는 두 가지 모델을 지원한다: UnimerNet(이미지 encoder + LaTeX decoder, Transformer 기반)과 PP-FormulaNet-Plus-M(PaddleOCR 계열). 환경변수 MINERU_FORMULA_CH_SUPPORT로 선택한다. 중국어 수식이 많으면 PP-FormulaNet이 더 낫다.
표 인식은 두 단계다: ① 표인지 그림인지 분류(표 타입 분류 모델), ② 셀 구조 파악(SLANet-Plus 또는 UNet). MinerU는 ONNX Runtime으로 이 모델들을 실행해 PyTorch 없이도 가볍게 돌릴 수 있다. ONNX를 통한 교차 프레임워크 모델 서빙의 실전 예시다.
mineru-api는 동기 엔드포인트(POST /file_parse)와 비동기 작업 엔드포인트(POST /tasks + 폴링)를 함께 제공한다. 대용량 문서 파싱처럼 오래 걸리는 작업을 비동기로 처리하고 클라이언트는 상태를 폴링하는 패턴을 직접 코드로 볼 수 있다.
UnstructuredMarkdownLoader로 MinerU 결과를 RAG 파이프라인에 연결gradio_app.py)를 읽으며 Gradio 컴포넌트 학습어떤 환경에서 어떻게 시작하나.
| 항목 | pipeline (CPU/GPU) | hybrid / vlm-engine | *-http-client |
|---|---|---|---|
| 정확도 (OmniDocBench) | 86.47점 | 95.39점 (high) / 95.26점 (medium) | 서버 의존 |
| GPU 필요 여부 | 선택 (CPU도 가능) | 필수 | 불필요 (원격 서버 호출) |
| 최소 VRAM | 4 GB (GPU 사용 시) | 8 GB | 2 GB |
| 최소 RAM | 16 GB (32 GB 권장) | 16 GB | |
| 디스크 공간 | 20 GB 이상 (SSD 권장, 모델 포함) | 2 GB | |
| GPU 아키텍처 | Volta 이상 (RTX 10xx 이후) 또는 Apple Silicon | 불필요 | |
| 운영체제 | Linux / Windows / macOS 14+ | ||
| Python 버전 | 3.10 ~ 3.13 | ||
4 GB VRAM은 pipeline을 GPU로 돌리기 위한 최솟값이다. 수식·표 모델까지 GPU에 올리면 여유가 빠듯할 수 있다. 수식 인식(MFR)과 표 인식을 비활성화(--no-formula --no-table)하면 VRAM 소모를 크게 줄일 수 있다. GPU가 없으면 -b pipeline으로 CPU 전용 모드를 쓴다.
# pip 최신화 후 uv로 설치 (uv가 훨씬 빠름)
pip install --upgrade pip
pip install uv
uv pip install -U "mineru[all]"
# 모델 다운로드 (최초 1회, ~10~20 GB)
mineru-models-download -s huggingface -m all
# 중국 환경이면: mineru-models-download -s modelscope -m all
git clone https://github.com/opendatalab/MinerU.git
cd MinerU
uv pip install -e .[all]
# GPU 버전 (NVIDIA, Compute Capability 7.0 이상)
# docker/global/Dockerfile 기반 이미지 사용
# compose.yaml으로 실행:
cd docker/global
docker compose up -d
# GPU 있을 때 (기본 hybrid-medium 백엔드)
mineru -p input.pdf -o output/
# CPU만 있을 때
mineru -p input.pdf -o output/ -b pipeline
# 특정 백엔드 + 언어 지정
mineru -p scan_doc.pdf -o output/ -b pipeline --lang ja
# 배치 처리 (디렉토리)
mineru -p ./docs/ -o output/
# API 서버 시작
mineru-api --host 0.0.0.0 --port 8888
난이도별 3~5단계 — 손을 움직여야 몸이 기억한다.
설치 없이 바로 시작할 수 있다. HuggingFace Spaces 또는 mineru.net에 접속해 PDF를 업로드하고 Markdown 결과를 확인한다.
CPU 환경(GPU 없어도 됨)에서 MinerU를 설치하고 arXiv 논문을 파싱해본다.
pip install uv
uv pip install -U "mineru[all]"
mineru-models-download -s huggingface -m pipeline
# arXiv 논문 다운로드 (예: Attention Is All You Need)
curl -L https://arxiv.org/pdf/1706.03762 -o transformer.pdf
mineru -p transformer.pdf -o ./output/ -b pipeline
# output/transformer/ 폴더에 transformer.md, content_list.json 생성됨
cat output/transformer/transformer.md | head -50
MinerU로 파싱한 Markdown을 LangChain 파이프라인에 연결해 문서 Q&A 시스템을 구현한다.
pip install langchain langchain-community langchain-openai faiss-cpu
python3 <<'EOF'
from langchain.document_loaders import UnstructuredMarkdownLoader
from langchain.text_splitter import MarkdownHeaderTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI
# MinerU 출력 Markdown 로드
loader = UnstructuredMarkdownLoader("output/transformer/transformer.md")
docs = loader.load()
# 헤더 기준으로 청킹
splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=[("#","H1"),("##","H2"),("###","H3")]
)
splits = splitter.split_text(docs[0].page_content)
# 벡터 DB 생성 및 RAG 체인
vectorstore = FAISS.from_documents(splits, OpenAIEmbeddings())
qa = RetrievalQA.from_chain_type(
llm=ChatOpenAI(model="gpt-4o-mini"),
retriever=vectorstore.as_retriever()
)
print(qa.run("What is the main contribution of this paper?"))
EOF
mineru-api의 비동기 작업 패턴(POST /tasks + 폴링)을 직접 구현해 대용량 파일 처리 흐름을 이해한다.
# 터미널 1: API 서버 시작
mineru-api --host 0.0.0.0 --port 8888
# 터미널 2: 비동기 작업 제출 및 폴링
python3 <<'EOF'
import httpx, time
BASE = "http://localhost:8888"
# 파일 업로드 + 작업 제출
with open("transformer.pdf", "rb") as f:
r = httpx.post(f"{BASE}/tasks", files={"file": f})
task_id = r.json()["task_id"]
print(f"Task ID: {task_id}")
# 완료 대기 (폴링)
while True:
status = httpx.get(f"{BASE}/tasks/{task_id}").json()
print(f"Status: {status['status']}")
if status['status'] in ('done', 'failed'):
break
time.sleep(2)
# 결과 다운로드
result = httpx.get(f"{BASE}/tasks/{task_id}/result")
print(result.json()['markdown'][:500])
EOF
GPU가 여러 장인 환경(또는 여러 서버)에서 mineru-router를 이용한 로드밸런싱을 구성한다. router는 mineru-api와 동일한 인터페이스를 제공하므로 클라이언트 코드 변경 없이 확장된다.
# GPU 0에서 API 서버 1
CUDA_VISIBLE_DEVICES=0 mineru-api --port 8881 &
# GPU 1에서 API 서버 2
CUDA_VISIBLE_DEVICES=1 mineru-api --port 8882 &
# 라우터 (두 서버를 묶어 하나의 엔드포인트 제공)
mineru-router --backends http://localhost:8881,http://localhost:8882 --port 8888
MinerU를 이해하고 활용하기 위한 주차별 공부 순서.
| 주차 | 주제 | 공부할 것 |
|---|---|---|
| 1주차 | 문서 파싱 기초 | PDF 구조 이해 (텍스트 레이어 vs 이미지 PDF), pymupdf로 텍스트 추출 실습, MinerU pipeline 백엔드 설치 및 첫 파싱 체험 |
| 2주차 | 컴퓨터 비전 기초 | 객체 탐지 개념 (바운딩 박스, IoU, NMS), YOLO 모델 구조 기초, PP-DocLayoutV2 결과 시각화 실습 (layout_viz 옵션) |
| 3주차 | OCR 엔지니어링 | PaddleOCR 아키텍처 (Detection→Recognition 2단계), PP-OCRv6 개선 사항, 다국어 OCR 처리 방법, Tesseract와 비교 |
| 4주차 | 수식·표 인식 | 이미지→LaTeX (seq2seq 개념), UnimerNet 논문 읽기, HTML 표 구조 (thead/tbody/td), ONNX Runtime으로 모델 로드 실습 |
| 5주차 | RAG 파이프라인 | LangChain 문서 로더·텍스트 분할기, 벡터 DB (FAISS, Chroma), 임베딩 모델 선택, MinerU 출력으로 RAG Q&A 구현 |
| 6주차 | FastAPI 서버 설계 | FastAPI 비동기 라우터, Pydantic 요청/응답 스키마, 백그라운드 작업 + 폴링 패턴, Docker 컨테이너화 |
| 7주차 | VLM 추론 서빙 | vLLM/LMDeploy 아키텍처, PagedAttention 개념, GPU 메모리 관리, mlx-vlm으로 Apple Silicon 추론 실습 |
| 8주차 | 프로덕션 배포 | mineru-router 로드밸런싱, Kubernetes Pod/Service 설계, MCP 서버 연결(Claude Desktop·Cursor), 모니터링 기초 |
처음 마주치면 당황스러운 용어 정리.
| 키워드 | 한줄 설명 |
|---|---|
| PP-DocLayoutV2 | PaddleOCR 생태계의 문서 레이아웃 감지 모델. YOLO 기반으로 제목·본문·표·그림 영역을 바운딩 박스로 탐지한다. |
| PP-OCRv6 | PaddleOCR의 6세대 OCR 모델. MinerU 3.4에서 채택, 기존 대비 정확도 11%↑, 속도 2배↑. |
| UnimerNet | 수식 이미지를 LaTeX로 변환하는 OpenDataLab의 공식 MFR 모델. small 버전이 기본값. |
| PP-FormulaNet-Plus-M | PaddleOCR 기반 수식 인식 모델. 중국어 포함 수식에 강점. 환경변수로 UnimerNet과 교체 가능. |
| SLANet-Plus | 무선 표(격자 없는 표) 구조를 인식하는 ONNX 모델. PaddleOCR TableStructureRec 기반. |
| UNet (표 인식) | 유선 표(격자 있는 표) 구조를 인식하는 ONNX 모델. 픽셀 세그멘테이션으로 셀 경계 탐지. |
| MFR (Math Formula Recognition) | 수식 인식 약자. MinerU 내부 코드에서 AtomicModel.MFR로 표현되는 수식 인식 단계. |
| MFD (Math Formula Detection) | 수식 탐지. 페이지에서 수식 영역 위치를 찾는 단계 (레이아웃 감지의 일부). |
| middle JSON | MinerU 내부 중간 표현. 페이지별 블록 타입·텍스트·좌표가 담긴 JSON. 최종 Markdown 생성 전 단계. |
| OmniDocBench | 문서 파싱 모델 정확도를 평가하는 벤치마크. MinerU가 공식 평가 지표로 사용. v1.6 기준 hybrid 95점대. |
| hybrid-engine | pipeline의 네이티브 텍스트 추출 + VLM의 고정확도를 조합한 백엔드. effort=medium이 기본. GPU 필수. |
| vlm-engine | VLM(Vision-Language Model)이 페이지 이미지를 직접 읽어 파싱하는 백엔드. 가장 높은 정확도. GPU 필수. |
| mineru-router | 여러 mineru-api 서버에 작업을 분산하는 로드밸런서. 멀티 GPU 배포의 핵심. |
| MCP 서버 | Model Context Protocol 서버. Claude Desktop, Cursor 같은 AI 도구에 MinerU를 연결해 문서 파싱을 도구(tool)로 호출 가능하게 한다. |
| magika | Google이 만든 파일 타입 감지 라이브러리. MinerU가 입력 파일 형식을 자동 판별하는 데 사용. |
| InternLM | 상하이 AI Lab의 오픈소스 대형 언어 모델. MinerU는 이 모델의 사전학습 데이터를 처리하다 탄생했다. |
| ONNX Runtime | 모델을 특정 딥러닝 프레임워크 없이 실행할 수 있는 추론 엔진. MinerU의 표 인식 모델이 .onnx 형식으로 배포됨. |
| pdfium2 | Google의 PDF 렌더링 라이브러리 PDFium의 Python 바인딩. MinerU가 PDF 페이지를 이미지로 변환할 때 사용. |
더 깊이 파고들고 싶다면.