레거시 DOC, XLS, PPT를 OOXML로 변환하기
Office Oxide는 Word 97–2003(.doc), Excel 97–2003(.xls), PowerPoint 97–2003(.ppt)을 읽고 그리고 대응하는 최신 OOXML 형식을 쓸 수 있는 유일한 Rust/Python 라이브러리입니다. JVM(Apache Tika)도, 외부 변환기(LibreOffice headless)도, 상용 라이선스(Aspose)도 필요 없습니다.
save_as 하나로 변환이 끝납니다. 레거시 파일을 열고 최신 확장자로 저장하면, Office Oxide가 IR을 거쳐 새 OOXML 컨테이너를 작성합니다.
한 줄로 끝내기
Rust
use office_oxide::Document;
Document::open("old.doc")?.save_as("modern.docx")?;
Document::open("old.xls")?.save_as("modern.xlsx")?;
Document::open("old.ppt")?.save_as("modern.pptx")?;
Python
from office_oxide import Document
with Document.open("old.doc") as doc:
doc.save_as("modern.docx")
with Document.open("old.xls") as doc:
doc.save_as("modern.xlsx")
with Document.open("old.ppt") as doc:
doc.save_as("modern.pptx")
JavaScript
import { Document } from 'office-oxide';
using doc = Document.open('old.xls');
doc.saveAs('modern.xlsx');
Go
doc, _ := officeoxide.Open("old.xls")
defer doc.Close()
doc.SaveAs("modern.xlsx")
C#
using var doc = Document.Open("old.xls");
doc.SaveAs("modern.xlsx");
C
int err = 0;
OfficeDocumentHandle *doc = office_document_open("old.xls", &err);
if (!doc) { fprintf(stderr, "open failed: code=%d\n", err); return 1; }
/* target format inferred from the extension; legacy -> OOXML converts transparently */
if (office_document_save_as(doc, "modern.xlsx", &err) != 0) {
fprintf(stderr, "save_as failed: code=%d\n", err);
}
office_document_free(doc);
대량 마이그레이션
파일 컬렉션 전체를 한 줄로 마이그레이션합니다.
Rust
use office_oxide::Document;
use std::path::Path;
fn migrate(src: &Path, dst: &Path) -> office_oxide::Result<()> {
Document::open(src)?.save_as(dst)?;
Ok(())
}
Python
from pathlib import Path
from office_oxide import Document
for src in Path("legacy").rglob("*"):
if src.suffix.lower() in {".doc", ".xls", ".ppt"}:
new_ext = {".doc": ".docx", ".xls": ".xlsx", ".ppt": ".pptx"}[src.suffix.lower()]
dst = Path("modern") / src.relative_to("legacy").with_suffix(new_ext)
dst.parent.mkdir(parents=True, exist_ok=True)
with Document.open(src) as doc:
doc.save_as(dst)
print(f"{src} → {dst}")
C
/* migrate one file: open from path, save_as routes by the dst extension */
int migrate(const char *src, const char *dst) {
int err = 0;
OfficeDocumentHandle *doc = office_document_open(src, &err);
if (!doc) return err;
int rc = office_document_save_as(doc, dst, &err);
office_document_free(doc);
return rc == 0 ? 0 : err;
}
대규모 파일 컬렉션을 병렬로 처리하려면 루프를 rayon으로 감싸세요.
Shell — CLI 사용
find legacy/ -iname '*.doc' | parallel \
'office-oxide convert {} modern/{/.}.docx'
find legacy/ -iname '*.xls' | parallel \
'office-oxide convert {} modern/{/.}.xlsx'
find legacy/ -iname '*.ppt' | parallel \
'office-oxide convert {} modern/{/.}.pptx'
변환 후 보존되는 내용
Office Oxide는 콘텐츠 구조인 단락, 표, 셀, 슬라이드, 목록, 제목과 그 안의 값을 보존합니다. 레거시 형식이 IR이 모델링하지 않는 독자적인 구조로 인코딩하기 때문에 일부 항목은 변환되지 않습니다.
| 항목 | 보존 여부 | 비고 |
|---|---|---|
| 단락 텍스트 | ✓ | 굵게/기울임꼴/밑줄 서식 포함 |
| 목록 | ✓ | 순서 있음 + 순서 없음 |
| 표 | ✓ | 셀, 행 순서, 헤더 행 |
| XLSX 셀 값(string, number, bool) | ✓ | — |
| 시트 이름 | ✓ | — |
| 슬라이드 제목 + 본문 | ✓ | — |
| 하이퍼링크 | ✓ | — |
| 이미지 | 일부 | DOC/PPT는 인라인 이미지 보존, XLS 이미지 앵커는 손실 |
| 댓글 / 수정 이력 | — | 변경 내용 추적은 평탄화됨 |
| 수식(XLS) | 값만 | 캐시된 수식 결과는 보존, 수식 표현식은 보존되지 않음 |
| WordArt, SmartArt, 차트 | — | 필요하면 대상 형식에서 다시 작성 |
| 암호화 | — | 레거시 파일을 먼저 복호화하세요(예: LibreOffice 사용) |
LLM, 인덱싱, 아카이빙 용도에서는 콘텐츠 수준의 충실도가 핵심입니다. Office Oxide는 밀리초 단위로 완전히 편집 가능한 DOCX/XLSX/PPTX를 반환합니다.
성능
파일당 변환 속도는 텍스트 추출과 같은 수준입니다. 일반적인 Word 97 .doc 파일이라면 엔드투엔드 기준으로 한 자리 수 밀리초를 예상할 수 있습니다.
참고 문서
- 성능 벤치마크 — DOC/XLS/PPT 추출 수치
- IR로 빌드하기 —
save_as의 내부 동작 - python-docx에서 마이그레이션 — 단일 형식 Python 라이브러리에서 전환하기