MarkItDown은 웹 스크래퍼와 자주 같은 범주로 묶이곤 하는데, 그 분류는 틀렸습니다. 이 도구에는 크롤러도 없고, JavaScript 실행 엔진도 없고, URL을 가져와서 본문 외 요소를 깔끔하게 제거하는 기능도 없습니다. 대신 이미 가지고 있는 바이트, 즉 PDF, Word 문서, 스프레드시트, 슬라이드 자료 등을 받아서 언어 모델이 읽기 좋은 Markdown으로 변환합니다.
저는 Microsoft의 MarkItDown을 단일 Mac 환경에서 몇 주 동안 실제 문서들에 돌려 보면서, 사전에 작성한 매니페스트와 대조해 모든 표를 채점하고 각 변환 시간을 기록했습니다. 한 줄 요약은 이렇습니다. 입력이 깨끗하면 빠르고 충실하지만, 패키징에는 요청하지도 않은 73MB짜리 머신러닝 런타임이 숨어 있고, 표는 "텍스트가 살아남았는가?" 검사에는 통과해도 "데이터가 올바른 열에 있는가?" 검사에서는 실패하는 식으로 깨집니다. 이제 숫자와 함께 전체를 살펴보겠습니다.
MarkItDown은 정확히 무엇인가
MarkItDown은 Microsoft가 만든 Python 유틸리티로, 파일과 Office 문서를 LLM에 최적화된 Markdown으로 변환합니다. PDF, .docx, .xlsx, .pptx, 이미지, HTML 파일, 그리고 그 밖의 몇 가지 형식에 던져 넣으면 Markdown을 돌려줍니다. 호출 방식도 세 가지로 제공됩니다. CLI(markitdown file.pdf -o out.md 또는 stdin 파이프), Python API(MarkItDown().convert(...)), 그리고 에이전트 워크플로용 선택형 MCP 서버입니다.

