# 아키텍처 ## 기본 원칙 - 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 제한을 검증 항목에 포함한다.