LLM용 PDF를 마크다운으로 변환하기
요약
본 문서는 LLM 활용을 위해 PDF를 마크다운(Markdown) 형식으로 변환하는 방법을 다룹니다. 제목, 표 구조 등을 유지하며 텍스트를 구조화하여 RAG 파이프라인이나 에이전트가 읽기 쉬운 형태로 만드는 것이 핵심입니다. 세 가지 오픈 소스 도구(MarkItDown, Docling, Marker)의 사용법과 테스트 결과를 비교 분석합니다.
핵심 포인트
- PDF 내용을 LLM 친화적인 마크다운으로 변환하는 방법을 제시합니다.
- 마크다운은 RAG 파이프라인에서 구조적 분할에 용이하여 선호됩니다.
- MarkItDown, Docling, Marker 세 가지 오픈 소스 도구를 비교 테스트했습니다.
- 테스트는 다양한 복잡성(표, 스캔본 등)의 PDF를 대상으로 진행되었습니다.
PDF를 LLM(대규모 언어 모델)을 위해 마크다운으로 변환한다는 것은 페이지 내용을 구조가 필요한 텍스트로 바꾸는 것을 의미합니다. 즉, 제목은 제목으로, 표는 표로, 열 내용은 읽기 순서대로 유지하는 것입니다. 마크다운은 모델들이 잘 읽으며, 일반적으로 HTML보다 가볍고, RAG 파이프라인에서 임의의 문자 개수 단위가 아닌 제목을 기준으로 분할하기 용이하여 주로 사용되는 목표 형식입니다.
이러한 변환 작업은 세 가지 이유 중 하나로 수행됩니다. 문서를 검색을 위해 인덱싱하거나, 표 구조를 잃지 않고 프롬프트에 붙여넣거나, 에이전트가 읽을 수 있는 파일 형태로 제공하기 위함입니다. 단순 텍스트 추출만으로는 이 세 가지 경우 어느 것에도 충분하지 않기 때문입니다. 왜냐하면 표가 줄마다 하나의 셀로 평탄화되면 표가 없는 것보다 더 나쁜 결과를 초래하기 때문입니다.
이 페이지는 동일한 PDF에 대해 세 가지 오픈 소스 변환기를 실행하고, 코드를 보여주며, 그 결과물을 보고합니다. 또한 어떤 것을 테스트하지 않았는지(anyformat 포함)도 언급합니다.
필요한 것들
- Python 3.10 이상 버전과 모든 도구를 설치할 경우 약 4GB의 여유 디스크 공간이 필요합니다. Docling과 Marker는 첫 사용 시 모델을 다운로드하기 때문입니다.
- 본인이 가진 PDF 파일 하나, 가능하다면 실제 클라이언트 파일보다는 샘플이나 가상의 문서가 좋습니다. 가장 보기 싫은 것을 사용하세요: 표, 두 개의 열, 또는 스캔본 같은 것이 좋습니다. 변환기들은 깨끗한 단일 열 텍스트에서는 동일하게 보입니다.
- 터미널.
- 세 가지 오픈 소스 도구 각각에 대한 가상 환경(virtual environment)이 필요합니다. 각 도구를 개별적으로 설치했기 때문에 의존성 충돌을 방지할 수 있습니다:
pip install "markitdown[pdf]" # environment 1
pip install docling # environment 2
pip install marker-pdf # environment 3
테스트 방법
저희는 세 가지 가상의 PDF를 생성했습니다: 제목, 글머리 목록, 헤더 행이 있는 5x4 표가 포함된 두 페이지 보고서(그리고 이어서 두 개의 열로 구성된 한 페이지), 텍스트 레이어가 없는 스캔 스타일의 PDF(약간 회전된 문장 세 개와 작은 표), 그리고 40페이지짜리 문서입니다. 저희는 2026-09-30에 GPU가 없는 Apple Silicon Mac에서 각 프로젝트 README의 최소 코드를 실행했습니다. 사용된 버전은 MarkItDown 0.1.8, Docling 2.131.0, Marker 2.0.0이었습니다.
이것은 하나의 Mac과 작은 합성 파일들을 사용했으며, 각각 한 번씩 시간을 측정했습니다. 벤치마크로 보기보다는 실패 모드를 확인하는 방법으로 간주해 주십시오.
단계 1. 세 가지 변환기를 실행하기
각각 몇 줄의 코드로 이루어져 있습니다. Microsoft에서 만든 MarkItDown은 다음과 같습니다:
from markitdown import MarkItDown
text = MarkItDown().convert("report.pdf").text_content
IBM Research에서 만든 Docling은 다음과 같습니다:
from docling.document_converter import DocumentConverter
text = DocumentConverter().convert("report.pdf").document.export_to_markdown()
Datalab에서 만든 Marker는 다음과 같습니다. 여러 페이지의 PDF에서는 워커 프로세스를 시작하므로, 메인 가드(main guard) 안에 넣지 않으면 스크립트 상단 부분을 재실행하게 되니 주의해야 합니다:
from marker.converters.pdf import PdfConverter
from marker.models import create_model_dict
from marker.output import text_from_rendered
...
우리가 본 것
| MarkItDown | Docling | Marker | |
|---|---|---|---|
| 표(Table) | 손상됨: 셀당 한 줄, 열이 뒤섞임 | 정확함 | 정확함 |
| ... | |||
| 시간은 GPU가 없는 Apple Silicon Mac 하나에서 2026-09-30에 단일 실행으로 측정되었습니다. |
MarkItDown은 빠르지만 깨끗한 텍스트에만 적합하다
이것은 두 페이지를 0.04초 만에 변환했으며, 두 열의 읽기 순서를 유지했습니다. 하지만 제목(headings)은 전혀 유지하지 못했고, 글머리 기호(bullet glyphs)는 (cid:127) 줄로 바뀌었으며, 표도 뒤섞였습니다: 각 셀이 자체 단락이 되었고 열 순서가 섞였습니다.
Region Q1 Q2 Q3
North
100
...
스캔된 PDF의 경우 빈 문자열을 반환했습니다. MarkItDown의 README에는 이미지를 비전(vision)이 있는 LLM으로 보내는 별도의 markitdown-ocr 플러그인이 설명되어 있지만, 우리는 그것을 테스트하지 않았습니다. 깨끗한 단일 열 텍스트의 경우 압도적으로 가장 저렴한 옵션입니다. 하지만 표나 스캔된 자료에는 자체만으로는 충분하지 않습니다.
Docling은 비용을 지불하고서라도 여기서 최고의 출력을 보여주었다
Docling은 표는 올바른 마크다운 테이블로, 목록은 목록으로, 두 개의 열은 단락이 풀린 상태로 순서대로 반환했습니다. 또한 설정 없이 스캔 자료에 대해 OCR을 실행하여 세 문장과 정확한 테이블을 반환했습니다. 저희가 원본과 육안으로 비교해 본 결과 오류는 발견되지 않았습니다. 이는 정확도 점수가 아닌 관찰된 내용입니다.
| Region | Q1 | Q2 | Q3 |
|----------|------|------|------|
| North | 100 | 120 | 140 |
...
비용은 약 1.1 GB의 패키지와 약 570 MB의 모델 크기이며, 처음 실행 시(모델 다운로드 및 초기화)는 대략 70초가 걸리고 이후 문서당 몇 초가 소요됩니다. 또한 제목 레벨을 평탄화했습니다: 모든 제목이 ##로 출력되어 제목과 그 하위 섹션들이 동일하게 보입니다. 만약 사용하시는 청커(chunker)가 제목 깊이에 따라 분할한다면, 이 점이 중요합니다.
Marker: 신뢰하기 전에 설치 상태를 확인하세요
Marker는 텍스트 PDF에서 올바른 테이블과 올바른 두 열 순서를 읽어냈으나, 한 제목을 제외하고 두 열 페이지에서 누락되는 문제가 있었습니다. 저희 테스트에서 두 가지 문제가 발생했으며, 둘 다 알아두실 필요가 있습니다.
첫째, GPU가 없는 Mac 환경에서 Marker 2.0.0은 스캔된 페이지를 변환할 수 없었습니다. SpawnError: llama-server binary not found라는 오류와 함께 중단되었습니다. 이 제품의 README에 따르면 CPU 및 Apple Silicon 모드는 llama.cpp에서 별도로 설치한 llama-server 바이너리가 필요하다고 합니다. 저희는 이를 설치하지 않았기 때문에 스캔 자료에 대한 Marker 결과는 없으며, 이에 대해 주장하지 않습니다.
둘째, 모든 섹션의 본문 텍스트가 동일한 40페이지 분량의 PDF에서 Marker는 701자만 반환하고 섹션 2부터 40까지의 본문을 누락시켰습니다. 저희는 반복적인 헤더 제거 문제라고 의심하지만, 이를 확인하지 못했으므로 관찰된 내용으로 간주해 주십시오. 각 섹션마다 고유한 텍스트를 가진 40페이지 분량의 PDF에서는 모든 40개 섹션이 살아남았지만, 81개의 제목 중 42개만 통과했으며, 레벨은 ###와 ####로 평탄화되었습니다.
어떤 것을 배포하기 전에 반드시 라이선스를 확인하세요. Marker's README에 따르면 코드는 Apache 2.0이며 모델 가중치는 "수정된 AI Pubs Open Rail-M 라이선스(연구, 개인 사용 및 $5M 미만 자금 조달/매출을 가진 스타트업에게 무료)"를 사용합니다. 그 이상의 상업적 경로는 공급업체를 통해 이용할 수 있습니다. Docling의 코드는 MIT이며, README는 각 모델의 라이선스로 안내합니다. MarkItDown은 MIT입니다.
아무것도 제공하지 못한 것들
어떤 변환기도 진정한 제목 레벨을 보존하지 못했으며, 페이지의 어느 위치에서 블록이 왔는지 또는 그에 대해 얼마나 확신하는지 반환하지 못합니다. RAG(검색 증강 생성) 청커에게는 보통 괜찮습니다. 하지만 검토자가 출처를 봐야 하거나 신뢰할 것을 자동으로 결정해야 하는 경우에는 이 정보가 필요하며, 이는 아래의 anyformat 섹션에서 설명합니다.
직접 PDF 확인하기
저희 표에 의존하지 마세요. 문서에 포함되어 있다고 아는 몇 가지 항목을 적어보고 테스트해 보세요. 10분밖에 걸리지 않지만 어떤 벤치마크보다 더 많은 것을 알려줍니다. 아래 함수는 실패한 체크만 보고하며, 문서의 내용은 절대 보고하지 않아 로그로 기록하기 안전합니다.
def check_markdown(md: str, must_contain: list[str], table_row: list[str]) -> list[str]:
problems = []
for i, needle in enumerate(must_contain, start=1):
...
같은 파일에 대해 모든 변환기로 실행해 보면 자신만의 비교 결과를 얻을 수 있습니다.
어떤 경우에 무엇을 사용할지
- 구조보다 속도가 더 중요한 깨끗하고 단일 열의 텍스트: MarkItDown.
- 테이블, 스캔 및 다중 열 레이아웃, 설치 비용을 감당할 수 있다면: Docling.
- GPU를 가지고 있거나 llama.cpp 의존성을 갖추고 있고 모델 라이선스를 읽었다면 Marker. 먼저 긴 문서를 대상으로 테스트해 보세요.
또 다른 방법: anyformat
anyformat은 문서 추출 플랫폼이며, 파싱(parsing)이 첫 단계이고 독립적으로 사용할 수 있습니다. PDF를 보내면 API를 통해 마크다운을 받고, 설치할 모델도 GPU도 필요 없습니다.
import os
import time
from anyformat.sdk import Client
...
pip install anyformat으로 설치합니다. 반환되는 마크다운은 구조화되어 있습니다: 페이지의 각 블록을 식별하는 앵커(anchors)를 포함하고 있습니다. 전체 파싱 결과는 해당 블록들을 페이지, 경계 상자(bounding box), 그리고 신뢰도 점수(confidence score)와 함께 나열하며, 이를 통해 특정 텍스트 조각이 페이지의 어느 위치에 있는지 링크를 유지할 수 있습니다. 이 예제는 마크다운 문자열만 가져오며, 블록 출력은 API 문서에서 설명합니다. 응답 형태는 API Docs를 참조하세요. 동일한 파싱은 MCP 서버를 통해 에이전트로부터도 접근할 수 있습니다.
위 테스트에서 anyformat을 실행하지 않았으므로, 이 페이지는 해당 파일들에서 그 출력이 어떻게 비교되는지에 대한 어떠한 주장도 하지 않습니다. 실제 파일에는 클라이언트 데이터가 포함될 수 있으므로, 가상의 문서를 사용하여 위 섹션의 검사를 통해 반환되는 마크다운을 직접 실행하고 비교해 보세요. 만약 문서가 깨끗하고 인덱싱을 위해 텍스트만 필요하다면, 로컬 오픈소스 변환기가 더 간단한 선택입니다.
자주 묻는 질문 (Frequently asked questions)
RAG에 가장 좋은 PDF-to-markdown 컨버터는 무엇인가요?
문서에 따라 다릅니다. 저희 테스트 파일에서는 Docling이 가장 완전한 출력을 제공했고, MarkItDown은 가장 빠르며 깨끗한 텍스트에서만 신뢰할 수 있었고, Marker는 스캔의 경우 추가 설정이 필요했습니다. 선택하기 전에 위와 같은 검사를 통해 자체 PDF로 테스트해 보세요.
MarkItDown은 OCR을 수행하나요?
일반적인 PDF 변환에서는 그렇지 않습니다. README에는 이미지를 읽기 위해 비전(vision)을 사용하는 LLM과 Azure Document Intelligence를 사용하는 옵션을 포함하는 별도의 markitdown-ocr 플러그인이 설명되어 있습니다.
Marker는 상업적 사용에 무료인가요?
코드는 Apache 2.0입니다. 모델 가중치(model weights)는 AI Pubs Open Rail-M 라이선스를 사용하며, README에는 이 라이선스가 연구, 개인 사용 및 $5M 미만의 자금 지원 또는 매출을 가진 스타트업에 대해 무료라고 설명되어 있습니다. 귀하의 경우를 위해 저장소에서 라이선스를 읽어보세요.
PDF를 마크다운으로 변환할 때 표가 깨지는 이유는 무엇인가요? PDF는 행과 열이 아닌 페이지의 위치에 문자를 저장합니다. 텍스트를 순서대로만 읽는 컨버터는 각 셀을 개별 줄로 만듭니다. 테이블 구조를 감지하는 컨버터는 행을 재구성할 수 있습니다.
GPU가 필요한가요? 저희가 사용한 세 가지 도구의 경우 그렇지 않습니다. 모두 GPU 없이 Mac에서 텍스트 PDF를 변환했습니다. Marker의 README에는 정확도가 더 높은 GPU 모드가 설명되어 있으며, Mac에서의 스캔 페이지 모드는 위에서 설명했듯이 추가 바이너리가 필요했습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기