Files
PDFToMD/docs/ARCHITECTURE.md
T
2026-04-23 10:22:30 +09:00

5.3 KiB

아키텍처

기본 원칙

  • 1차 목표는 UI가 아니라 안정적인 CLI/라이브러리 변환 엔진이다.
  • PDF parser는 Marker를 기본 엔진으로 사용한다.
  • 변환 파이프라인은 Marker 출력에 직접 결합하지 않고 내부 중간 표현(Document Model)을 거친다.
  • 출력은 Obsidian 친화 Markdown을 우선하되, 표준 Markdown과의 호환성을 가능한 한 유지한다.
  • 긴 문서는 20페이지 단위 chunk로 처리하고, chunk별 상태/캐시/로그를 남겨 재시도가 가능해야 한다.

목표 디렉토리 구조

venv/                       # 가상 환경
samples/                    # 품질 검증용 샘플 PDF
src/
├── converter/              # PDF to Markdown 변환 핵심
│   ├── engines/            # Marker 및 향후 parser adapter
│   ├── model/              # 내부 Document Model
│   ├── renderers/          # Obsidian Markdown 출력
│   ├── indexer/            # index 파일 생성
│   └── diagnostics/        # 로그, 경고, 변환 상태
├── ui/                     # 2차 목표: PyQt UI 컴포넌트
└── utils/                  # 유틸리티 + 헬퍼

주요 컴포넌트

Converter Core

  • PDF 입력, 사전 분석, chunk 분할, parser 실행, 중간 표현 생성, 출력 렌더링을 조율한다.
  • UI와 분리되어 CLI와 테스트에서 직접 호출 가능해야 한다.

Parser Engine Adapter

  • 1차 구현은 MarkerEngine만 대상으로 한다.
  • 향후 Nougat, Docling, PyMuPDF 등 다른 엔진을 붙일 수 있도록 adapter 경계를 둔다.
  • parser adapter는 원본 parser 결과와 프로젝트 내부 Document Model 사이의 변환을 담당한다.

Document Model

내부 중간 표현은 최소한 다음 정보를 담아야 한다.

  • document id, title, source path, output slug
  • chunk id, page range, conversion status
  • block id, block type, text/content
  • heading level, paragraph, list, quote, equation, table, figure
  • source page, bbox, confidence, parser metadata
  • image/table asset path
  • warnings/errors

Obsidian Renderer

  • Document Model을 Obsidian 친화 Markdown 파일로 렌더링한다.
  • 수식은 $ ... $, $$ ... $$ 형식을 지킨다.
  • 이미지는 Obsidian 내부 링크 또는 프로젝트에서 정한 표준 이미지 링크 형식으로 연결한다.
  • 복잡한 표는 Markdown table에 억지로 맞추지 않고 HTML table 또는 별도 CSV 링크를 허용한다.

Index Builder

  • 단순 목차가 아니라 AI Agent가 문서 내부로 진입하기 위한 탐색 index를 만든다.
  • heading, 주요 문단, 표, 그림, 수식에 대해 Markdown 파일, heading, line 위치, 원본 page 정보를 연결한다.
  • 가능한 경우 block id와 bbox를 metadata에 보존한다.

Diagnostics & Recovery

  • 변환 설정, Marker 버전, GPU/CPU 사용 여부, 처리 시간, 경고, 실패 chunk를 기록한다.
  • 완료된 chunk는 재사용하고 실패한 chunk만 재시도할 수 있어야 한다.
  • 원본 Marker 결과와 내부 Document Model snapshot은 디버깅 가능한 형태로 보존한다.

프로그램 흐름

PDF 파일 입력
-> 사전 분석: 페이지 수, 텍스트 포함 여부, 스캔 여부, 예상 chunk 수 확인
-> 20페이지 단위 chunk 분할
-> chunk별 Marker 변환
-> Marker 결과를 내부 Document Model로 변환
-> reading order, paragraph stitching, semantic mapping 보정
-> 이미지/표/수식 asset 정리
-> Obsidian 친화 Markdown 렌더링
-> index 파일 생성
-> metadata/log 저장

상태 관리

  • 문서 단위 상태와 chunk 단위 상태를 분리한다.
  • chunk 상태는 pending, running, completed, error, skipped 같은 값으로 관리한다.
  • 변환 중 실패가 발생해도 완료된 chunk 결과는 유지한다.
  • 최종 index는 chunk 결과를 기준으로 재생성 가능해야 한다.

변환 결과 출력 구조

output/
└── document-slug/
    ├── document-slug_index.md
    ├── document-slug_001.md
    ├── document-slug_002.md
    ├── document-slug_003.md
    ├── images/
    │   ├── page-001_fig-001.png
    │   └── page-012_fig-003.png
    ├── tables/
    │   ├── page-005_table-001.csv
    │   └── page-008_table-002.html
    └── metadata/
        ├── document.json
        ├── chunks.json
        ├── parser-output/
        └── conversion.log

Obsidian 출력 규칙

  • 파일명은 Windows와 Obsidian에서 안전한 slug 기반 이름을 사용한다.
  • 원본 PDF 파일명은 metadata에 보존한다.
  • heading은 Obsidian 내부 링크 대상이 될 수 있도록 안정적으로 생성한다.
  • 이미지는 상대 경로 또는 Obsidian 내부 링크 중 프로젝트 표준을 정해 일관되게 사용한다.
  • index 파일은 각 chunk 파일과 주요 heading으로 이동할 수 있어야 한다.
  • 수식은 Obsidian에서 렌더링 가능한 Markdown math 문법을 사용한다.

검증 전략

  • TDD를 기본으로 한다.
  • 전체 Markdown snapshot 비교보다 부분 품질 검증을 우선한다.
  • 샘플 PDF별로 heading 추출, 수식 block 수, 이미지 파일 생성, 표 구조 보존, index 링크 생성, 예외 발생 여부를 확인한다.
  • Windows native, 한글 경로, 긴 파일명, 8GB VRAM 제한을 검증 항목에 포함한다.