실습 노트
AI는 왜 HWP 양식을 망가뜨릴까: kordoc 실패 기록과 성공 조건
채용 공고 HWPX의 서식 4종을 AI로 채우면서 세 번 실패한 기록입니다. 같은 도구(kordoc)로 실패와 성공을 가른 조건을 정리하고, 그 절차를 스킬(SKILL.md)로 박제해 다음부터는 저렴한 모델도 재현하게 만든 과정까지 담았습니다.
대학 채용 공고 HWPX 파일 하나로 실험을 했습니다. 공고 본문(채용 개요, 지원자격, 전형 일정 같은 안내문)은 전부 지우고, 뒤에 붙은 서식 4종(응시원서·이력서·자기소개서·개인정보 동의서)만 남긴 뒤 가상의 지원자 데이터를 채우는 작업입니다. 공공기관 문서 업무에서 흔한 패턴이라, AI 에이전트에게 시키면 어디서 막히는지 직접 확인해보고 싶었습니다.
도구는 kordoc1을 썼습니다. HWP·HWPX2를 Markdown으로 파싱하고, 양식 채우기와 서식 보존 패치까지 지원하는 오픈소스입니다. 결론부터 말하면 도구는 문제가 아니었습니다. 같은 도구로 세 번 실패했고, 조건을 바꾸니 성공했습니다. 실패 원인이 전부 도구의 설계를 이해하지 못한 제 쪽에 있었다는 점이 이 글의 요지입니다. 그리고 그 시행착오를 다시 겪지 않으려고 절차 전체를 스킬(Skill)3 문서로 박제했습니다.
(1) kordoc — HWP 3.x/5.x, HWPX, PDF, Office 문서를 Markdown으로 파싱하는 오픈소스 CLI + MCP 서버. 양식 채우기, 서식 보존 패치, 공문서 생성 기능을 함께 제공합니다. MIT License, Copyright (c) 2026 chrisryugj. GitHub 저장소 →
(2) HWPX — 한글 문서의 개방형 포맷. 실체는 ZIP 압축 안에 XML 파일들이 들어 있는 구조라서, 압축을 풀면 텍스트 편집기로 내용을 직접 다룰 수 있습니다. 반면 구형 .hwp(5.x)는 바이너리 포맷이라 같은 접근이 어렵습니다.
(3) 스킬(Skill) — Claude Code 같은 AI 에이전트에게 특정 작업의 절차·규칙을 문서(SKILL.md)로 미리 넘겨주는 방식입니다. 에이전트가 매번 시행착오를 반복하는 대신 검증된 절차를 따르게 됩니다.
실패 1: 자동 양식 인식(fill)은 문서를 가렸다
kordoc에는 라벨을 인식해 빈칸을 채우는 fill 명령이 있습니다. 먼저 이걸 시도했습니다.
kordoc fill "공고.hwpx" --dry-run
dry-run이 알려준 인식 신뢰도가 0.48이었습니다. 병합 셀이 많은 공고문 표에서 라벨과 값이 한 칸씩 밀려 매칭됐고("성명" 라벨의 값이 "(한글)"로 잡히는 식), 결정적으로 같은 라벨이 여러 표에 반복되는 구조를 처리하지 못했습니다. 이 공고의 응시원서는 정본·부본·응시표 3장이 같은 필드 구조로 반복되는데, fill은 항상 같은 한 곳만 채웠습니다. 배열로 값을 넘기는 방법도 시도했지만 에러가 났습니다.
실패 2: 문서를 새로 생성(generate)하니 양식이 무너졌다
방향을 바꿔서, 파싱한 Markdown을 편집한 뒤 generate 명령으로 새 HWPX를 만들었습니다. 내용은 전부 맞게 들어갔습니다. 다만 결과물을 열어보니 원본 공고문 특유의 표 스타일(셀 배경, 테두리 두께, 열 너비)이 전부 사라져 있었습니다. generate는 이름 그대로 문서를 처음부터 새로 그리는 명령이라, 기존 양식을 "다시 만드는" 용도로 쓰면 안 되는 것이었습니다. 라이브러리 쪽에는 원본 표 서식을 추출해 입히는 기능도 있지만, 행과 열 수가 원본과 다르면 매칭에서 제외되어 부분적으로만 통했습니다.
실패 3: 서식 보존 패치(patch)도 처음엔 대부분 거부됐다
kordoc의 patch는 편집된 Markdown을 원본과 비교해 달라진 텍스트만 원본 파일 안에서 바꾸는 명령입니다. 원본 서식을 건드리지 않는 방식이라 이게 정답처럼 보였는데, 처음 돌렸을 때는 삭제하려던 문단 77건이 전부 skip되고 일부 셀만 적용됐습니다.
로그를 읽어보니 두 가지 이유였습니다. 첫째, patch는 블록(문단·표) 삭제를 지원하지 않습니다. 버그가 아니라 "원본을 훼손하지 않는다"는 무손실 설계의 의도된 제약입니다. 둘째, 제가 Markdown의 표를 손으로 다시 쓰면서 병합 셀 구조가 원본 파싱 결과와 미세하게 어긋났고, patch는 이걸 "표의 행을 삭제하려는 위험한 편집"으로 판정해 거부했습니다. 안전장치가 제대로 작동한 셈인데, 당하는 입장에서는 왜 안 되는지 한참 헤맸습니다.
성공 조건: 구조는 그대로, 텍스트만
정리하면 실패의 공통 원인은 하나였습니다. 도구가 보장하는 범위 밖의 일을 시킨 것. 성공한 절차는 이렇습니다.
| 단계 | 작업 | 결과 |
|---|---|---|
| 파싱 | kordoc 원본.hwpx -o clean.md --silent |
원본의 구조를 그대로 담은 Markdown 확보 |
| 치환 | clean.md에서 셀 텍스트만 스크립트로 교체 (행·열·셀 안의 줄 수 유지, 치환마다 발생 횟수 검증) | 구조가 원본과 동일한 편집본 |
| patch | kordoc patch 원본.hwpx edited.md -o filled.hwpx |
59건 변경 전부 적용, skip 0건, 재파싱 검증 일치 |
| 삭제 | HWPX 압축을 풀어 section0.xml의 최상위 문단을 직접 제거 | 문단 122개 중 100개(공고 본문) 삭제 |
| 검증 | kordoc validate + 재파싱 후 삭제 대상 키워드 grep |
구조 검증 통과, 잔존 0건 |
핵심은 2단계입니다. 편집본을 사람이 자유롭게 고치는 게 아니라, 파싱 결과에서 셀 안의 텍스트만 프로그램적으로 치환하고 나머지는 1글자도 건드리지 않는 것. 같은 빈 행이 반복되는 표(경력사항 7행, 자격사항 6행)는 몇 번째 등장인지 세어가며 치환했습니다. 이 조건을 지키자 실패 3에서 대부분 거부됐던 patch가 중첩표 안의 체크박스(□→☑)까지 전부 적용했습니다.
4단계 삭제는 kordoc이 지원하지 않는 영역이라 HWPX의 ZIP을 직접 열었습니다. 문단을 지울 때 두 가지를 조심해야 했습니다. 첫 문단에는 페이지 설정 정보가 들어 있어서 지우면 안 되고(텍스트만 비움), 서식 제목 문단에 걸린 페이지 나눔 속성을 그대로 두면 앞 내용이 사라진 뒤 첫 페이지가 빈 페이지로 남습니다. 재압축할 때도 mimetype 파일을 무압축으로 첫 엔트리에 넣어야 한글이 파일을 열어줍니다.
구형 .hwp는 어디까지 되나
같은 문서의 .hwp(5.x 바이너리) 버전으로도 실증해봤습니다. patch 채우기는 60건 중 57건이 적용됐습니다. 실패한 3건은 전부 개인정보 동의서의 중첩표(표 안의 표) 내부 체크박스였는데, 바이너리 포맷에서는 중첩표 매핑이 안 된다는 것이 도구의 실제 한계였습니다. 그리고 삭제 수술은 XML이 아니라서 아예 불가능합니다.
결국 실무 대응은 단순합니다. .hwp만 있는 문서는 한글에서 "다른 이름으로 저장 → HWPX" 한 번 거친 뒤 작업하면 됩니다. 한계를 우회하는 데 공수를 들이기보다 변환 안내가 빠릅니다.
시행착오를 스킬로 박제하기
여기까지의 절차를 SKILL.md 문서로 정리했습니다. 구성은 네 가지입니다.
- 복사해서 바로 쓸 수 있는 명령어·스크립트 템플릿
- 실패 경로 명시 — 어떤 명령을 어떤 상황에서 쓰면 안 되는지
- 검증 게이트 — 각 단계에서 무엇을 확인해야 다음으로 넘어가는지 (skip 0건, 재파싱 일치, grep 0건)
- 트러블슈팅 표 — 증상별 원인과 처방
이렇게 만든 이유는 비용입니다. 시행착오는 추론이 강한 비싼 모델로 한 번 겪고, 검증된 절차가 문서로 남으면 그다음부터는 저렴한 모델이 문서를 따라가기만 하면 됩니다. 실제로 이번 실패 기록의 상당 부분은 절차 없이 작업한 세션에서 나왔고, 성공 절차는 같은 도구·같은 문서에서 조건만 바꿔 얻은 것입니다. 도구 사용법보다 "AI에게 일을 시키는 절차를 어떻게 설계하고 남기는가"가 더 큰 변수라고 생각합니다. 스킬이라는 개념 자체가 낯설다면 프롬프트 공유의 진화형이 스킬인 이유에서 배경을 다뤘습니다.
kordoc 도구 자체는 AI 큐레이션: chrisryugj/kordoc에 따로 정리해뒀습니다.
| 키워드 | 언제 쓰나 |
|---|---|
| kordoc patch | HWPX 원본 서식을 유지한 채 텍스트만 바꾸고 싶을 때 |
| kordoc fill dry-run | 양식 자동 인식이 이 문서에서 통할지 먼저 확인할 때 |
| HWPX XML structure section0 | 문단 삭제처럼 도구가 지원하지 않는 편집이 필요할 때 |
| Claude Code SKILL.md | 검증된 작업 절차를 에이전트용 문서로 남기고 싶을 때 |
그래서 실무에서 어디까지 맡길 수 있나
속도와 토큰 비용까지 같이 놓고 보면 판단은 꽤 분명합니다. 초안 작성은 실수가 섞이더라도 AI에게 맡길 만합니다. 값 채우기, 반복되는 표 처리, 서술형 항목의 초안까지, 사람이 처음부터 타이핑하는 것보다 훨씬 빠르고 틀린 곳은 검증 게이트(skip 0건·재파싱 일치·grep)로 상당 부분 걸러집니다.
대신 마지막 터치는 아직 사람 몫입니다. 특히 파일을 실제로 열었을 때만 드러나는 것들이 그렇습니다. 셀에서 텍스트가 넘치는지, 페이지가 표 중간에서 끊기는지, 섹션이 의도한 페이지에서 시작하는지 같은 것은 파싱된 구조만 봐서는 알기 어렵습니다. 도구가 다루는 건 문서의 구조이지 실제 렌더링이 아니기 때문입니다.
이 경계가 고정된 건 아닙니다. 스킬과 규칙을 더 촘촘히 다듬으면 사람이 손볼 몫은 줄어듭니다. 다만 양식마다 표 구조와 페이지 구성이 제각각이라, 그 고도화는 양식별로 시간을 들여 쌓아야 하는 일입니다. 지금 단계의 현실적인 답은 분명합니다. 초안은 AI가, 최종 확인은 사람이. 그 사람 몫을 얼마나 줄이느냐가 다음 과제라고 봅니다.
이 글의 실패 재현부터 스킬 작성까지의 흐름은 공공기관 HWP/HWPX 공문서 AI 활용 교육 과정에서 실습으로 다룹니다.
오픈소스 도구를 활용한 교육이며, 문서의 버전·암호화·서식 복잡도에 따라 변환 결과는 달라질 수 있고 AI 결과물은 사람이 검토하는 것을 전제로 합니다.