"쓸 만한 변환기가 하나도 없다."
HWP 변환? 유료 아니면 반쪽짜리. PDF 변환? 광고 도배 사이트뿐. 다중 파일 일괄 변환? 그런 건 존재하지 않았다. 찾다, 찾다, 빡쳐서 직접 만들었다. 발로.
nothing — 쓸 만한 게 아무것도 없으니까. 2md — 그래서 직접 Markdown으로 만든다.
이 프로젝트는 발로 하는 바이브 코딩으로 만들어졌다. 비유가 아니다. 개발자는 실제로 발로 마우스를 조작하며 AI와 대화하고, 코드를 리뷰하고, 빌드를 돌린다. 손이 자유롭지 않아도 코딩은 멈출 수 없으니까. 빡침은 신체적 한계도 뛰어넘는다.
세상에는 수많은 문서 변환 도구가 있지만, 막상 쓰려고 하면 하나같이 빡치는 요소 투성이다:
- HWP/HWPX: 한국에서 가장 많이 쓰이는 포맷인데, 제대로 된 오픈소스 변환기가 없다
- PDF 변환 사이트: 검색하면 전부 광고 폭탄, 파일 크기 제한, 회원가입 강요
- 다중 파일 변환: 폴더 안의 수십 개 파일을 한 번에? 그런 도구는 없었다
- 스캔된 PDF: 이미지로만 된 PDF는 텍스트 추출 자체가 안 되는 도구가 대부분
- LLM 활용: RAG 시스템에 넣으려면 깨끗한 Markdown이 필요한데, 기존 도구의 출력은 쓰레기
n2md는 이 모든 불만을 하나의 도구로 해결한다.
| 카테고리 | 확장자 | 변환 엔진 | 비고 |
|---|---|---|---|
| 한글 | .hwp, .hwpx |
n2md Pure Engine | 외부 의존성 없이 바이너리 직접 파싱 |
.pdf |
PyMuPDF4LLM + Tesseract OCR | 텍스트 PDF는 구조 보존, 스캔 PDF는 OCR 자동 fallback | |
| Office | .docx, .pptx |
Mammoth, python-pptx | 제목/목록 등 의미 구조 중심 변환 |
| Data | .xlsx, .xls, .csv |
Pandas + tabulate | Markdown 표 자동 생성 |
| Ebook | .epub |
EbookLib | 챕터 구조 보존 |
| Web | .html, .htm, URL |
BeautifulSoup4 + markdownify | 불필요 태그 제거, 본문 자동 추출 |
| Image | .png, .jpg, .jpeg, .bmp, .tiff |
Tesseract OCR | CJK(한/중/일) 자동 감지 |
| 기타 | .odt, .rtf |
odfpy, striprtf | ODF 및 RTF 문서 지원 |
- HWP 5.0+ 순수 파이썬 파싱 —
olefile+zlib로 바이너리를 직접 디코딩. 한컴오피스 설치 불필요 - 스캔 PDF OCR 자동 감지 — 텍스트가 거의 없는 PDF를 자동 판별하여 페이지별 300 DPI OCR 수행
- CJK 언어 자동 감지 — 설치된 Tesseract 언어팩을 자동 탐지하여 한국어/중국어/일본어 OCR 지원
- GUI 드래그 앤 드롭 — 파일이든 폴더든 끌어다 놓으면 끝. 파일을 놓으면 상위 폴더 자동 추가
- 폴더 일괄 변환 — 수백 개 파일도 한 번에. 확장자 필터, 하위 폴더 재귀 탐색, 폴더 구조 보존
- LLM/RAG 최적화 출력 —
pymupdf4llm기반으로 대형 언어 모델이 이해하기 좋은 구조의 Markdown 생성 - LLM Polishing — Gemini API를 통한 변환 결과 후처리 (CLI:
--model옵션) - 시스템 테마 자동 감지 — Windows/Linux 다크/라이트 모드 자동 적용
git clone https://github.com/your-repo/n2md.git
cd n2md
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt이미지 변환 및 스캔 PDF OCR을 사용하려면 Tesseract 설치가 필요하다.
# Ubuntu
sudo apt-get install tesseract-ocr tesseract-ocr-kor
# macOS
brew install tesseract tesseract-lang
# Windows — UB Mannheim 인스톨러 사용
# https://github.com/UB-Mannheim/tesseract/wikiCJK 언어팩은 ~/tessdata/ 디렉토리에 .traineddata 파일을 넣으면 자동 인식된다.
python gui.py- 단일 파일 탭: 파일을 드래그 앤 드롭하거나 추가 버튼으로 선택
- 폴더 일괄 탭: 폴더 단위로 변환. 확장자 필터링, 하위 폴더 탐색 지원
- 파일을 폴더 탭에 드롭하면 상위 폴더가 자동으로 추가됨
# 기본 변환
python main.py convert document.pdf
# 출력 경로 지정
python main.py convert report.hwp --output result.md
# 웹페이지 변환
python main.py convert https://example.com --output page.md
# LLM 폴리싱 적용
python main.py convert scan.pdf --model gemini-1.5-flash이 프로젝트는 "쓸 만한 게 없다" 는 분노에서 시작했다. 그리고 그 분노는 발끝에서 코드가 되었다 — 문자 그대로.
-
HWP의 벽 — 한글 파일을 Markdown으로 바꾸고 싶었다. 검색하면 나오는 건 유료 서비스, 반쪽짜리 라이브러리, 아니면 한컴오피스를 설치해야 하는 도구뿐이었다. 결국
olefile로 HWP 5.0 바이너리 스펙을 직접 파싱하는 엔진을 만들었다. -
PDF 광고 지옥 — PDF를 텍스트로 바꾸려고 검색하면, 상위 결과는 전부 광고로 도배된 온라인 변환 사이트였다. 파일 크기 제한, 회원가입, 워터마크...
pymupdf4llm을 발견하고 나서야 제대로 된 변환이 가능해졌다. -
다중 파일의 부재 — 폴더 안에 HWP 30개, PDF 50개가 있는데 하나씩 변환하라고? 일괄 변환을 지원하는 무료 도구는 찾을 수 없었다. 드래그 앤 드롭으로 폴더를 던지면 알아서 처리하는 GUI를 직접 만들었다.
-
스캔 PDF의 함정 — 텍스트 PDF는 해결했는데, 스캔된 문서는 이미지만 들어있어서 텍스트 추출이 안 됐다. Tesseract OCR을 연동하여 텍스트가 부족한 PDF를 자동으로 감지하고 페이지별 OCR fallback을 구현했다.
-
CJK 언어 장벽 — OCR을 넣었더니 한국어가 깨졌다. Tesseract에 한국어/중국어/일본어 언어팩을 설치하고, 설치된 언어를 자동 감지하여 모두 활용하는 로직을 추가했다.
결국 "없으니까 만든다" — 이것이 n2md의 이름이자 존재 이유다. 손이 안 되면 발로. 발도 안 되면 AI한테 시키면 된다. 멈출 이유가 없다.
| 영역 | 기술 |
|---|---|
| CLI | Typer + Rich |
| GUI | customtkinter + tkinterdnd2 |
| HWP 파싱 | olefile + zlib (순수 파이썬) |
| PyMuPDF + PyMuPDF4LLM | |
| OCR | Tesseract + pytesseract + Pillow |
| Office | Mammoth (DOCX), python-pptx (PPTX) |
| Data | Pandas + tabulate |
| Web | BeautifulSoup4 + markdownify |
| LLM | Google Generative AI (Gemini) |
# 전체 테스트
python -m pytest tests/ -v
# 커버리지 포함
python -m pytest tests/ --cov=. --cov-report=htmltests/
├── conftest.py # 공통 fixtures
├── test_cli.py # CLI 명령어 및 포맷 감지 테스트
├── test_converters.py # 개별 컨버터 단위 테스트
├── test_runner.py # 전체 포맷 통합 테스트
└── generate_samples.py # 테스트용 샘플 파일 생성
MIT License
일부 의존 라이브러리는 AGPL 라이선스 (pyhwp, pymupdf, ebooklib)를 따른다. n2md 자체는 MIT이며, 오픈소스 배포 시 AGPL 의존성의 소스 공개 의무가 적용된다.
Developed by Gi-hyeon (Father of Young-mi) Built with feet, fury, and vibe coding.