가장 중요한 점은 이 도구가 무엇을 하지 않는가입니다. README가 그런 기능을 주장하지도 않고, 테스트에서도 확인했듯이 크롤링도, JS 렌더링도, 링크 추적도, 페이지네이션 처리도, readability 스타일의 본문 추출도 하지 않습니다. 이 도구는 전체 문서를 변환합니다. 사용자가 바이트를 가져오면, 그것을 표준화합니다. 이 한 가지 차이가 이 도구를 스택에 넣을지 말지를 결정하므로, 계속해서 이 점을 짚게 될 것입니다.
GitHub 수치만 보면 저장소의 규모는 꽤 큽니다. 2026년 7월 중순 기준 165,282개의 스타와 11,790개의 포크를 보유한 MIT 라이선스 프로젝트이며, 최신 릴리스(v0.1.6)는 2026-05-26에 공개됐습니다. 다만 이 스타 수는 Microsoft 조직 저장소가 LLM 도구에 대한 전반적인 관심을 탄 덕분이지, 변환 엔진의 성숙도를 직접 보여주는 지표는 아닙니다. 열린 이슈도 833개나 있고, 그중 몇몇은 설치 전에 알아야 할 내용입니다(아래에서 더 설명합니다).
HTML을 Markdown으로: 빠르고 완전하지만, 부수 콘텐츠도 함께
이번 스크래퍼 리뷰 시리즈의 나머지 부분과 마찬가지로 동일한 네 개의 웹 테스트 파일을 사용했기 때문에, MarkItDown에도 똑같은 로컬 HTML 파일을 넣어 봤습니다. 스크래퍼로 평가하려는 목적이 아니라, HTML을 Markdown으로 얼마나 잘 바꾸는지 확인하기 위해서였습니다. 태그가 잘 정리된 페이지에서는 정말 괜찮았습니다.
핵심 설치만으로 네 페이지가 모두 변환됐고 추가 패키지도 필요 없었습니다. 본문 내용도 빠짐없이 살아남았습니다. Wikipedia의 "Web scraping" 문서(226KB)는 제목 구조를 그대로 옮겨 왔습니다. h1 하나, h2 일곱 개, h3 열두 개가 실제 섹션 구조와 일치했고, 418개의 링크도 [text](url) 형식으로 보존됐습니다. Scrape This Site forms 페이지의 25×9 하키 통계 표는 27행짜리 깔끔한 GFM 파이프 테이블로 바뀌었습니다. 헤더, 구분선, 데이터 26행까지 그대로였습니다. 속도도 문제 없었습니다. 작은 quotes 페이지는 중앙값 48ms, 226KB짜리 Wikipedia 페이지는 352ms였습니다.
하지만 여기에는 함정이 하나 있습니다. 버그라기보다 설계 선택에 가깝습니다. MarkItDown은 보일러플레이트를 제거하지 않습니다. <body> 전체를 변환하므로 사이트의 헤더·푸터·네비게이션 같은 껍데기도 함께 따라옵니다. 그리고 이런 잔여물은 페이지에 얼마나 많은 부가 UI가 있느냐에 따라 커집니다.
| 페이지 | 출력 문자 수 | 제목(h1/h2/h3) | 링크 수 | 사이트 공통 UI 줄 비율 |
|---|---|---|---|---|
| Books to Scrape | 10,478 | 1 / 0 / 0 | 94 | 0.6% (1/159) |
| Quotes to Scrape | 2,973 | 1 / 1 / 0 | 55 | 1.2% (1/86) |
| ScrapeThisSite forms | 3,385 | 1 / 0 / 0 | 31 | 6.7% (5/75) |
| Wikipedia Web scraping | 60,159 | 1 / 7 / 12 | 418 | 12.4% (42/338) |
거의 부가 UI가 없는 Books 홈페이지에서는 출력 줄의 0.6%만이 사이트 공통 UI입니다. 반면 Wikipedia에서는 그 비율이 12.4%에 달합니다. 비어 있지 않은 338줄 중 42줄이 "jump to content", "목차 토글", "22 languages", "retrieved from", 쿠키/라이선스 푸터 같은 내용입니다. Wikipedia의 관리 배너("이 문서에는 추가 출처가 필요합니다")까지도 충실하게 두 열 파이프 테이블로 렌더링되며, 실제 데이터 표가 없는 페이지에서 표 행이 9개나 생기는 이유가 바로 이것입니다.
이건 MarkItDown이 뭔가 잘못한 것이 아닙니다. 이 도구는 전체 문서를 변환하는 도구이지, readability 추출기가 아닙니다. 충실한 HTML-to-Markdown 변환과 깔끔한 기사 본문 추출은 서로 다른 작업입니다. Trafilatura나 Firecrawl 계열 도구는 본문만 돌려주려 하지만, MarkItDown은 페이지 전체를 돌려줍니다. 내부적으로는 _html_converter.py가 <script>와 <style>을 제거한 뒤 전체 body를 markdownify 라이브러리에 넘기며, 본문 추출 휴리스틱은 전혀 들어 있지 않습니다. 기사 본문만 원한다면, 이건 잘못된 레이어입니다.
MarkItDown의 주 무대: PDF, DOCX, XLSX, PPTX
MarkItDown이 본래 겨냥한 것은 문서입니다. 저는 실제 공개 파일들을 대상으로 테스트했습니다. 텍스트 레이어가 있는 arXiv 논문, 비트코인 백서, 텍스트가 전혀 없는 이미지 전용 스캔 PDF(직접 렌더링한 파일), 그리고 UUID를 심어 두어 조용한 콘텐츠 손실 여부를 확인할 수 있도록 MarkItDown 자체 테스트 스위트의 DOCX/XLSX/PPTX 파일입니다.
| 문서 | 입력 | 출력 문자 수 | 프로브 | 중앙값 시간 | 메모 |
|---|---|---|---|---|---|
| arXiv 1706.03762 (텍스트 레이어 PDF) | 2.2 MB | 40,174 | 7/7 | 3.7초(워밍업) | title, "Transformer", "BLEU", "References" 모두 포함 |
| Bitcoin whitepaper (9쪽 PDF) | 184 KB | 22,485 | 6/6 | 1.4초 | "Satoshi Nakamoto", "proof-of-work", "Conclusion" 포함 |
| 스캔 PDF (텍스트 레이어 없음) | 89 KB | 0 | 0/4 | 15ms | 출력 없음, 오류 없음, OCR 없음 |
| DOCX (test.docx) | 136 KB | 4,651 | — | 70ms | 제목 + GFM 표; 삽입한 UUID도 유지 |
| 수식이 포함된 DOCX | 15 KB | 240 | — | 101ms | Office Math가 LaTeX로 보존됨 |
| XLSX (test.xlsx) | 12 KB | 808 | — | 57ms | 각 시트가 ## SheetName + GFM 표로 변환 |
| PPTX (test.pptx) | 278 KB | 2,047 | — | 52ms | 슬라이드 번호 표식, 표, 차트가 표로 변환 |
텍스트 레이어가 있는 PDF에서 텍스트 회수율은 매우 좋았습니다. arXiv의 "Attention Is All You Need" 논문에서는 사전 등록한 7개 프로브를 모두 찾았고, Bitcoin 백서에서는 6개 전부를 찾았습니다. Office 파일에서도 UUID sentinel이 하나도 빠지지 않았으므로, 유지보수용 회귀 테스트 파일들에서 조용한 콘텐츠 손실은 없었습니다. 특히 좋았던 좁은 강점 하나는 DOCX 경로(mammoth를 통해)가 Office Math 수식을 LaTeX로 유지한다는 점입니다. equations.docx가 진짜 $$...$$ 수식으로 변환됩니다. 수식이 많은 Word 문서를 LLM에 넣는다면, 작지만 분명한 강점입니다. 다른 곳에서는 이 장점이 잘 정리된 걸 못 봤습니다.
이 무대에서 특히 주의할 만한 발견은 두 가지입니다. 실제로 가장 먼저 발목을 잡을 가능성이 큰 것들이기 때문입니다.
사라져 버리는 스캔 PDF
텍스트 레이어가 없는 이미지 전용 PDF를 MarkItDown에 넣으면 빈 문자열이 나옵니다. 0자, 예외 없음, 경고 없음. 추출할 것이 없기 때문에 약 15ms 만에 끝납니다. MarkItDown의 PDF 경로는 텍스트 추출 전용이며(pdfminer와 pdfplumber를 내부에서 사용), 핵심 설치에도, pip extra에도 OCR은 들어 있지 않습니다.
이건 배치 작업에서 문제가 됩니다. 일부는 스캔본인 PDF 폴더를 처리하는 개발자는, 아무 신호도 없이 해당 파일들에서 조용히 빈 결과를 받게 됩니다. 저는 fixture 자체가 깨진 게 아닌지 확인하려고 pdfminer의 extract_text를 직접 돌려 봤고, 그 결과 0개의 추출 문자와 텍스트 레이어 없음이 확인되었습니다. 따라서 빈 출력은 실제 스캔 파일에 대한 MarkItDown의 진짜 동작입니다. 이는 오래전부터 열려 있는 OCR fallback 갭(#1268)을 그대로 재현한 결과이기도 합니다. 문서화된 경로는 선택형 Azure Document Intelligence 백엔드나 플러그인이며, 둘 다 기본 설치에는 포함되지 않습니다.
PDF는 구조가 아닌 평문으로 나온다
텍스트 레이어가 있는 두 PDF 모두에서 MarkItDown은 Markdown 제목 마커를 하나도 만들지 않았습니다. PDF 자체에는 의미론적 heading 태그가 없고, MarkItDown도 글자 크기 등을 보고 이를 추론하지 않기 때문에 모든 줄이 본문 레벨로 들어갑니다. 텍스트 회수율은 높지만, 구조는 평평합니다.
이건 제 결과만이 아닙니다. 외부 공개 벤치마크에서도 MarkItDown의 PDF heading 계층 점수는 대략 0.0, 표 충실도는 약 0.27로 나오며, Docling의 TableFormer 기반 0.88보다 한참 낮습니다(MarkItDown vs Docling vs Marker 비교와 READoc 벤치마크 참고). 제 테스트도 같은 결과를 재현했으니, 증거력 측면에서는 강점입니다. 외부 소스와 제 수치가 맞아떨어지기 때문입니다. 같은 벤치마크들이 보여 주는 트레이드오프는 MarkItDown이 Docling보다 대략 100배 빠르다는 점인데, 제 문서 테스트에서도 분 단위가 아니라 초 단위였던 결과와 잘 맞습니다. 결론은 이렇습니다. MarkItDown은 빠르고 깔끔한 PDF 텍스트를 주지만, PDF의 구조는 주지 않습니다. heading과 표가 반드시 살아 있어야 한다면 Docling이나 Marker 같은 레이아웃 모델 도구가 맞는 레이어입니다.
표: 텍스트는 살아남아도 구조는 종종 무너진다
표에서는 "텍스트가 살아남았는가?"와 "데이터를 실제로 쓸 수 있는가?"가 갈라지기 때문에, 정확히 어떤 형태가 유지되고 어떤 형태가 깨지는지 보기 위해 13개 케이스 매트릭스를 만들었습니다. 각 케이스는 하나의 <table>로 구성했고, 실행 전에 작성한 매니페스트와 비교해 점수를 매겼습니다.

핵심 결론은 이렇습니다. MarkItDown은 표 내용을 한 번도 잃지 않았습니다. 13개 케이스 모두 사전에 등록한 토큰을 100% 유지했습니다. 하지만 구조 충실도는 세 갈래로 갈렸습니다. 13개 중 7개는 잘 형성된 GFM 그리드로 나왔습니다. 일반 표, 헤더 colspan, 24열짜리 넓은 표, 헤더 없는 표, 빈 셀 표, 블록이 들어간 셀, 그리고 오른쪽에서 왼쪽으로 쓰는 아랍어 표입니다. 4개는 Markdown에 span 셀 개념이 없기 때문에 너덜너덜해졌습니다. rowspan, colspan, 그리고 잘못된 원본은 짧은 행으로 떨어집니다. 나머지 2개는 아예 망가졌습니다.
망가진 두 사례는 꼭 짚을 가치가 있습니다. 중첩 표(<td> 안의 <table>)는 인라인으로 평탄화되면서 자기 자신의 파이프와 구분선 행을 부모 셀 안에 쏟아 넣고, 결과적으로 14개 "열"짜리 쓰레기 행을 만듭니다. 또 셀 안의 문자 그대로의 |는 이스케이프되지 않습니다. a | b는 두 열로, x || y는 세 열로 읽히기 때문에, 2열 표가 2열·3열·4열짜리 행을 뱉게 되고, 이후의 Markdown 파서는 잘못된 경계를 읽게 됩니다. 흥미롭게도 셀 내부의 별표와 백틱은 이스케이프됩니다. 파이프만 예외입니다. 원인은 MarkItDown의 HTML 경로가 markdownify의 기본 표 처리 방식을 사용하고, 커스텀 서브클래스가 링크, 이미지, 제목은 덮어쓰지만 셀은 건드리지 않기 때문입니다. 같은 파이프 이스케이프 버그 계열은 CSV 변환기에 대해서도 오픈 이슈(#2019)로 올라와 있지만, 그 수정은 제가 테스트한 HTML 경로에는 닿지 않습니다.
가장 미묘하지만 데이터 엔지니어라면 꼭 봐야 할 결과는 rowspan입니다. t03 케이스는 단순히 너덜너덜해지는 수준이 아니라, 조용히 데이터 정렬이 틀어집니다. rowspan=2인 라벨("Fruit")은 한 번만 출력되고, 그 아래 행은 짧은 2열 행(| Banana | 8 |)이 됩니다. 그래서 "Banana"가 Item이 아니라 Group 열 아래로 들어갑니다. 토큰은 모두 존재합니다. 하지만 무심코 "두 번째 열을 읽는" 소비자는 잘못된 값을 얻게 됩니다. 텍스트 생존 검사에는 통과하지만 데이터셋을 조용히 오염시키는, 그런 종류의 버그입니다.
이 span 제한 자체는 이미 알려져 있고 추적 중인 설계 제약입니다(#1211, #1248). 평평한 GFM 파이프 그리드로는 span이나 중첩을 진짜로 표현할 수 없기 때문에, 이 변환기는 구조를 포기하고 내용 완전성을 택합니다. 좋은 동작도 있습니다. 헤더 없는 표는 빈 헤더 행을 생성하므로 데이터가 조용히 헤더로 승격되지 않고, 빈 셀은 유지되며, <caption>은 표 위의 텍스트 줄로 살아남습니다.
설치와 시작 시간: "가벼운 유틸리티"가 말해 주지 않는 비용
이 부분은 예상 밖이었고, "가벼운 Python 유틸리티"라는 표현이 얼마나 과장되었는지 드러나는 지점입니다.

첫째, pip install 'markitdown[all]'은 쓰지 마세요. Python 3.14에서 이 명령은 조용히 markitdown 0.0.2로 되돌아가며, 저는 깨끗한 venv에서 이를 직접 재현했습니다. 버전 고정으로 그 이유가 드러납니다. pip install 'markitdown[all]==0.1.6'는 에러가 나는데, [all] extra가 youtube-transcript-api~=1.0.0를 고정해 두었고, 현재 PyPI의 해당 범위 빌드들은 모두 Python <3.14로 제한되어 있으며, 3.14와 호환되는 빌드만 그 고정 범위 밖에 있기 때문입니다. 해결되지 않는 resolver가 끝까지 내려가다 보니, 의존성을 만족시킬 수 있는 마지막 릴리스로 돌아가는 것입니다. 이는 오픈 업스트림 이슈(#2179)와 일치합니다. 해결책은 단순합니다. 버전을 고정하고 extra를 개별로 설치하세요. pip install 'markitdown==0.1.6' 다음에 pip install 'markitdown[pdf,docx,pptx,xlsx,xls]==0.1.6'를 설치하면 됩니다. 각각은 정상적으로 해결되며, 문제는 [all] 묶음에만 있습니다. (이 함정은 Python 버전에 따라 다릅니다. Python 3.13 이하에서는 해당 제한이 걸리지 않아 [all]의 해석이 달라질 수 있습니다.)
둘째, 설치 용량입니다. 핵심 설치만 해도 161MB입니다(13MB짜리 빈 venv + 148MB). 그중 onnxruntime 73MB와 numpy 34MB가 합쳐서 107MB를 차지하므로 전체 핵심 footprint의 66%입니다. 둘 다 단일 하드 의존성인 magika, 즉 Google의 ML 파일 형식 탐지기 때문에 끌려옵니다. 즉, 텍스트 변환기 하나가 기본 설치에 73MB짜리 ONNX 추론 런타임을 싣고 오는 셈입니다. 문서용 extras까지 더하면 venv는 310MB까지 올라갑니다. 헤드리스 브라우저 스택보다 훨씬 가볍긴 하지만, pip install 한 번으로 끝나는 마이크로 유틸리티를 기대했다면 ONNX 런타임이 동반된다는 점은 알아 두셔야 합니다.
셋째, 그리고 이번 전체 테스트에서 제가 진행한 모든 새로움 검사를 통과한 유일한 발견이기도 한데, 깨끗하게 설치한 뒤에도 import markitdown은 이 머신에서 약 3.35초가 듭니다. 비용은 거의 전적으로 import 시점에 발생합니다. markitdown._markitdown이 전체 변환기 레지스트리를 즉시 로드하기 때문인데(누적 2.56초, 총 시간의 76%), 그 과정에서 pandas(1.21초, XLSX 변환기 경유), python-pptx(427ms), magika(354ms), requests(270ms)까지, 실제로 해당 형식을 변환하지 않더라도 전부 끌려옵니다. 장기 실행 서비스라면 이 비용은 한 번 흡수되고 끝납니다. 하지만 CLI 실행이나 서버리스 cold start에서는 프로세스마다 지불해야 하는 실제 비용이며, "가벼운 유틸리티"라는 말만 들으면 예상하기 어려운 부분입니다. (공정한 단서는, 이것은 단일 프로파일 실행 결과이며 여러 번의 분포가 아니라 하나의 관측값으로 취급했다는 점입니다.)

규모: 크래시는 없지만, PDF에는 CPU 예산을, 스프레드시트에는 RAM 예산을 잡아야 한다
네 개의 큰 대상 파일을 각각 별도 프로세스로 돌렸습니다. 이전 실행의 영향으로 피크 메모리가 오염되지 않도록 하기 위해서였습니다. 크래시는 없었습니다. 다만 비용 구조는 한쪽으로 치우쳐 있습니다.

| 대상 | 입력 | 출력 문자 수 | 중앙값 시간 | 피크 RSS 변화 |
|---|---|---|---|---|
| NIST SP 800-53r5 (492쪽 PDF) | 6.07 MB | 1,625,365 | 192.5초 | +40 MB |
| XLSX 50,000행 × 8열 | 2.1 MB | 3,722,955 | 62.1초 | +374 MB |
| arXiv 1706.03762 (~15쪽 PDF) | 2.2 MB | 40,174 | 12.6초 | +25 MB |
| XLSX 200행 × 64열 | 46 KB | 120,129 | 2.9초 | +22 MB |
492쪽 분량의 NIST PDF는 중앙값 192.5초, 즉 약 3.2분이 걸렸습니다. 페이지당 0.39초 정도입니다. pdfplumber가 모든 페이지에서 단어 위치 기반 폼 감지를 수행하기 때문입니다. 피크 RSS는 +40MB 수준에 머물렀으므로 메모리보다 CPU가 병목입니다. 15쪽짜리 arXiv PDF도 별도 프로세스에서는 12.6초가 걸렸는데, 이는 같은 파일이 문서 모음 안에서 워밍 상태였을 때의 3.7초보다 약 3.4배 느립니다. 이 차이는 cold process 비용이며, 원시 바이트 크기보다 페이지별 작업량이 주된 원인임을 보여 줍니다. 이 PDF에 대한 단일 전이 가능한 숫자가 필요하다면, 격리 실행의 12.6초를 쓰면 됩니다.
스프레드시트 경로는 병목이 반대로 바뀝니다. 2.1MB, 50,000행짜리 XLSX는 +374MB의 피크 RSS와 370만 자가 넘는 출력으로 불어났습니다. 변환기가 전체 시트를 메모리에 올리고 거대한 Markdown 문자열 하나를 만들기 때문입니다. 따라서 실무적 가이드는 단순합니다. 큰 PDF는 CPU를 몇 분 단위로, 큰 스프레드시트는 RAM을 수백 MB 단위로 잡아 두어야 합니다. 이 수치는 macOS arm64와 Python 3.14에서 얻은 단일 머신 결과이며, 페이지당·행당 상수는 플랫폼에 따라 다릅니다. 하지만 형태, 즉 PDF는 느리고 CPU를 쓰며, XLSX는 메모리를 많이 먹고, 아무것도 터지지는 않는다는 점은 그대로 옮겨갈 수 있습니다.
Thunderbit가 들어갈 자리 — 그리고 아닌 자리
이 비교는 과장하기 쉬운 부분이므로, 선을 분명히 그어 두겠습니다. MarkItDown과 Thunderbit는 같은 문제가 아니라 인접한 문제를 해결합니다.
MarkItDown은 이미 가지고 있는 파일을 변환합니다. Thunderbit는 먼저 페이지를 가져옵니다. Thunderbit의 /distill 엔드포인트는 살아 있는 웹 페이지를 깔끔하고 LLM 친화적인 Markdown으로 바꿉니다. MarkItDown에는 없는 JS 렌더링, 안티봇 대응, 동적 콘텐츠 처리까지 담당합니다. 그리고 /extract 엔드포인트는 단순한 원시 Markdown이 아니라 스키마에 맞춘 구조화 JSON을 돌려줍니다. 개발자에게는 이것이 하나의 AI 엔진 위에서 API(POST /distill / POST /extract), MCP 서버, CLI(npx @thunderbit/thunderbit-cli)로 노출되며, 10만 명 이상이 사용하는 확장 프로그램을 구동하는 바로 그 엔진입니다.
즉, 둘은 정확히 한 가지에서 겹칩니다. 둘 다 "LLM-ready Markdown"을 내보낼 수 있다는 점입니다. 하지만 입력 도메인은 다릅니다. Thunderbit의 distill은 열린 웹의 URL을 받고, MarkItDown은 로컬 파일을 받습니다. 완전히 대체 가능한 관계는 아니며, 그렇게 말하고 싶지도 않습니다. 현실적인 스택은 둘 다 사용하는 방식입니다. Thunderbit나 Firecrawl 스타일의 서비스로 웹을 가져오고 크롤링한 뒤, PDF·슬라이드·스프레드시트 같은 로컬 문서들은 MarkItDown으로 정규화하는 식입니다. 하나는 네트워크를 다루고, 다른 하나는 파일 서랍을 다룹니다.
장단점
장점
- 깨끗한 HTML에서 본문을 완전하게 회수함(4/4 페이지), 제목 구조와 링크도 충실히 보존
- PDF/DOCX 텍스트 회수율이 높고(arXiv 7/7, Bitcoin 6/6), 유지보수용 Office 테스트 파일에서 조용한 콘텐츠 손실이 없었음
- Office Math 수식을 LaTeX로 보존 — 꽤 실용적인 특화 강점
- 492쪽 PDF와 5만 행 XLSX까지 어떤 규모에서도 크래시 없이 동작
- CLI,
convert(), stdin 파이핑, 선택형 MCP 서버 등 호출이 매우 간단함 - MIT 라이선스, Microsoft가 적극 유지보수 중, 이슈 대응도 괜찮음
단점
- 보일러플레이트를 그대로 가져옴 — Wikipedia에서 최대 12.4%가 공통 UI 줄; 기사 추출기는 아님
- span, 중첩, 셀 내 파이프에 약함(13개 중 2개는 완전 실패, 4개는 너덜너덜), rowspan은 데이터를 조용히 잘못된 열로 밀어 넣을 수 있음
- 스캔/이미지 전용 PDF는 OCR도 없이, 오류도 없이 빈 출력
- PDF 출력에는 제목 구조가 전혀 없음(공개 벤치마크와도 일치)
- 핵심 설치가 161MB이고 그 안에 73MB짜리 ONNX 런타임이 포함됨; 콜드 import 약 3.35초
[all]extra가 Python 3.14에서 조용히 2년 전 0.0.2로 되돌아감
누가 쓰면 좋고, 누가 쓰면 안 되는가
LLM 파이프라인용 Markdown으로 Word, Excel, PowerPoint, 텍스트 레이어 PDF 등 여러 로컬 문서를 한꺼번에 표준화하고 싶고, 구조보다 텍스트 완전성이 더 중요하다면 MarkItDown을 쓰면 됩니다. 배치 작업의 마지막 단계에서 모델에 깔끔한 텍스트를 넘기는 용도라면 빠르고 충실하며 무료입니다.
반대로 다음 중 하나라면 건너뛰거나 다른 도구와 함께 쓰세요. 웹 페이지에서 본문만 필요하다면 readability 또는 Firecrawl 스타일 도구를 쓰는 것이 맞고, PDF의 제목과 표가 원형 그대로 살아 있어야 한다면 Docling이나 Marker 쪽이 맞습니다. 입력에 스캔 문서가 포함되어 OCR이 필요하다면 Azure 백엔드나 아예 다른 도구가 필요합니다. 그리고 처음부터 스크래퍼, 즉 가져오고 크롤링하는 도구를 찾고 있었다면, MarkItDown은 전혀 그게 아닙니다.
제가 스크래퍼식 기준으로 잠정 채점해 본 결과 MarkItDown은 60/100이었는데, 이 낮은 점수는 크롤러용 테스트로 변환기를 평가한 데서 나온 산물입니다. 자기 분야에서는 텍스트 충실도 점수가 높고, 약점은 구조(표, PDF 제목)와 패키징(용량, import, [all] 함정)이지 텍스트 품질이 아닙니다. 이 도구를 있는 그대로, 즉 파일을 Markdown으로 바꾸는 변환기로 평가하면 생산 환경에 넣기 전에 알아야 할 몇 가지 날카로운 모서리는 있지만, 꽤 견고하고 잘 유지보수되는 도구입니다.
자주 묻는 질문
MarkItDown은 웹 스크래퍼인가요?
아니요. 크롤러도 없고, JavaScript 렌더링도 없고, 링크 추적도 없고, 페이지네이션도 없습니다. 이미 가지고 있는 파일과 문서, 즉 PDF, DOCX, XLSX, PPTX, 이미지, HTML을 Markdown으로 변환합니다. 살아 있는 웹 페이지를 가져오고 크롤링해야 한다면 Thunderbit나 Firecrawl 같은 스크래핑 도구가 필요하고, MarkItDown은 그 다음 단계, 즉 가져오거나 로컬에 있는 파일을 깔끔한 Markdown으로 바꾸는 역할입니다.
왜 pip install markitdown[all]은 오래된 버전을 설치하나요?
Python 3.14에서는 [all] extra가 youtube-transcript-api~=1.0.0를 고정하는데, 그 범위의 빌드들은 모두 Python 3.14 미만으로 제한됩니다. resolver가 이 고정을 만족할 수 없어서 조용히 markitdown 0.0.2, 즉 2년 전 릴리스로 되돌아갑니다. 해결책은 버전을 고정하고 extra를 개별 설치하는 것입니다. pip install 'markitdown==0.1.6' 다음에 'markitdown[pdf,docx,pptx,xlsx,xls]==0.1.6'를 추가하세요. 이 문제는 이슈 #2179로 추적 중입니다.
MarkItDown은 스캔 PDF에 OCR을 하나요?
기본 설치에서는 하지 않습니다. PDF 경로가 텍스트 추출 전용이라서 텍스트 레이어가 없는 이미지 전용 PDF는 빈 문자열로 나옵니다. 오류도, 경고도 없습니다. OCR이 필요하면 선택형 Azure Document Intelligence 백엔드나 플러그인을 써야 하며, 이 둘 모두 기본 배포에는 포함되지 않습니다. 이는 오래 추적된 갭입니다(이슈 #1268).
MarkItDown은 표를 얼마나 잘 처리하나요?
내용만 놓고 보면 매우 잘 처리합니다. 제 13개 케이스 테스트에서는 모든 경우에서 표 내용의 100%를 유지했습니다. 구조는 형태에 따라 다릅니다. 단순 표, 넓은 표, 헤더 없는 표, 빈 셀 표는 깔끔한 GFM 그리드로 나오지만, rowspan과 colspan은 너덜너덜해지고(rowspan은 데이터를 조용히 잘못된 열에 넣을 수도 있음), 중첩 표는 쓰레기 행으로 평탄화되며, 셀 내부의 문자 그대로 파이프는 이스케이프되지 않습니다. Markdown의 평면적인 표 형식은 span이나 중첩을 표현할 수 없습니다.
MarkItDown은 큰 문서에도 충분히 빠른가요?
큰 파일에서도 크래시는 없지만, 리소스는 파일 종류별로 예산을 잡아야 합니다. 492쪽 PDF는 페이지별 폼 감지 때문에 약 3.2분(대략 0.39초/페이지)이 걸렸고 CPU 병목이었습니다. 5만 행 스프레드시트는 약 1분 만에 끝났지만 메모리 내에서 큰 Markdown 문자열을 만들기 때문에 RAM이 +374MB 늘었습니다. 큰 PDF는 CPU를 분 단위로, 큰 스프레드시트는 RAM을 수백 MB 단위로 계획하세요.
웹 데이터 추출용 Thunderbit 사용해 보기 Get Started Free


