포맷 확장 가이드¶
대상 독자
이 문서는 라이브러리에 직접 기여하여 새 포맷을 추가하려는 개발자를 위한 가이드예요.
새 Parser 추가하기¶
새 입력 포맷을 지원하려면 세 단계가 필요해요.
1. 파서 클래스 작성¶
src/ureca_document_parser/ 아래에 새 디렉토리를 만들고 파서를 구현하세요. Parser Protocol의 두 메서드만 맞추면 돼요.
extensions()— 지원하는 파일 확장자 리스트를 반환parse(filepath)— 파일을 파싱해서Document를 반환
from ureca_document_parser.models import Document, Metadata, Paragraph
class PdfParser:
@staticmethod
def extensions() -> list[str]:
return [".pdf"]
@staticmethod
def parse(filepath):
import pymupdf # 선택적 의존성은 함수 안에서 import
doc = Document(metadata=Metadata(source_format="pdf"))
pdf = pymupdf.open(str(filepath))
for page in pdf:
text = page.get_text().strip()
if text:
doc.elements.append(Paragraph(text=text))
return doc
핵심 규칙:
- 반드시
Document를 반환해야 해요 - 선택적 의존성은 함수 내부에서 lazy import해야 해요
- 상속은 필요 없어요 — 메서드 시그니처만 맞으면 Protocol과 호환돼요
2. 레지스트리에 등록¶
registry.py의 _auto_register() 함수에 추가하세요. try/except ImportError로 감싸서 의존성이 없을 때도 안전하게 동작하도록 해요.
def _auto_register(registry: FormatRegistry) -> None:
# ... 기존 파서들 ...
try:
from .pdf import PdfParser
registry.register_parser(PdfParser)
except ImportError:
pass
3. optional dependency 추가 (선택)¶
외부 라이브러리가 필요하다면 pyproject.toml에 추가하세요.
확인¶
등록이 완료되면 CLI와 Python API에서 자동으로 사용할 수 있어요.
새 Writer 추가하기¶
새 출력 포맷을 지원하려는 경우에도 비슷한 흐름이에요. Writer Protocol의 세 메서드를 구현하면 돼요.
format_name()— 포맷 이름을 반환 (예:"html")file_extension()— 파일 확장자를 반환 (예:".html")write(doc)—Document를 받아 출력 문자열을 반환
from ureca_document_parser.models import Document, Paragraph
class HtmlWriter:
@staticmethod
def format_name() -> str:
return "html"
@staticmethod
def file_extension() -> str:
return ".html"
@staticmethod
def write(doc: Document) -> str:
parts = []
for element in doc.elements:
if isinstance(element, Paragraph):
if element.heading_level > 0:
tag = f"h{element.heading_level}"
parts.append(f"<{tag}>{element.text}</{tag}>")
else:
parts.append(f"<p>{element.text}</p>")
return "\n".join(parts)
레지스트리 등록 방법은 Parser와 동일해요.
# registry.py의 _auto_register()
from .writers.html import HtmlWriter
registry.register_writer(HtmlWriter)
등록 후 CLI에서 -f 옵션으로 사용할 수 있어요.
체크리스트¶
새 포맷을 추가할 때 다음 사항을 확인하세요.
- [ ] Protocol 시그니처와 호환되는 클래스를 작성했나요?
- [ ]
Document모델만 사용해서 입출력하나요? - [ ]
_auto_register()에try/except ImportError로 등록했나요? - [ ] 선택적 의존성을
pyproject.toml에 추가했나요? - [ ] lazy import를 사용하고 있나요?
- [ ] 테스트 케이스를 작성했나요? (
tests/디렉토리) - [ ] docstring을 작성했나요? (Google 스타일)
테스트 작성¶
새 파서나 Writer를 추가하면 반드시 테스트를 작성하세요.
파서 테스트 예시¶
# tests/test_pdf_parser.py
from pathlib import Path
from ureca_document_parser.pdf import PdfParser
from ureca_document_parser import Paragraph
def test_pdf_parser():
parser = PdfParser()
doc = parser.parse("tests/fixtures/sample.pdf")
assert doc.metadata.source_format == "pdf"
assert len(doc.elements) > 0
assert isinstance(doc.elements[0], Paragraph)
Writer 테스트 예시¶
# tests/test_html_writer.py
from ureca_document_parser import Document, Paragraph
from ureca_document_parser.writers.html import HtmlWriter
def test_html_writer():
doc = Document(elements=[
Paragraph(text="제목", heading_level=1),
Paragraph(text="본문"),
])
writer = HtmlWriter()
html = writer.write(doc)
assert "<h1>제목</h1>" in html
assert "<p>본문</p>" in html
문서 업데이트¶
새 포맷을 추가하면 다음 문서를 업데이트하세요.
docs/index.md— 지원 포맷 테이블에 추가docs/formats/<format>.md— 새 포맷 가이드 페이지 작성 (HWP/HWPX 참고)mkdocs.yml— 네비게이션에 추가
기여 워크플로¶
- 이슈 생성 — 추가하려는 포맷에 대한 이슈를 먼저 생성하세요
- 브랜치 생성 —
feature/add-<format>-parser형식으로 브랜치 생성 - 구현 — 파서/Writer 구현 + 테스트 작성
- 문서 업데이트 — 위 섹션 참고
- PR 생성 — 메인 브랜치로 Pull Request 생성
- 리뷰 — CI 통과 및 코드 리뷰 진행