Are you the author? Sign in to claim
모두 파싱해버리겠다 — HWP·HWPX·PDF·Office 문서를 Markdown으로. 양식 자동 채우기와 신구대조를 갖춘 CLI·MCP 서버 | Convert Korean documents (HWP, HWPX, P
모두 파싱해버리겠다.
대한민국에서 둘째가라면 서러울 문서지옥. 거기서 7년 버틴 공무원이 만들었습니다.
HWP 3.x/5.x, HWPX, HWPML, PDF, XLS, XLSX, DOCX, 이미지(PNG/JPG/WebP) — 관공서에서 쏟아지는 모든 문서를 파싱하고, 비교하고, 분석하고, 생성합니다.
▶ 클릭하면 유튜브에서 재생됩니다.
macOS / Linux / Windows 공용. Node.js 18+ 만 있으면 됩니다.
npx -y kordoc setup
대화형 마법사가:
[감지됨] 표시)Windows 도 자동으로 cmd /c npx 래핑. 수동 JSON 편집 불필요. 재시작하면 15개 문서 도구 (parse_document, parse_table, fill_form, patch_document, generate_document 등) 활성화.
CLI 로만 쓸 거면 설치 없이
npx kordoc <파일>바로 사용. 아래 CLI 섹션 참고.
MODULE_NOT_FOUND/Cannot find module ...\dist\cli.js가 뜨면: 과거에 깨진 글로벌 설치가 남아있는 상태입니다. 아래로 해결:hljs language-powershellnpm uninstall -g kordoc npx -y kordoc@latest setup
Windows PowerShell 에서
npx.ps1 파일을 로드할 수 없습니다 · PSSecurityException이 뜨면: PowerShell 기본 보안 정책이 서명 없는.ps1을 차단하는 표준 동작입니다 (kordoc 무관). 아래 중 하나 쓰시면 됩니다.방법 1 — 명령 프롬프트(cmd) 창에서 실행 (가장 안전) 윈도우 키 →
cmd검색 → Enter → 검은 창에서 그대로:hljs language-arduinonpx -y kordoc setup방법 2 — PowerShell 실행 정책 한 번만 완화 관리자 권한 PowerShell:
hljs language-powershellSet-ExecutionPolicy -Scope CurrentUser RemoteSigned이후 PowerShell 재시작 →
npx -y kordoc setup그대로 됨.
MCP 등록 대신 스킬(SKILL.md) 형태로 쓰려면:
/plugin marketplace add chrisryugj/kordoc
/plugin install kordoc@kordoc
.hwp/.hwpx 언급이나 공문서 생성·서식 채우기 요청 시 kordoc 스킬이 자동 활성화됩니다
(내부에서 npx -y kordoc@^4 CLI 호출 — 별도 설치 불필요).
단순한 텍스트 추출을 넘어, 공문서 처리를 위한 모든 과정을 자동화합니다.
HWP3 (구버전), HWP(5.x), HWPX, HWPML, PDF, XLS, XLSX, DOCX 파일은 물론 PNG/JPG/WebP 이미지(자동 OCR)까지 즉시 Markdown으로 변환합니다. AI(LLM)가 문서를 읽고 분석하기 가장 좋은 상태로 만들어줍니다.HWPX)으로 되돌려줍니다. 이제 복사-붙여넣기 노가다에서 해방되세요.kordoc lint)까지 — 한글 COM 실렌더로 조판까지 실측 검증했습니다.patchHwpx(HWPX) / patchHwp(HWP 5.x 바이너리)에 넘기면, 원본 서식을 1바이트도 건드리지 않고 바뀐 문단/표 셀의 텍스트만 원본 안에서 교체합니다. v3.7부터는 표에 행을 추가/삭제하는 편집도 원본 서식을 승계하며 반영되고, v3.8부터는 HWP 5.x의 빈 셀에 값 넣기도 지원합니다.kordoc seal).Claude Desktop, Cursor, Codex와 같은 도구에서 직접 kordoc을 호출해 문서를 읽고 코딩할 수 있습니다.[날짜] 부터 [날짜] 까지 같은 서식 기간 입력란) 텍스트가 표 앞으로 끌려나오던 순서 역전을 수정했습니다. 최상위 blocks와 IRCell.blocks 모두 원문 배치 순서를 따르고, 생성기도 같은 순서로 방출해 라운드트립이 대칭입니다. float·페이지 앵커 표는 종전대로 텍스트 흐름에 불참합니다. (@jumaniac 제보)~~취소선~~으로 살아납니다. 판정은 취소선 모양 whitelist — 한컴은 취소선 없는 문자에도 취소선 비트를 기본값으로 저장하므로(원저장소 rhwp 실측) 모양이 실제 선 종류일 때만 인정, 미지 값은 안전하게 무시. HWPX는 부분 취소선까지, HWP5는 문단 단위.kordoc 서식.png / parse(buffer) / MCP parse_document. 텍스트층이 없으므로 내장 OCR 이 자동 적용됩니다 (플래그 불필요, 디코딩은 optional dependency sharp).parse(buffer, { ocr: true }) / CLI --ocr / MCP parse_document의 ocr 옵션. 모델 ~18MB는 첫 사용 시 자동 다운로드+SHA 검증. 품질 신호가 가리키는 페이지(스캔·글꼴 매핑 깨짐)만 정밀 OCR 하고 정상 페이지는 그대로 두며, OCR 라인 좌표를 표 감지 파이프라인에 태워 스캔본에서도 표가 복원됩니다. 한국어 사전 11,945자(완성형 한글 11,172자 전량 + 자모·라틴·기호), 1페이지 ≈1초.--pages 필터가 한 페이지 밀리고 수식이 이전 페이지에 붙던 잠복 결함. XLSX/XLS --keep-empty-cols 배선 누락도 수리.render_document MCP 도구 신설: 생성·패치·양식 채움 결과 HWPX를 조판 그대로 PNG 이미지로 응답에 직접 반환 — AI가 자기가 만든 문서를 눈으로 확인하고 다시 고치는 루프가 MCP 안에서 닫힙니다 (한컴 저장본은 조판 캐시, 생성본은 reflow 조판, 검색어 형광펜 지원).kordoc redact + redact_document MCP 신설: 개인정보(주민번호·전화·이메일·카드·계좌, 여권·운전면허 opt-in)를 탐지해 원본 서식 그대로 마스킹(850315-●●●●●●●)한 HWPX/HWP를 출력합니다. 생년월일·Luhn 검증으로 오탐 축소, 리포트에 원본 개인정보 미포함. 자동 검출 보조 도구 — 최종 공개 전 사람 확인 필수.--format chunks + parse_chunks MCP 신설: RAG용 구조 청크 JSON — 헤딩·개조식 위계(□○- / 1.·가.·1))를 breadcrumb 경로로 보존하고 표는 독립 청크로 분리합니다.keepTrailingEmptyCols 파싱 옵션(CLI --keep-empty-cols)으로 보존할 수 있고, 양식 경로(parse_form·fill)는 항상 보존해 fill이 채울 수 있는 필드가 목록에서 빠지지 않습니다. 제보 @jumaniac. 참조, 로고·워터마크 페이지 간 중복 억제, 페이지 경계 표 병합 비간섭.w:object 이미지: OLE 개체 미리보기(v:imagedata)가 추출에서 빠지던 것 수정 (mc:Fallback 사본은 종전대로 중복 제외).[text](url) 생성. 워드·구글독스가 흔히 쓰는 필드코드 HYPERLINK(fldSimple/fldChar)와 내부 anchor 링크도 처리 (실측 176→21 손실이던 문서 전량 복원). 참조가 안 들어가던 것을 문단 위치 인라인 방출로 수정.garbled_hangul 사유의 페이지별 NEEDS_OCR 경고.**·* 마커로 복원됩니다 (charPr 실속성 기반, 한컴 편집 이력으로 쪼개진 run 자동 병합). 표 헤더행처럼 셀 전체가 볼드인 구조 서식은 마커를 만들지 않습니다.**강조**가 보존됩니다 — 보고서 1단계 □ 전체 굵게 같은 구조 볼드와 자동 구분.1)·- 항목이 재생성 시 1단계로 붕괴('1)'→'2.', '-'→□)하던 것을 들여쓰기 역산 선행 공백으로 해소 — 기안문·보고서·개조식 2차 왕복이 동일 결과로 수렴.fontName_hangul — 원본 없이 글꼴 재현), 첫 행 지문 anchor_row(첫 셀이 빈 크로스탭 매칭), 행0 전체 병합 표의 열폭 보존, 손편집 JSON의 괘선 값(type·mm·색상) 사전 검증.IRBlock.indent), 원문자 15+/51+ 폴백 파서 정합, 중첩표 높이 정밀화, 결문 구분선 컬럼폭 적응.--pt 15·numbering: 'standard'로 복원 가능).colPr) 미방출로 본문이 좌우 10mm씩 좁게 잡히고 표가 우측 여백을 침범하던 결함 해소 — 전 프리셋 실렌더 조판영역 초과 0건.--doc-head/--doc-foot, 별지 제1호서식) · 보도자료 프리셋 press (머리박스·담당 표) · 공고문 두문 (--notice-head) · 보고정보 행 (--report-info).--bullet2).--h2-marker(box □ / number / none), 개조식 소분류 부호 ― → 실무 관행 하이픈 -.kordoc lint <file> + 공문서 생성 시 경고 병기.--preset 개조식.hwpxToProfile(hwpx)로 레퍼런스 서식만 JSON으로 추출하고, markdownToHwpx(md, { profile })로 다른 문서에 그 서식을 입힙니다 — 원본 유출 없이 기관 서식만 공유·재현(이슈 #41, 스키마 docs/format-profile-spec.md). 스키마·예시 기여: @ai-localgov-officer (PR #42).kordoc seal — "(인)"·"서명 또는 인" 앵커를 찾아 도장 PNG를 글 앞 부유로 배치. 표/페이지를 키우지 않아 날인 후 서식이 밀리지 않습니다 (MCP place_seal 포함). 중첩표·글상자·탭/줄바꿈 문단은 위치가 근사이며 결과 warnings 로 고지됩니다 — 한컴에서 확인 후 --dx/--dy(dx_mm/dy_mm)로 미세조정하세요./plugin marketplace add chrisryugj/kordoc → .hwp/.hwpx/공문서 요청에 kordoc 스킬 자동 활성화.fill -o 출력 등 "성공 메시지 뒤에 조용히 틀린 산출물" 계열 소탕.<신 설> 표기를 텍스트 상자로 오인해 표 전체를 문단으로 해체하던 PDF 파서 결함 수정 — 30p 개정안 대비표가 통째 1표로 복원.markdownToHwpx 산출물·AI 생성본·편집본처럼 조판 캐시(linesegarray)가 없어 렌더가 거부되던 HWPX를 renderHwpxToSvg(buf, { reflow: true }) / kordoc render --reflow로 순수 TS 조판합니다. 검증된 줄나눔 엔진(실측 98% 일치) + 실측 세로 모델로 lineseg를 합성해 기존 렌더 파이프(정렬·표·이미지·형광펜·다페이지)를 재사용합니다. 단문단·표 셀·표 밀어내기·자동 페이지 분할. 한컴 저장본은 캐시 재생 그대로(무회귀).kordoc render-worker가 프로세스를 유지하며 연속 렌더 요청(stdin NDJSON)을 처리해 node 콜드스타트를 없앱니다(미리보기 앱 연동용).kordoc render가 전 페이지를 세로 스택 SVG로 그립니다(페이지별 흰 배경·경계선·클립, data-page 속성, RenderSvgResult.pageCount). 기존엔 전 페이지가 첫 장 한 장에 겹쳐 그려졌습니다.--highlight <쉼표구분어> / RenderSvgOptions.highlights — 텍스트를 매치 경계로 분할해 매치 세그먼트에만 배경을 깝니다(대소문자 무시, textLength 동일 계산으로 정렬 오차 없음).textpos를 HWP5 문자 스트림 슬롯(컨트롤 8·문자형 컨트롤 1·서로게이트 2슬롯) 기준으로 재구성해, 컨트롤·탭이 섞인 문단에서 첫 줄에 글자가 몰리고 다음 줄이 비던 어긋남을 해결했습니다(데모 1,132개 멀티라인 문단 검증).imgClip을 imgDim(내용 상자) 기준으로 해석 — 삽입 후 리사이즈된 이미지(로고 대부분)가 좌상단 코너로 잘못 잘려 깨지던 문제를 해결했습니다(데모 pic 267개 검증).※ …참조 등)이 hwpml 파싱에서 통째로 소실되던 문제를 수정했습니다. 캡션을 표 앞/뒤 문단으로 보존합니다.kordoc render 문서.hwpx -o 문서.svg / renderHwpxToSvg(buffer) — 한컴이 저장한 조판 캐시(줄 좌표·셀 그리드·개체 앵커)를 SVG 절대배치로 그려 원본 레이아웃을 재현합니다. run별 글자 크기/굵기/색/장평/자간, 문단 정렬, 셀 배경·테두리, 병합 셀, 인라인 개체, 이미지 크롭까지. 한컴 저장본 전용(1페이지).vertOffset="4294967103"(= −193) 같은 uint32 저장 음수를 올바르게 해석합니다.horzRelTo="COLUMN"을 셀 영역 기준으로 해석합니다 (사진이 페이지 왼쪽으로 튀던 문제).$$ \frac{a}{b} $$ 같은 display math 블록이 한컴 수식 개체(<hp:equation>)로 생성됩니다. \frac·\sqrt·첨자·그리스 문자·적분/극한·행렬(matrix/pmatrix/bmatrix)·\left( 구분자·\text 리터럴 지원. 생성한 수식은 kordoc으로 다시 파싱해도 같은 LaTeX로 돌아옵니다 (#38, @leehuiso 기여).$$가 문서 전체를 삼키던 문제(일반 문단 폴백), 중괄호 폭탄 크래시(깊이/길이 상한), 닫는 $$ 뒤 텍스트 소실을 수정했습니다.******·홍** 같은 마스킹 별표가 마크다운 수평선/볼드로 오독되던 것을 이스케이프로 보존합니다 (별표 각주 * 단, …의 리스트 오인도 해소).patchHwp): 원본에서 비어 있던 표 셀에 마크다운 편집으로 값을 넣으면 이제 HWP 바이너리에도 삽입됩니다. 한컴이 빈 문단을 저장하는 방식(텍스트 레코드 생략형 포함)을 실파일 실측으로 지원. (실파일 12건 무손상 검증)warnings로 보고합니다.patchHwpx): 마크다운에서 표에 행을 새로 넣거나 지워도 이제 원본에 반영됩니다. 새 행은 인접 행의 서식(테두리·글꼴·높이)을 그대로 복제해 셀 텍스트만 바꿔 넣고, rowCnt·셀 좌표·표 높이까지 함께 갱신합니다. 세로 병합을 가로지르거나 행에 이미지/중첩표가 있는 등 위험한 경우엔 문서를 건드리지 않고 사유와 함께 skip합니다. (실제 결재문서 45건 검증 — 손상 0)fillFormFields(IR)와 fillHwpx(원본 보존) 두 경로가 같은 결과를 내도록 정합.PatchSkip.partial 신설 — "적용은 됐지만 원형 그대로는 아님"(셀 내 줄 병합·빈 문단 잔존 등)을 구분해 보고합니다.autoFit): 한두 글자가 다음 줄로 넘어가는(orphan) 문단만 골라 장평을 95→90%로 줄여 한 줄에 담습니다. 공문서 작성 관행 그대로.markdownToHwpx로 구조 그대로 HWPX 표가 됩니다 — parse↔generate 표 라운드트립 완성.hwpxToProfile(hwpx)로 서식만 JSON으로 추출하고, markdownToHwpx(md, { profile })로 다른 문서에 그 서식을 입힙니다 — 원본 유출 없이 기관 서식만 공유·재현(이슈 #41, 스키마: docs/format-profile-spec.md).fillForm 값에 배열(string[])을 주면 같은 라벨의 등장 순서대로 하나씩 소진 — 반복 양식·명부형 표(헤더+여러 행) 채우기.patchHwpx): 기존 한글파일(HWPX) 안의 문단을 마크다운 표(| … |)로 편집해 patch에 넘기면, 원본 서식을 그대로 둔 채 그 문장만 표로 바꿔줍니다. 셀 테두리는 자동 생성, 나머지 문단·표·서식은 1바이트도 건드리지 않고 무손실 검증을 통과합니다. CLI kordoc patch·MCP patch_document가 자동 지원. (HWP 5.x 바이너리는 미지원 — generate로 새 문서 생성 권장)generate_document 도구: AI 에이전트가 마크다운(표 포함)을 바로 HWPX로 생성. parse_document로 읽은 내용을 표로 재구성해 다시 한글파일로 출력하는 워크플로가 완성됩니다. 공문서 프리셋(보고서·기안문…)·글꼴·글자크기 옵션 지원.markdownToHwpx(md, { gongmun: { preset: "보고서" } })처럼 라이브러리/MCP에서 한글 프리셋명을 직접 넘기면 터지던 버그 수정(normalizeGongmunPreset). CLI는 영향 없었음.🏛️ 공문서 모드 markdownToHwpx(md, { gongmun }) — 마크다운을 한국 행정 공문서 표준 서식의 HWPX로 렌더링. 행정안전부 「행정업무운영편람」·시행규칙 근거.
1. 가. 1) 가) (1) (가) ① ㉮ (마크다운 마커 종류 무시, 깊이로 강제). 가나다 소진 시 단모음 연속(거·너·더), 상위 항목 진행 시 하위 카운터 리셋, 단일 형제 부호 생략.<hc:intent>(음수 hanging) + <hc:left>(단계별 누적)로 둘째 줄이 내용 첫 글자에 정렬. (실제 한컴 공문서 paraPr 구조와 동일하게 검증)official(기안문)·report(보고서, □○-ㆍ 불릿)·plan·notice·minutes.import { markdownToHwpx } from "kordoc"
const md = "1. 첫째 항목\n - 둘째 항목\n - 셋째 항목"
const hwpx = await markdownToHwpx(md, { gongmun: { preset: "보고서" } })
// → 1. / 가. / 1) 항목부호 + 내어쓰기 + 공식 여백 자동 적용
CLI: kordoc generate doc.md -o out.hwpx --preset 보고서 (별칭 gen, --font/--pt/--line-spacing/--plain). 표준 레퍼런스: docs/gongmunseo-reference.md, 작성 스킬: .claude/skills/gongmunseo/.
🖊️ 에디터 통합 API HwpxSession — 블록 클릭-편집형 에디터를 위한 증분 패치 세션. openHwpxDocument(bytes)로 열고, session.patchBlocks(edits)로 블록 인덱스 기반 직접 편집 (문단 텍스트 / 표 셀). n회 연속 증분 패치 ≡ 일괄 patchHwpx 바이트 동일 동등성을 CI 게이트로 보장합니다.
import { openHwpxDocument } from "kordoc"
const session = await openHwpxDocument(new Uint8Array(buf))
session.capability(3) // "text" | "cell-text" | "locked" — 편집 전 잠금 판정
const res = await session.patchBlocks([
{ blockIndex: 3, newText: "개최 완료" },
{ blockIndex: 5, cells: [{ row: 1, col: 2, text: "홍길동" }] },
])
// session.bytes — 서식 그대로, 텍스트만 바뀐 HWPX (증분 누적)
📋 양식 필드 스키마 extractFormSchema(blocks) — 양식 인식에 타입 추론을 더해 폼 UI 자동 생성 지원. 필드 타입 7종(text/date/phone/email/amount/checkbox/idnum) + required(필수 표시 감지) + empty(채움 대상 판정).
fillHwpx splice 전환 — 수정 범위 외 섹션 XML을 원본 바이트 그대로 보존하도록 전면 재작성 (동작·결과는 v3.0과 패리티).
CJS 빌드 수정 — require("kordoc") 시 import.meta SyntaxError 나던 버그 수정.
patchHwp(원본HWP, 편집된마크다운) 신규 API. HWPX 패치(patchHwpx)의 HWP 5.x(OLE2 바이너리) 대응으로, 변경된 문단/표 셀의 PARA_TEXT만 레코드 안에서 치환합니다 (PARA_HEADER 글자수·CHAR_SHAPE·LINE_SEG 연쇄 갱신).
skipped[]로 graceful skipkordoc patch가 .hwp/.hwpx를 매직바이트로 자동 분기__dirname 미정의로 테스트 매트릭스가 실패하던 문제 수정🔄 서식 보존 무손실 라운드트립 — patchHwpx(원본HWPX, 편집된마크다운) 신규 API. 변경된 문단/셀의 텍스트만 원본 XML 안에서 in-place 치환하고 나머지 ZIP 엔트리는 바이트 그대로 보존. 미지원 편집(블록 추가/삭제, 표 구조 변경)은 원본을 건드리지 않고 skipped[]로 정직하게 보고하며, 패치 후 자동 재파싱 검증 리포트(verification)를 제공합니다.
import { parse, patchHwpx } from "kordoc"
const r = await parse(buf) // HWPX → 마크다운
const edited = r.markdown.replace("개최 예정", "개최 완료") // LLM이 편집했다고 가정
const res = await patchHwpx(new Uint8Array(buf), edited)
// res.data — 서식 그대로, 텍스트만 바뀐 HWPX 바이트
// res.applied / res.skipped / res.verification — 적용·미지원·검증 리포트
🎯 "99.9% 정확도" 파서 대도약 — 실측 공문서 코퍼스 324건(정부 보도자료 + 서울시 결재문서 + 2014~2016 옛 문서) 자기참조 채점 기준:
| 지표 | v2.9.1 | v3.0.0 |
|---|---|---|
| HWPX 텍스트 재현율 | 99.699% | 99.998% |
| HWPX 표 구조 정확일치 | 99.875% | 100% (1,421표 · 중첩표 343 포함) |
| PDF coverage | 97.013% | 99.16% |
| HWP5↔HWPX 쌍 유사도 | — | 99.94% |
중첩표 구조 보존(IRCell.blocks), 한컴 PUA 매핑, HWP5 이미지 추출(0→90건), 자동번호 카운터, 머리말/각주 정밀 처리 등. 채점기·코퍼스 수집기·게이트는 bench/에 포함 — node bench/score.mjs로 재현 가능.
parsePdf 결과에 페이지별 품질 신호(pageQuality)와 문서 요약(qualitySummary)을 추가 — needsOcr/ocrReason 으로 OCR 큐 자동 라우팅이 가능. kordoc 은 OCR 을 기본 탑재하지 않고 신호만 노출합니다. 전국 지자체 주요업무계획 PDF 190건(45,399쪽) 대량 처리 중 도출. (아래 PDF 텍스트 품질 신호 참고)markdownToHwpx 테마 옵션 (#31) — 헤딩/본문/인용/표 헤더 셀의 텍스트 색상과 표 헤더 굵기를 옵션으로 지정 가능. 새 export 타입 HwpxTheme, MarkdownToHwpxOptions. 옵션 미지정 시 기존과 동일하게 검정으로 출력(baseline 백워드 호환).<hp:run> 이 <hp:t> 자식 없이 self-closing)에 값이 삽입되지 않으면서 결과에는 성공으로 보고되던 false-positive 수정. setRunText 가 <hp:t> 없는 run 에 새로 생성해 텍스트 삽입. 기여: @amnotyoung"HWP Document File V3.00" 시그니처) 텍스트 추출. 기존 kordoc 이 거부하던 구버전 판결문/공문서 등이 검색 인덱싱 가능. 상용조합형(johab) → 유니코드 + 5,893개 한자/기호 lookup. 표 cell / 머리말 / 각주 의 nested paragraph 재귀 추출. @edwardkim/rhwp 의 Rust 구현을 TypeScript 로 포팅.markdownToHwpx() 가 만든 HWPX 가 macOS 한컴에서 "파일이 깨졌다"며 거부되던 문제 해결. 테이블 XML 을 최소 스켈레톤에서 완전 스펙 형태로 재작성 — <hp:tbl> 필수 속성 10종 + <hp:sz>/<hp:pos>/<hp:outMargin>/<hp:inMargin>, <hp:tc> 안에 <hp:subList> 래퍼 + <hp:cellAddr>/<hp:cellSpan>/<hp:cellSz>/<hp:cellMargin>, paragraph 래핑. Preview/PrvText.txt 추가 + borderFill id=1(SOLID 0.12mm) 추가..hwp 바이너리에서 "이 문서는 상위 버전의 배포용 문서입니다..." 경고 플레이스홀더만 나오는 케이스에서, Windows + 한컴오피스 환경이면 자동으로 HWPFrame.HwpObject COM API 로 재시도. v2.4.0 의 HWPX DRM fallback 인프라를 .hwp 에도 확장.manifest.xml에서 암호화 감지 → HWPFrame.HwpObject의 GetPageText로 페이지별 추출 → Markdown 변환. Windows + 한컴 오피스 설치 환경에서 별도 설정 없이 동작..hwp XML 방식) 파싱 지원. npx kordoc <file.hwp>에서 지원하지 않는 파일 형식 오류가 나던 XML 기반 공문서를 이제 Markdown으로 변환할 수 있습니다. HWP 5.x 바이너리와 자동 구분(XML 시그니처 감지).[중첩 테이블 #N] 마커 삽입. 큰 중첩 테이블(≥3행 + ≥2열)은 별도 블록으로 분리, 작은 것은 셀 내 평탄화. HWP5는 기존에 내용이 완전히 손실되던 것을 마커로 복구.binaryItemIDRef가 확장자 없이("image1") 저장된 HWPX에서 이미지 추출이 실패하던 문제 해결. ZIP 내 파일명 regex 매칭으로 복원.□→☑), 괄호 빈칸(일반( )통→일반(3)통), 어노테이션((한자:)→(한자:金)) 지원.fillHwpx()로 HWPX XML을 직접 조작하여 글꼴, 크기, 정렬 등 원본 서식 100% 유지한 채 값만 교체.colspan/rowspan이 있는 복잡한 표를 GFM 대신 HTML <table>로 출력하여 구조 보존.~) 이스케이프로 취소선 오해석 방지, 테이블 셀 내 | 문자 이스케이프, 중첩 테이블 텍스트 구분자 | → / 변경으로 GFM 파서 충돌 방지.Math.min/max(...spread) 스택 오버플로 수정 (15개소), Watch 동시 처리 제한(MAX_CONCURRENT=3).parse_metadata XLSX/DOCX 오분류 수정, PDF 폰트 크기 통계 메모리 최적화(40MB→~50엔트리).isPathTraversal 합법적 파일명 오탐 수정.<p>><run>><tbl> 구조의 중첩 테이블 파싱 누락 수정.--no-header-footer 플래그 반전 버그, MCP XLSX/DOCX 확장자 허용, ZIP bomb 보호 공유 유틸화, href XSS 살균 강화, PDF timeout 타이머 정리, HWP5 BinData O(n) 최적화, cluster indexOf O(n²)→O(n), SSRF IPv6 차단 등.onProgress 콜백. CLI에서 [3/15 pages] 형태 표시.parse("path/to/file.hwp") 문자열 오버로드.removeHeaderFooter 옵션.࣐Ā 쓰레기 문자가 출력되던 버그 수정.구분/항목/종류/기준 등 한국 공문서 key-value 패턴을 자동으로 2열 테이블로 변환.heading, paragraph, table, list, image, separator. 새 필드: bbox, style, pageNumber, level, href, footnoteText.outline (문서 구조), warnings (스킵된 요소, 숨김 텍스트) 필드 추가.outline, warnings 포함.IRBlock[]과 DocumentMetadata에 직접 접근. 마크다운 넘어선 데이터 활용.parse(buffer, { pages: "1-3" }) — 필요한 페이지만 빠르게.ocr: true, PP-OCRv5 korean) 또는 외부 프로바이더(Tesseract, Claude Vision 등).kordoc watch ./수신함 -d ./변환결과 --webhook https://..."ENCRYPTED", "ZIP_BOMB", "IMAGE_BASED_PDF" 등 구조화된 에러 핸들링npm install kordoc
PDF 파싱(pdfjs-dist)·수식 OCR 등 선택 의존성은 기본 설치됩니다 (optionalDependencies).
설치 용량을 줄이려면 npm install kordoc --omit=optional 로 스킵할 수 있습니다 —
이 경우 PDF 파싱·수식 OCR·인쇄 렌더 등 일부 기능이 제한됩니다.
import { parse } from "kordoc"
import { readFileSync } from "fs"
const buffer = readFileSync("사업계획서.hwpx")
const result = await parse(buffer)
if (result.success) {
console.log(result.markdown) // 마크다운 텍스트
console.log(result.blocks) // IRBlock[] 구조화 데이터
console.log(result.metadata) // { title, author, createdAt, ... }
}
import { compare } from "kordoc"
const diff = await compare(구버전Buffer, 신버전Buffer)
// diff.stats → { added: 3, removed: 1, modified: 5, unchanged: 42 }
// diff.diffs → BlockDiff[] (테이블은 셀 단위 diff 포함)
HWP vs HWPX 크로스 포맷 비교도 가능합니다.
import { parse, extractFormFields } from "kordoc"
const result = await parse(buffer)
if (result.success) {
const form = extractFormFields(result.blocks)
// form.fields → [{ label: "성명", value: "홍길동", row: 0, col: 0 }, ...]
// form.confidence → 0.85
}
import { fillForm } from "kordoc"
import { readFileSync, writeFileSync } from "fs"
const template = readFileSync("신청서.hwpx")
// HWPX 원본 서식 보존 모드 — 글꼴, 크기, 정렬 100% 유지
const result = await fillForm(template, {
성명: "홍길동",
주민등록번호: "900101-1234567",
주소: "서울특별시 광진구 능동로 120",
}, "hwpx-preserve")
writeFileSync("신청서_작성완료.hwpx", Buffer.from(result.output as ArrayBuffer))
// result.fill.filled → [{ label: "성명", value: "홍길동" }, ...]
// result.fill.unmatched → 매칭 실패한 키 목록
import { markdownToHwpx } from "kordoc"
const hwpxBuffer = await markdownToHwpx("# 제목\n\n본문 텍스트\n\n| 이름 | 직급 |\n| --- | --- |\n| 홍길동 | 과장 |")
writeFileSync("출력.hwpx", Buffer.from(hwpxBuffer))
// display math block은 HWPX native 수식(<hp:equation>)으로 생성됩니다.
// 초기 지원 범위는 \frac, \sqrt, 첨자/위첨자, Greek, 적분/극한,
// 화살표, 관계 연산자, matrix 계열의 제한된 LaTeX-like subset입니다.
const withEquation = await markdownToHwpx("피타고라스\n\n$$a^2 + b^2 = c^2$$")
// 공문서 모드 — 항목부호 8단계 + 내어쓰기 + 공식 여백/명조 자동
const gongmun = await markdownToHwpx("1. 추진배경\n - 세부 항목\n2. 추진계획", {
gongmun: { preset: "보고서" }, // official | report | plan | notice | minutes | gaejosik | press
})
// 정부 표준 개조식 보고서 (v4.0) — 표지·목차(장식 배너)·로마숫자 장헤더·
// 본문 제목박스·쪽번호("- 1 -", 표지·목차 제외)까지 실측 정부 양식 그대로
const report = await markdownToHwpx(md, {
gongmun: {
preset: "개조식",
cover: { org: "기관명", date: "2026. 7. 11." },
toc: true, // h2 목록 → Ⅰ Ⅱ Ⅲ 목차 (개조식 기본 켜짐)
approval: ["담당", "팀장", "과장"], // 결재란 (선택)
pageNumbers: true, // 쪽번호 (개조식·보고서·계획서 기본 켜짐)
endMark: false, // 본문 끝 "끝." (기안문 기본 켜짐)
},
})
// 표는 실측 정부 문법 자동 적용: 헤더 음영+bold+하변 이중선, 외곽 0.4mm 위계,
// 라벨열 음영, 내용 비례 열폭(수치 열 실폭 고정), 본문폭보다 좁게 + 우측 배치
CLI로도: kordoc generate 보고서.md -o 보고서.hwpx --preset 개조식 --org 기관명 --approval 담당,팀장,과장
(--toc/--no-toc --cover/--no-cover --page-numbers --end-mark --no-body-title-box --fonts --sizes)
한컴이 HWPX에 저장하는 조판 캐시(줄 좌표·셀 그리드·개체 앵커)를 그대로 SVG 절대배치로
그립니다. 조판 엔진 없이 빠르고, 서버에 한컴 설치 없이 원본 모양 미리보기를 만들 수
있습니다. 다페이지 세로 스택·검색어 형광펜·그리기 도형 지원(v3.14~15). 조판 캐시가 없는
파일(markdownToHwpx 산출물·AI 생성본·편집본)은 reflow: true를 주면 순수 TS reflow
엔진이 직접 조판합니다(v3.15). 수식 개체는 미지원.
import { renderHwpxToSvg } from "kordoc"
const r = await renderHwpxToSvg(readFileSync("결재문서.hwpx"), { highlights: ["예산"] })
writeFileSync("결재문서.svg", r.svg)
// r.width/r.height (pt), r.pageCount, r.stats { texts, images, tables }, r.warnings
const g = await renderHwpxToSvg(generatedHwpx, { reflow: true }) // 조판 캐시 없는 생성본
CLI로도: kordoc render 결재문서.hwpx -o 결재문서.svg (--reflow·--highlight 예산,집행),
연속 렌더는 kordoc render-worker(stdin NDJSON, 미리보기 앱 연동용)
const result = await parse(buffer, { pages: "1-3" }) // 1~3 페이지만
const result = await parse(buffer, { pages: [1, 5, 10] }) // 특정 페이지
// 내장 OCR (PP-OCRv5 korean, 첫 사용 시 모델 ~18MB 자동 다운로드)
const result = await parse(buffer, { ocr: true }) // OCR 필요 페이지만 자동 판정
const result = await parse(buffer, { ocr: "force" }) // 전 페이지 강제 OCR
needsOcr 신호)만 OCR 하고 정상 페이지의 파싱 결과는 그대로 유지합니다.const result = await parse(buffer, {
ocr: async (pageImage, pageNumber, mimeType) => {
return await myOcrService.recognize(pageImage) // Claude Vision, Tesseract 등
}
})
PDF는 텍스트층이 있어도 ToUnicode/CMap이 깨졌거나 NUL 등 제어문자가 섞이는 경우가 많다. parsePdf 결과는 페이지별 품질 신호를 함께 반환한다.
const r = await parsePdf(buffer)
if (r.success && r.qualitySummary?.needsOcr) {
// 내장 OCR 로 재시도 (v4.2.0+) — 또는 외부 OCR 큐로 라우팅
const retried = await parse(buffer, { ocr: true })
}
// 페이지 단위 신호
for (const p of r.pageQuality ?? []) {
if (p.needsOcr) console.log(`p${p.page} 검토 필요: ${p.ocrReason}`)
}
신호 키: textChars, hangulRatio, controlCharRatio, replacementCharRatio, puaRatio / needsOcr (페이지·문서 단위) / ocrReason (low_text | high_pua | high_control | high_replacement).
npx kordoc 사업계획서.hwpx # 터미널 출력
npx kordoc 보고서.hwp -o 보고서.md # 파일 저장
npx kordoc *.pdf -d ./변환결과/ # 일괄 변환
npx kordoc 검토서.hwpx --format json # JSON (blocks + metadata 포함)
npx kordoc 보고서.hwpx --pages 1-3 # 페이지 범위
npx kordoc fill 신청서.hwpx -f '성명=홍길동,주소=서울' -o 결과.hwpx # 양식 채우기
npx kordoc fill 신청서.hwpx -j values.json -o 결과.hwpx # JSON 파일로 채우기
npx kordoc fill 신청서.hwpx --dry-run # 필드 목록만 확인
npx kordoc generate 보고서.md -o 보고서.hwpx --preset 보고서 # 마크다운 → 공문서 HWPX
npx kordoc patch 원본.hwpx 편집.md -o 반영.hwpx # 서식 보존 라운드트립 패치 (.hwp도 자동 분기)
npx kordoc seal 신청서.hwpx --image 도장.png --anchor "(인)" -o 날인.hwpx # 도장/서명 날인
npx kordoc validate 산출물.hwpx # HWPX 구조 검증 (ZIP·필수 파트·XML)
npx kordoc lint 보고서.hwpx # 공문서 표기법 검수 13룰 (v4.0.1)
npx kordoc render 결재문서.hwpx -o 미리보기.svg # 레이아웃 보존 SVG 렌더 (--reflow 지원)
npx kordoc watch ./수신함 -d ./변환결과 # 폴더 감시 모드
npx kordoc watch ./문서 --webhook https://api/hook # 웹훅 알림
자동 설치 (추천):
npx -y kordoc setup
대화형으로 AI 클라이언트를 감지해 설정 파일을 자동 패치. Windows 에서 cmd /c npx 래핑도 자동. 상세는 위 30초 설치 섹션.
Codex는 설정 파일을 직접 수정하지 않고 codex mcp add 명령으로 안전하게 등록합니다.
Codex 수동 등록:
codex mcp add kordoc -- npx -y kordoc mcp
수동 등록 (macOS / Linux):
{
"mcpServers": {
"kordoc": {
"command": "npx",
"args": ["-y", "kordoc", "mcp"]
}
}
}
수동 등록 (Windows — Claude Desktop 이 .cmd 를 못 찾을 때):
{
"mcpServers": {
"kordoc": {
"command": "cmd",
"args": ["/c", "npx", "-y", "kordoc", "mcp"]
}
}
}
15개 도구:
| 도구 | 설명 |
|---|---|
parse_document | HWP/HWPX/PDF/XLSX/DOCX → 마크다운 (메타데이터 포함) |
detect_format | 매직 바이트로 포맷 감지 |
parse_metadata | 메타데이터만 빠르게 추출 |
parse_pages | 특정 페이지 범위만 파싱 |
parse_table | N번째 테이블만 추출 |
compare_documents | 두 문서 비교 (크로스 포맷) |
parse_form | 양식 필드를 JSON으로 추출 |
fill_form | 양식 템플릿에 값 채우기 (HWPX 원본 서식 보존, 서식/유일성 가드) |
patch_document | 편집된 마크다운을 원본 HWPX/HWP에 서식 보존 반영 (v3.3) |
extract_profile | 참조 HWPX에서 표 서식 프로필(JSON) 추출 — generate_document의 profile_path로 재현 |
generate_document | 마크다운(표·수식·차트 포함) → HWPX 생성, 공문서 프리셋 (v3.5) |
place_seal | 도장/서명 이미지를 앵커 문구 위에 부유 배치 (v3.16) |
render_document | HWPX를 조판 그대로 PNG 이미지/SVG로 렌더 — 생성·수정 결과를 AI가 눈으로 검증 (v4.1) |
redact_document | 개인정보(주민번호·전화·이메일·카드·계좌) 탐지 + 서식 보존 마스킹, 리포트 반환 (v4.1) |
parse_chunks | RAG용 구조 청크 JSON — 헤딩·개조식 위계 breadcrumb + 표 독립 청크 (v4.1) |
| 함수 | 설명 |
|---|---|
parse(buffer, options?) | 포맷 자동 감지 → Markdown + IRBlock[] |
parseHwpx(buffer, options?) | HWPX 전용 |
parseHwp(buffer, options?) | HWP 5.x 전용 |
parseHwp3(buffer, options?) | HWP 3.x (1996~2002 구버전) 전용 |
parsePdf(buffer, options?) | PDF 전용 |
parseXlsx(buffer, options?) | XLSX 전용 |
parseXls(buffer, options?) | XLS (Excel 97~2003, BIFF8) 전용 |
parseDocx(buffer, options?) | DOCX 전용 |
parseHwpml(buffer, options?) | HWPML (XML 기반 HWP) 전용 |
detectFormat(buffer) | "hwpx" | "hwp" | "hwp3" | "hwpml" | "pdf" | "xlsx" | "xls" | "docx" | "unknown" |
| 함수 | 설명 |
|---|---|
compare(bufferA, bufferB, options?) | IR 레벨 문서 비교 |
extractFormFields(blocks) | IRBlock[]에서 양식 필드 인식 |
extractFormSchema(blocks) | 양식 필드 인식 + 타입/필수/빈값 추론 (v3.1) |
fillForm(input, values, outputFormat?) | 양식 템플릿에 값 채우기 — outputFormat: "markdown"(기본)/"hwpx"/"hwpx-preserve", 반환 { output, format, fill } |
fillFormFields(blocks, values) | IRBlock[] 기반 필드 값 교체 |
fillHwpx(buffer, values) | HWPX XML 직접 조작 (원본 서식 보존) |
patchHwpx(original, editedMarkdown, options?) | 편집 마크다운 → 원본 HWPX 서식 보존 in-place 패치 (v3.0) |
patchHwp(original, editedMarkdown, options?) | 편집 마크다운 → 원본 HWP 5.x 바이너리 서식 보존 패치 (v3.0.1) |
openHwpxDocument(bytes, options?) | 에디터용 블록 단위 증분 패치 세션 HwpxSession (v3.1) |
patchHwpxBlocks(bytes, edits, options?) | 세션 없이 블록 편집 1회 패치 (v3.1) |
markdownToHwpx(markdown, options?) | Markdown → HWPX 역변환 (테마 옵션 지원) |
markdownToPdf(markdown, options?) | Markdown → PDF 생성 (Print Renderer) |
blocksToPdf(blocks, options?) | IRBlock[] → PDF 생성 |
renderHtml(blocks, options?) | IRBlock[] → 인쇄용 HTML |
renderHwpxToSvg(buffer, options?) | HWPX → 레이아웃 보존 SVG — 다페이지·형광펜·도형, 캐시 없으면 reflow (v3.10~15) |
placeSealHwpx(buffer, seals) | 도장/서명 이미지를 앵커 문구 위에 부유 배치 (v3.16) |
validateHwpx(buffer) | HWPX 구조 검증 — ZIP·mimetype·필수 파트·XML 웰폼드 (v3.16) |
blocksToMarkdown(blocks) | IRBlock[] → Markdown 문자열 |
import type {
ParseResult, ParseSuccess, ParseFailure, FileType,
IRBlock, IRBlockType, IRTable, IRCell, CellContext,
DocumentMetadata, ParseOptions, ErrorCode, OutlineItem,
DiffResult, BlockDiff, CellDiff, DiffChangeType,
FormField, FormResult, FillResult, HwpxFillResult, FillOutputFormat, FillFormOutput,
PatchOptions, PatchResult, PatchSkip,
HwpxTheme, MarkdownToHwpxOptions,
PrintPreset, PrintOptions, PageMargin,
RenderSvgOptions, RenderSvgResult,
OcrProvider, WatchOptions,
} from "kordoc"
| 포맷 | 엔진 | 특징 |
|---|---|---|
| HWPX (한컴 2020+) | ZIP + XML DOM | 매니페스트, 중첩 테이블, 병합 셀, 손상 ZIP 복구 |
| HWP 5.x (한컴 레거시) | OLE2 + CFB | 배포용 복호화, 손상 CFB 복구, 각주/하이퍼링크, 21종 제어문자, 이미지 추출 |
| HWP 3.x (1996~2002) | 단일 binary | 상용조합형→유니코드, 5,893자 한자/기호 lookup, nested paragraph 추출 |
| HWPML 2.x (XML 기반 HWP) | XML DOM | HeadingType 기반 헤딩 감지, 병합 셀, DoS 방어 |
| pdfjs-dist | 선 기반 테이블, XY-Cut 읽기 순서, 헤딩 감지, OCR, 텍스트 품질 신호 | |
| XLSX (Excel) | ZIP + XML DOM | 공유 문자열, 병합 셀, 다중 시트, 수식 표시 |
| XLS (Excel 97~2003) | OLE2 + BIFF8 | Workbook 스트림, SST 공유 문자열, 셀/시트 추출 |
| DOCX (Word) | ZIP + XML DOM | 스타일 heading, 번호 매기기, 각주, 이미지 추출 |
프로덕션급 보안 강화: ZIP bomb 방지, XXE/Billion Laughs 방지, 압축 폭탄 방지, 경로 순회 차단, MCP 에러 정제, 파일 크기 제한(500MB). 자세한 내용은 SECURITY.md 참조.
대한민국 지방공무원. 광진구청에서 7년간 HWP 파일과 싸우다가 이걸 만들었습니다. 5개 공공 프로젝트에서 수천 건의 실제 관공서 문서를 파싱하며 검증했습니다.
이 프로젝트는 아래 오픈소스를 포함합니다:
자세한 내용은 NOTICE 파일을 참조하세요.
Run analytics queries on ClickHouse — explore schemas, execute SQL, fetch results
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
Browser automation using accessibility snapshots instead of screenshots
Google's universal MCP server supporting PostgreSQL, MySQL, MongoDB, Redis, and 10+ databases