HWP 읽기 · 표 안 글자를 잃지 마라
품앗이가 AI와 함께 일하며 남긴 기록을 다른 조직이 다시 쓸 수 있게 옮긴 글입니다. 묶음 전체와 도구를 만든 사람들은 한글 문서를 AI로 다루기에서 볼 수 있습니다.
요지
한글 문서를 AI에게 읽힐 때 가장 많이 잃는 것은 표 안 글자입니다. 지원사업 신청서, 실적표, 검사 결과지처럼 중요한 숫자와 이름이 표 안에 있는 문서는 흔한 텍스트 추출로는 거의 빈 껍데기가 됩니다. 그래서 먼저 버전을 보고, 표를 살리는 경로를 고르고, 그래도 안 되면 문서를 그림으로 렌더해 읽는 것이 우리 기록이 남긴 순서입니다.
1. 먼저 버전부터 본다
같은 「.hwp」라도 판에 따라 속 구조가 다릅니다. 우리 기록에 따르면 한 교육 단체 자료실에서 내려받은 한글 파일 22개가 전부 3.0 판이었고, 파이썬 라이브러리와 오피스 변환기 모두 열지 못했습니다. 3.0은 자체 바이너리 형식이라 지금 쓸 수 있는 파이썬 라이브러리가 없었습니다. 5.0 이상은 OLE라는 묶음 구조라서 읽히고, HWPX는 압축 파일 안에 XML이 든 구조입니다.
버전은 파일 형식을 알려 주는 명령 한 줄로 확인됩니다. 3.0이면 그 자리에서 「이 파일은 읽을 수 없다」고 말하고, 한글 프로그램에서 HWPX나 PDF로 다시 저장해 달라고 부탁합니다. 되는 척하고 내용 없는 정리본을 만드는 것이 가장 나쁜 선택이라고 품앗이는 봅니다.
2. 텍스트 추출은 표 안을 버린다
pyhwp에 들어 있는 hwp5txt는 표를 「표」라는 표시 하나로만 남기고 셀 안 글자는 버립니다. 기록에 따르면 한 융자 신청서를 읽을 때 재무와 실적 숫자가 전부 표 안에 있어서 이 명령으로는 다 사라졌습니다.
표 안까지 읽으려면 두 갈래가 있습니다. hwp5html은 표를 HTML 표로 살려 내고, hwp5odt는 오픈 문서 형식의 본문 XML에 표 안 글자까지 담아 냅니다. 다만 pyhwp 판에 따라 hwp5html이 빠져 있기도 해서, 표 양식 문서 수천 건을 읽은 한 작업에서는 hwp5odt를 썼습니다.
같은 함정에 두 번 빠진 기록도 있습니다. hwp5txt가 표를 버린다는 사실이 이미 적혀 있었는데, 그 기록을 읽지 않고 다시 hwp5txt부터 시험했습니다. 한글 문서를 받으면 이 노드의 2절을 먼저 떠올리는 것이 시간을 가장 아낍니다.
뽑아 낸 글자의 순서는 화면 순서가 아닙니다. 한 검사 결과지 양식을 오픈 문서 형식으로 뽑아 보니 소견 칸이 성명, 생년월일, 주소 칸보다 앞에 나왔습니다. 그래서 「이 표식 뒤만 남기면 이름이 빠진다」는 식으로 가명 처리를 하면 이름이 그대로 남습니다. 규칙을 세우기 전에 이름과 숫자를 모두 가린 채 구조부터 보는 것이 그 기록의 처방입니다.
3. 표가 본질인 문서는 렌더해서 읽는다
정책과제집처럼 사업 내용과 추진 일정이 표로만 적힌 문서는 텍스트 추출로는 읽히지 않습니다. 기록에 따르면 hwp5txt는 표를 버렸고, rhwp의 본문 덤프도 표 셀은 내주지 않고 긴 문단은 말줄임표로 잘랐습니다.
이때는 rhwp로 쪽마다 SVG 그림을 만들고, 그 SVG를 PNG로 바꾼 다음, 그림을 읽을 수 있는 AI에게 보여 줍니다. 그렇게 하자 표와 배치까지 정확히 읽혔습니다. SVG 파일 안의 글자를 직접 검색하면 글자가 한 자씩 따로 적혀 있어 순서가 깨지니, 그림으로 바꿔 보는 단계를 건너뛰지 않습니다.
4. 표준 도구가 죽으면 다음 도구로
한 사업계획서 작업에서는 같은 HWP 파일에서 hwp5txt와 hwplib가 둘 다 예외를 내고 멈췄습니다. 도구 하나의 실패는 막다른 길이 아니라는 것이 그 기록의 결론입니다. 그날 쓴 순서는 이렇습니다.
- rhwp로 본문을 덤프한다. 한컴 오피스에 가까운 정확도지만 긴 문단은 말줄임표로 잘릴 수 있다.
- 그래도 모자라면 HWP 묶음 파일에서 본문 스트림을 직접 읽는다. 압축돼 있으면 풀고, 기록 단위를 순서대로 훑어 본문 글자 기록만 모은다. 글자는 UTF-16LE로 저장돼 있다.
오피스 변환기도 믿고 넘어가지 않습니다. 우리 기록에는 서버의 오피스 프로그램에 한글 필터가 깔려 있지 않아 HWP와 HWPX 변환이 출력 파일도 없이 실패한 일이 있고, 설치 자체가 깨져 한 줄짜리 워드 문서조차 열지 못한 일도 있습니다. 한 줄짜리 시험 문서를 넣어 보면 파일 문제인지 환경 문제인지 바로 갈립니다. 「오피스가 깔려 있으니 되겠지」는 확인이 아닙니다.
5. 이미지 PDF와 2단 PDF
PDF에서 글자를 뽑았는데 거의 0자가 나오면 그 PDF는 글자 대신 그림으로 된 슬라이드입니다. 기록에 남은 한 강연 자료는 31쪽에서 4,391자밖에 나오지 않았습니다. 이럴 때는 쪽을 그림으로 렌더해 AI의 시각 판독으로 읽습니다. 표, 그래프, 계통도, 한글이 다 읽혔습니다.
그림을 읽는 AI는 숫자를 잘못 읽을 수 있습니다. 그래서 숫자가 빽빽한 표가 있는 쪽은 그 쪽 하나만 따로 다시 읽혀 앞의 결과와 대조한 뒤 확정합니다. 읽어 낸 결과는 세 가지로 남겼습니다. 표와 숫자는 구조화된 데이터 파일로, 본문은 출처를 밝힌 위키 노드로, 원인과 결과의 관계는 온톨로지로 남겨 검색과 추론 양쪽에서 쓸 수 있게 했습니다.
한글로 된 2단 PDF는 배치를 살리는 추출 방식으로 뽑으면 왼쪽 단과 오른쪽 단을 한 줄로 이어 붙여 문장 순서가 깨집니다. 읽는 순서를 따르는 방식으로 뽑고 문단을 다시 붙입니다. 양끝 맞춤 때문에 줄바꿈이 낱말 가운데서 일어나기도 하는데, 기록에 남은 규칙은 이렇습니다. 줄 끝에 한 음절만 남은 낱말은 다음 줄과 붙이고, 줄 첫머리에 조사 한 음절이 넘어왔으면 앞 줄과 붙입니다. 「할 수」처럼 원래 띄어 쓰는 말은 건드리지 않습니다.
6. 원본을 파싱하기 전에 정리본부터
사람이 손으로 다루던 문서 폴더에는 그 사람이 만든 엑셀 현황표가 거의 늘 있습니다. 한 의료복지사협 폴더를 DB로 옮길 때 HWP 파서부터 만들었는데, 같은 폴더 맨 아래 엑셀에 담당 직원이 정리해 둔 명단이 이미 있었습니다. 원본을 파싱하는 일은 그 정리본을 검산하는 데 쓰는 편이 맞다고 우리 기록은 적고 있습니다. 이 사례는 현장 데이터를 꺼내고 옮길 때 1절에 자세히 있습니다.
처방 정리
- 한글 파일을 받으면 버전부터 본다. 3.0이면 다시 저장해 달라고 바로 말한다.
- 표 안에 중요한 내용이 있으면 hwp5txt를 쓰지 않는다. hwp5html이나 hwp5odt로 뽑는다.
- 표가 본질인 문서는 rhwp로 그림을 만들어 읽는다.
- 도구가 실패하면 다음 도구로 넘어가고, 오피스 변환기는 한 줄짜리 시험 문서로 먼저 살아 있는지 본다.
- 그림을 읽은 숫자는 그 쪽만 다시 읽혀 대조한다.
- 폴더를 받으면 엑셀 현황표부터 연다.
도구 메모
- 버전 확인: 파일 형식을 알려 주는
file명령에 한글 파일을 넣으면 판 번호가 나온다. - 표까지 뽑기:
hwp5html --html --output 출력.html 원본.hwp, 또는hwp5odt 원본.hwp --output 출력.odt를 한 뒤 압축을 풀어 content.xml을 읽는다. - pyhwp 설치 이름은 pyhwp이고 파이썬에서 부르는 이름은 hwp5다. 판에 따라 six, olefile, lxml을 따로 설치해야 돈다.
- 렌더해서 읽기:
rhwp export-svg 원본.hwp -o 폴더 --embed-fonts다음에rsvg-convert -w 1400 쪽.svg -o 쪽.png를 하고 PNG를 AI에게 보여 준다. - PDF 판별:
pdftotext 파일 - | wc -c가 거의 0이면 그림 PDF다. 2단 PDF는pdftotext -raw로 뽑는다.