python-pptx로 PPT 파싱했더니, 다이어그램은 거의 못 읽고 있었다
RAG 프로젝트에서 PPT 문서를 파싱해야 했습니다. 사내 교육자료, 시스템 구성도 같은 PPT 파일에서 엔티티와 관계를 뽑아서 지식그래프에 넣는 작업이었습니다.
파이썬에서 PPT를 다룰 때 가장 먼저 떠오르는 건 python-pptx입니다. 설치도 간단하고, 슬라이드 텍스트를 뽑는 코드도 몇 줄이면 됩니다. 텍스트 위주 슬라이드에서는 실제로 잘 동작했습니다.
다이어그램 슬라이드에서 엔티티가 1개?
문제는 다이어그램이 들어간 슬라이드에서 터졌습니다.
UAPS 시스템 개요 슬라이드를 python-pptx로 파싱하고, LLM으로 엔티티를 추출했는데 결과가 1개였습니다. 슬라이드를 직접 열어보면 RLDAP, MLDAP, UAPDB, PMH, CRS 같은 인프라 노드가 잔뜩 그려져 있거든요. 눈으로는 다 보이는데, 파서가 거의 못 읽고 있었습니다.
처음엔 LLM 프롬프트 문제인 줄 알았습니다. 그래서 프롬프트를 이리저리 바꿔봤는데, 아무리 바꿔도 결과가 비슷하더라고요. 그제서야 "혹시 파싱 단계에서 이미 텍스트가 빠지고 있는 건 아닌가?" 하고 의심이 갔습니다.
python-pptx는 도형 안 텍스트를 부분적으로만 읽는다
확인해보니 원인은 LLM이 아니라 파싱 단계였습니다.
PPT 파일 구조를 생각하면 이해가 됩니다. PPT 슬라이드에는 텍스트 박스도 있지만, 도형(Shape) 안에 텍스트를 넣는 경우가 많거든요. 시스템 구성도의 서버 이름, 플로우 다이어그램의 단계명 같은 것들이 전부 도형 안에 들어가 있습니다.
python-pptx는 이 도형들의 text_frame을 읽긴 합니다. 하지만 그룹화된 도형, 중첩된 SmartArt, 커넥터에 붙은 라벨 같은 건 빠지는 경우가 많습니다. 즉, 텍스트 위주 슬라이드는 잘 읽는데 다이어그램·구성도 슬라이드에서는 정보의 상당 부분이 누락됩니다.
실제 테스트 결과가 이걸 명확하게 보여줍니다. 동일 PPT(31슬라이드)에서 내용 있는 슬라이드 5개를 뽑아서 비교했습니다.
슬라이드 유형 | python-pptx | OpenDataLoader |
|---|---|---|
텍스트 위주 | 엔티티 10개 | 엔티티 10개 (동일) |
다이어그램 | 엔티티 1개 | 엔티티 16개 + 관계 15개 |
시스템 구성도 | 엔티티 4개 | 엔티티 23개 + 관계 37개 |
텍스트 위주 슬라이드에서는 차이가 없습니다. 그런데 다이어그램에서 16배, 구성도에서 6배 차이가 납니다. 프롬프트 문제가 아니라 입력 자체가 빈약했던 겁니다.

OpenDataLoader — PDF로 돌아가는 우회 전략
OpenDataLoader(ODL)는 한컴에서 만든 오픈소스 PDF 파서입니다. 이름에서 알 수 있듯이 PDF 전용이라, PPT를 직접 읽지는 못합니다.
그래서 파이프라인이 한 단계 늘어납니다. PPT를 먼저 LibreOffice로 PDF 변환하고, 그 PDF를 OpenDataLoader로 파싱합니다. 얼핏 보면 번거롭지만, 이 우회가 효과적인 이유가 있습니다.
LibreOffice가 PPT를 PDF로 변환할 때, 도형 안에 들어있던 텍스트가 PDF에 그대로 보존됩니다. python-pptx가 프로그래밍적으로 접근하지 못했던 텍스트들이 PDF에는 렌더링된 상태로 남아 있는 거죠. ODL은 여기에 XY-Cut++ 알고리즘을 적용해서 읽기 순서까지 복원하며 텍스트를 추출합니다.
전체 추출량을 비교하면 이렇습니다.
항목 | python-pptx | OpenDataLoader |
|---|---|---|
총 추출 문자 수 | 16,462자 | 31,519자 (1.9배) |
추출 엔티티 | 39개 | 77개 (2.0배) |
추출 관계 | 32개 | 78개 (2.4배) |
소요 시간 | 0.09초 | 9.6초 |
출력 형식 | 플레인 텍스트 | Markdown |
시간은 9.6초로 느린 편이지만, 배치 처리 기준으로는 충분히 감수할 수 있는 수준입니다. 엔티티가 2배, 관계가 2.4배 늘어나는 품질 차이를 생각하면 트레이드오프가 명확합니다.
도입 전에 알아둘 것
ODL을 도입하면서 몇 가지 주의할 점이 있었습니다.
첫째, Java 11 이상이 필요합니다. 파이썬 프로젝트인데 Java 의존성이 생기는 게 좀 걸리더라고요. pip install opendataloader-pdf로 파이썬 래퍼를 설치할 수 있지만, Java 자체는 시스템에 별도로 깔아서 PATH에 잡아줘야 합니다. Java 코드를 직접 작성할 일은 없지만, 환경 세팅에서 한 단계 더 필요한 셈입니다.
둘째, LibreOffice를 서버에 설치해야 합니다. PDF 변환을 LibreOffice 헤드리스 모드로 돌리기 때문에, 배포 환경에 LibreOffice가 깔려 있어야 합니다. Docker 이미지에 포함시키면 해결되긴 하지만 이미지 사이즈가 커집니다.
셋째, 텍스트 위주 슬라이드에서는 차이가 없습니다. 위 테스트에서도 봤듯이, 도형이 거의 없는 슬라이드는 python-pptx로 충분합니다. 모든 PPT를 ODL로 돌릴 필요는 없고, 다이어그램·구성도가 핵심인 문서에 집중하는 게 효율적입니다.
마무리
PPT 파싱에서 결과가 빈약한 원인이 LLM이나 프롬프트가 아니라 파서 자체에 있을 수 있습니다. 특히 다이어그램·구성도가 많은 PPT라면 python-pptx의 추출량이 눈에 띄게 떨어집니다.
이 프로젝트에서는 PPT → LibreOffice PDF 변환 → OpenDataLoader 파싱으로 파이프라인을 바꿨고, 엔티티 추출량이 2배로 올라갔습니다. 파싱 단계에서 정보가 빠지면 그 뒤에 아무리 좋은 LLM을 붙여도 소용없습니다.
PPT 파싱 품질이 의심될 때는 입력 데이터를 확인해보는 걸 추천합니다.