kordoc
An MCP server that parses South Korean document formats like HWP, HWPX, and PDF into Markdown. It features specialized table reconstruction and security-hardened extraction optimized for administrative and public institution files.
Ask AI about kordoc
Powered by Claude ยท Grounded in docs
I know everything about kordoc. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
kordoc
๋ชจ๋ ํ์ฑํด๋ฒ๋ฆฌ๊ฒ ๋ค.
๋ํ๋ฏผ๊ตญ์์ ๋์งธ๊ฐ๋ผ๋ฉด ์๋ฌ์ธ ๋ฌธ์์ง์ฅ. ๊ฑฐ๊ธฐ์ 7๋ ๋ฒํด ๊ณต๋ฌด์์ด ๋ง๋ค์์ต๋๋ค.
HWP, HWPX, PDF, XLSX, DOCX โ ๊ด๊ณต์์์ ์์์ง๋ ๋ชจ๋ ๋ฌธ์๋ฅผ ํ์ฑํ๊ณ , ๋น๊ตํ๊ณ , ๋ถ์ํ๊ณ , ์์ฑํฉ๋๋ค.

โก 30์ด ์ค์น (AI ์์ด์ ํธ ์ฐ๋)
macOS / Linux / Windows ๊ณต์ฉ. Node.js 18+ ๋ง ์์ผ๋ฉด ๋ฉ๋๋ค.
npx -y kordoc setup
๋ํํ ๋ง๋ฒ์ฌ๊ฐ:
- ์ฌ์ฉ ์ค์ธ AI ํด๋ผ์ด์ธํธ ๋ฒํธ ์ ํ (Claude Desktop / Cursor / Claude Code / Windsurf / VS Code / Gemini CLI / Zed / Antigravity โ ์ค์น๋ ๊ฑด
[๊ฐ์ง๋จ]ํ์) - ์ค์ ํ์ผ ์๋ ํจ์น โ ํด๋ผ์ด์ธํธ ์ฌ์์
Windows ๋ ์๋์ผ๋ก cmd /c npx ๋ํ. ์๋ JSON ํธ์ง ๋ถํ์. ์ฌ์์ํ๋ฉด 8๊ฐ ๋ฌธ์ ํ์ฑ ๋๊ตฌ (parse_document, parse_table, fill_form ๋ฑ) ํ์ฑํ.
CLI ๋ก๋ง ์ธ ๊ฑฐ๋ฉด ์ค์น ์์ด
npx kordoc <ํ์ผ>๋ฐ๋ก ์ฌ์ฉ. ์๋ CLI ์น์ ์ฐธ๊ณ .
MODULE_NOT_FOUND/Cannot find module ...\dist\cli.js๊ฐ ๋จ๋ฉด: ๊ณผ๊ฑฐ์ ๊นจ์ง ๊ธ๋ก๋ฒ ์ค์น๊ฐ ๋จ์์๋ ์ํ์ ๋๋ค. ์๋๋ก ํด๊ฒฐ:npm uninstall -g kordoc npx -y kordoc@latest setup
Windows PowerShell ์์
npx.ps1 ํ์ผ์ ๋ก๋ํ ์ ์์ต๋๋ค ยท PSSecurityException์ด ๋จ๋ฉด: PowerShell ๊ธฐ๋ณธ ๋ณด์ ์ ์ฑ ์ด ์๋ช ์๋.ps1์ ์ฐจ๋จํ๋ ํ์ค ๋์์ ๋๋ค (kordoc ๋ฌด๊ด). ์๋ ์ค ํ๋ ์ฐ์๋ฉด ๋ฉ๋๋ค.๋ฐฉ๋ฒ 1 โ ๋ช ๋ น ํ๋กฌํํธ(cmd) ์ฐฝ์์ ์คํ (๊ฐ์ฅ ์์ ) ์๋์ฐ ํค โ
cmd๊ฒ์ โ Enter โ ๊ฒ์ ์ฐฝ์์ ๊ทธ๋๋ก:npx -y kordoc setup๋ฐฉ๋ฒ 2 โ PowerShell ์คํ ์ ์ฑ ํ ๋ฒ๋ง ์ํ ๊ด๋ฆฌ์ ๊ถํ PowerShell:
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned์ดํ PowerShell ์ฌ์์ โ
npx -y kordoc setup๊ทธ๋๋ก ๋จ.
๐ก kordoc์ผ๋ก ๋ฌด์์ ํ ์ ์๋์?
๋จ์ํ ํ ์คํธ ์ถ์ถ์ ๋์ด, ๊ณต๋ฌธ์ ์ฒ๋ฆฌ๋ฅผ ์ํ ๋ชจ๋ ๊ณผ์ ์ ์๋ํํฉ๋๋ค.
- ๐ ์ด๋ค ๋ฌธ์๋ ๋งํฌ๋ค์ด์ผ๋ก:
HWP,HWPX,HWPML,PDF,XLSX,DOCXํ์ผ์ ์ฆ์Markdown์ผ๋ก ๋ณํํฉ๋๋ค. AI(LLM)๊ฐ ๋ฌธ์๋ฅผ ์ฝ๊ณ ๋ถ์ํ๊ธฐ ๊ฐ์ฅ ์ข์ ์ํ๋ก ๋ง๋ค์ด์ค๋๋ค. - ๐ ๋ณต์กํ ํ(Table) ์๋ฒฝ ์ฌํ: ์ ์ด ์๋ PDF๋ ๋ณต์กํ๊ฒ ๋ณํฉ๋ HWP ํ๋ ๊ตฌ์กฐ๋ฅผ ๋ถ์ํ์ฌ ์ ํํ ๋งํฌ๋ค์ด ํ ์ด๋ธ๋ก ๋ณต์ํฉ๋๋ค.
- ๐ ์ ๊ตฌ๋์กฐํ ์๋ ์์ฑ: ๋ ๋ฌธ์์ ์ฐจ์ด์ ์ ๋ถ์ํ์ฌ ๋ฌด์์ด ๋ฐ๋์๋์ง ํ๋์ ๋ณด์ฌ์ค๋๋ค. (HWP์ HWPX ๊ฐ์ ๋น๊ต๋ ๊ฐ๋ฅ!)
- ๐ ๋งํฌ๋ค์ด์ ๋ค์ HWPX๋ก: AI๊ฐ ์์ฑํ ๋ด์ฉ์ ๋ค์ ๋ณด๊ณ ์ ์์(
HWPX)์ผ๋ก ๋๋๋ ค์ค๋๋ค. ์ด์ ๋ณต์ฌ-๋ถ์ฌ๋ฃ๊ธฐ ๋ ธ๊ฐ๋ค์์ ํด๋ฐฉ๋์ธ์. - โ๏ธ ์์ ์๋ ์ฑ์ฐ๊ธฐ: ๊ณต๋ฌธ์ ์์ ํ ํ๋ฆฟ(์ ์ฒญ์, ๋ณด๊ณ ์)์ ๊ฐ์ ๋ฃ์ผ๋ฉด ์๋์ผ๋ก ๋น์นธ์ ์ฑ์๋๋ค. ์๋ณธ ์์(๊ธ๊ผด, ํฌ๊ธฐ, ์ ๋ ฌ)์ 100% ๋ณด์กดํฉ๋๋ค.
- ๐ค AI ์์ด์ ํธ ์ฐ๋ (MCP):
Claude,Cursor์ ๊ฐ์ ๋๊ตฌ์์ ์ง์ kordoc์ ํธ์ถํด ๋ฌธ์๋ฅผ ์ฝ๊ณ ์ฝ๋ฉํ ์ ์์ต๋๋ค.
v2.5.0 ๋ณ๊ฒฝ์ฌํญ
- ๐๏ธ macOS ํ์ปด์คํผ์ค ํธํ HWPX ์์ฑ (#4) โ
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์ถ๊ฐ +borderFillid=1(SOLID 0.12mm) ์ถ๊ฐ. - ๐ HWP 5.x ๋ฐฐํฌ์ฉ ๋ฌธ์ COM fallback (#25) โ
.hwp๋ฐ์ด๋๋ฆฌ์์ "์ด ๋ฌธ์๋ ์์ ๋ฒ์ ์ ๋ฐฐํฌ์ฉ ๋ฌธ์์ ๋๋ค..." ๊ฒฝ๊ณ ํ๋ ์ด์คํ๋๋ง ๋์ค๋ ์ผ์ด์ค์์, Windows + ํ์ปด์คํผ์ค ํ๊ฒฝ์ด๋ฉด ์๋์ผ๋กHWPFrame.HwpObjectCOM API ๋ก ์ฌ์๋. v2.4.0 ์ HWPX DRM fallback ์ธํ๋ผ๋ฅผ.hwp์๋ ํ์ฅ.
v2.4.0 ๋ณ๊ฒฝ์ฌํญ
- ๐ HWPX DRM ๋ฐฐํฌ์ฉ ๋ฌธ์ ์๋ ์ถ์ถ โ ๊ณต๊ณต๊ธฐ๊ด ๋ฐฐํฌ์ฉ DRM์ด ๊ฑธ๋ฆฐ HWPX ํ์ผ์ ํ์ปด ์คํผ์ค COM API๋ก ์๋ ํ
์คํธ ์ถ์ถ.
manifest.xml์์ ์ํธํ ๊ฐ์ง โHWPFrame.HwpObject์GetPageText๋ก ํ์ด์ง๋ณ ์ถ์ถ โ Markdown ๋ณํ. Windows + ํ์ปด ์คํผ์ค ์ค์น ํ๊ฒฝ์์ ๋ณ๋ ์ค์ ์์ด ๋์.
v2.3.0 ๋ณ๊ฒฝ์ฌํญ
- ๐ HWPML 2.x ํ์ ์ถ๊ฐ โ XML ๊ธฐ๋ฐ ํ์ปด ๋ฌธ์(
.hwpXML ๋ฐฉ์) ํ์ฑ ์ง์.npx kordoc <file.hwp>์์์ง์ํ์ง ์๋ ํ์ผ ํ์์ค๋ฅ๊ฐ ๋๋ XML ๊ธฐ๋ฐ ๊ณต๋ฌธ์๋ฅผ ์ด์ Markdown์ผ๋ก ๋ณํํ ์ ์์ต๋๋ค. HWP 5.x ๋ฐ์ด๋๋ฆฌ์ ์๋ ๊ตฌ๋ถ(XML ์๊ทธ๋์ฒ ๊ฐ์ง). - ๐งฉ ์ค์ฒฉ ํ
์ด๋ธ ๋ง์ปค โ HWPX/HWP5์์ ์
๋ด๋ถ ์ค์ฒฉ ํ
์ด๋ธ์ด ์๋ ์์น์
[์ค์ฒฉ ํ ์ด๋ธ #N]๋ง์ปค ์ฝ์ . ํฐ ์ค์ฒฉ ํ ์ด๋ธ(โฅ3ํ + โฅ2์ด)์ ๋ณ๋ ๋ธ๋ก์ผ๋ก ๋ถ๋ฆฌ, ์์ ๊ฒ์ ์ ๋ด ํํํ. HWP5๋ ๊ธฐ์กด์ ๋ด์ฉ์ด ์์ ํ ์์ค๋๋ ๊ฒ์ ๋ง์ปค๋ก ๋ณต๊ตฌ. - ๐ผ๏ธ HWPX ์ด๋ฏธ์ง ์ถ์ถ ๋ฒ๊ทธ ์์ โ
binaryItemIDRef๊ฐ ํ์ฅ์ ์์ด("image1") ์ ์ฅ๋ HWPX์์ ์ด๋ฏธ์ง ์ถ์ถ์ด ์คํจํ๋ ๋ฌธ์ ํด๊ฒฐ. ZIP ๋ด ํ์ผ๋ช regex ๋งค์นญ์ผ๋ก ๋ณต์. - ๐ PDF ๋จธ๋ฆฌ๊ธ/๋ฐ๋ฅ๊ธ ๊ฐ์ง ๊ฐ์ โ ํ ์คํธ ๋ฐ๋ณต ํจํด + y์ขํ ํด๋ฌ์คํฐ๋ง ํ์ด๋ธ๋ฆฌ๋. ํ์ด์ง๋ง๋ค ๋ฌ๋ผ์ง๋ ๋์ ๋จธ๋ฆฌ๊ธ(์ฑํฐ๋ช ๋ฑ)๋ ์์น ๊ธฐ๋ฐ์ผ๋ก ๊ฐ์ง. ๊ฐ์ง ์์ญ 10% โ 12%๋ก ํ์ฅ.
v2.2.4 ๋ณ๊ฒฝ์ฌํญ
- ๐ ์์ ์๋ ์ฑ์ฐ๊ธฐ (Form Filler) โ ๊ณต๋ฌธ์ ์์ ํ
ํ๋ฆฟ์ ๊ฐ์ ์๋์ผ๋ก ์ฑ์๋ฃ์ต๋๋ค. ๋ผ๋ฒจ-๊ฐ ์
ํจํด, ์ฒดํฌ๋ฐ์ค(
โกโโ), ๊ดํธ ๋น์นธ(์ผ๋ฐ( )ํตโ์ผ๋ฐ(3)ํต), ์ด๋ ธํ ์ด์ ((ํ์๏ผ)โ(ํ์๏ผ้)) ์ง์. - ๐๏ธ HWPX ์๋ณธ ์์ ๋ณด์กด ๋ชจ๋ โ
fillHwpx()๋ก HWPX XML์ ์ง์ ์กฐ์ํ์ฌ ๊ธ๊ผด, ํฌ๊ธฐ, ์ ๋ ฌ ๋ฑ ์๋ณธ ์์ 100% ์ ์งํ ์ฑ ๊ฐ๋ง ๊ต์ฒด. - ๐ ๋ณํฉ ์
HTML ํ
์ด๋ธ ์ถ๋ ฅ โ
colspan/rowspan์ด ์๋ ๋ณต์กํ ํ๋ฅผ GFM ๋์ HTML<table>๋ก ์ถ๋ ฅํ์ฌ ๊ตฌ์กฐ ๋ณด์กด. - ๐ง markdownToHwpx ์์ ๊ฐํ โ ์ญ๋ณํ ์ heading/bold/italic/table ๋ฑ ์์ ์ง์ ๋ํญ ๊ฐ์ .
- ๐ค MCP fill_form ๋๊ตฌ โ AI ์์ด์ ํธ๊ฐ ์์์ ์ง์ ์ฑ์ธ ์ ์๋ ์ MCP ๋๊ตฌ ์ถ๊ฐ (์ด 8๊ฐ).
v2.2.1 ๋ณ๊ฒฝ์ฌํญ
- ๐ง ๋งํฌ๋ค์ด ๋ ๋๋ง ๊ฐ์ โ GFM ํน์๋ฌธ์(
~) ์ด์ค์ผ์ดํ๋ก ์ทจ์์ ์คํด์ ๋ฐฉ์ง, ํ ์ด๋ธ ์ ๋ด|๋ฌธ์ ์ด์ค์ผ์ดํ, ์ค์ฒฉ ํ ์ด๋ธ ํ ์คํธ ๊ตฌ๋ถ์|โ/๋ณ๊ฒฝ์ผ๋ก GFM ํ์ ์ถฉ๋ ๋ฐฉ์ง. - ๐ ๋ฌธ๋จ ๊ฐ๊ฒฉ ์ ์ํ โ paragraph ๋ธ๋ก ์ฌ์ด ๋น ์ค ์ฝ์ ์ผ๋ก ๋งํฌ๋ค์ด์์ ๋ณ๋ ๋ฌธ๋จ์ผ๋ก ๋ ๋๋ง.
v2.2.0 ๋ณ๊ฒฝ์ฌํญ
- ๐ก๏ธ ๋ณด์ ๊ฐํ 7๊ฑด โ XLSX/DOCX Billion Laughs(XXE) ๋ฐฉ์ง, Watch SSRF ๋ฆฌ๋ค์ด๋ ํธยท10์ง์IPยทsymlink ์ฐจ๋จ, HWP5 lenient decompression bomb ๋ฐฉ์ง, CFB FAT ์นํฐ ์ํ, buildTableDirect ๋ฉ๋ชจ๋ฆฌ ํญ์ฃผ ๋ฐฉ์ง.
- ๐ฅ Crash ๋ฐฉ์ง โ
Math.min/max(...spread)์คํ ์ค๋ฒํ๋ก ์์ (15๊ฐ์), Watch ๋์ ์ฒ๋ฆฌ ์ ํ(MAX_CONCURRENT=3). - ๐ ์ ํ์ฑ ๊ฐ์ โ Levenshtein ๋์ผ ๊ธธ์ด ์ ์ฌ๋ 1.0 ๋ฒ๊ทธ ์์ , MCP
parse_metadataXLSX/DOCX ์ค๋ถ๋ฅ ์์ , PDF ํฐํธ ํฌ๊ธฐ ํต๊ณ ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ(40MBโ~50์ํธ๋ฆฌ). - ๐ฆ ํ์ง โ CLI JSON Uint8Array base64 ๋ณํ,
isPathTraversalํฉ๋ฒ์ ํ์ผ๋ช ์คํ ์์ .
v2.1.0 ๋ณ๊ฒฝ์ฌํญ
- ๐ ๋ํ HWPX ์ ๋ถ๋ฌธ์ ํ์ฑ โ
<p>><run>><tbl>๊ตฌ์กฐ์ ์ค์ฒฉ ํ ์ด๋ธ ํ์ฑ ๋๋ฝ ์์ . - ๐ฐ PDF 2๋จ ๋ ์ด์์ ๊ฐ์ง โ ๋ค๋จ ๋ ผ๋ฌธยท๋ณด๊ณ ์์ ์ปฌ๋ผ ๊ตฌ์กฐ๋ฅผ ๊ฐ์งํ์ฌ ์ฝ๊ธฐ ์์๋๋ก ์ถ์ถ.
- ๐ก๏ธ ์ ๋ ฅ ๊ฒ์ฆ ๊ฐํ โ ํฐํธ ํฌ๊ธฐ NaN/์์ ๊ฐ๋, colSpan/rowSpan NaN ๊ฐ๋.
v2.0 ๋ณ๊ฒฝ์ฌํญ
- ๐ ๋ฐฐํฌ์ฉ(์ด๋ ์ ํ) HWP ํ์ฑ ์ง์ โ ๊ด๊ณต์์์ ๋ฐฐํฌ์ฉ์ผ๋ก ์ ๊ทผ HWP ํ์ผ๋ ์ด์ ํ์ฑ๋ฉ๋๋ค. AES-128 ECB ๋ณตํธํ, ์์ JS ๊ตฌํ. rhwp(MIT) ์๊ณ ๋ฆฌ์ฆ ํฌํ .
- ์์๋ HWP ํ์ผ ๋ณต๊ตฌ โ ํ์ค CFB ๋ชจ๋์ด ๊ฑฐ๋ถํ๋ ํ์ผ์ ์ง์ FAT/๋๋ ํ ๋ฆฌ ํ์ฑ์ผ๋ก ๋ณต๊ตฌ. rhwp LenientCfbReader ํฌํ .
- HWP5 ๊ฐ์ฃผ/๋ฏธ์ฃผ/ํ์ดํผ๋งํฌ ์ถ์ถ โ ๊ฐ์ฃผ ๋ณธ๋ฌธ ํ ์คํธ ์ฐ๊ฒฐ, ํ์ดํผ๋งํฌ URL ์ถ์ถ ๋ฐ XSS ์ด๊ท .
- HWPX ํ ๋ณํฉ ๋ฐ๋ฆผ ์์ โ colspan/rowspan ๊ทธ๋ฆฌ๋ ๊ณ์ฐ ๋ฒ๊ทธ ์์ .
- ๋ณด์ ๊ฐํ โ CFB ์นํฐ ํฌ๊ธฐ ๊ฒ์ฆ, sanitizeHref 3์ค ๊ฒฝ๋ก ์ผ๊ด ์ ์ฉ.
v1.8.0 ๋ณ๊ฒฝ์ฌํญ
- XLSX ํ์ ์ถ๊ฐ โ Excel ์คํ๋ ๋์ํธ ํ์ฑ. ๊ณต์ ๋ฌธ์์ด, ๋ณํฉ ์ , ๋ค์ค ์ํธ ์ง์. ์ํธ๋ณ heading + table ๋ธ๋ก ์์ฑ.
- DOCX ํ์ ์ถ๊ฐ โ Word ๋ฌธ์ ํ์ฑ. ์คํ์ผ ๊ธฐ๋ฐ heading, ๋ฒํธ ๋งค๊ธฐ๊ธฐ(๋ฆฌ์คํธ), ๊ฐ์ฃผ, ํ์ดํผ๋งํฌ, ์ด๋ฏธ์ง ์ถ์ถ, vMerge/gridSpan ํ ์ด๋ธ ๋ณํฉ.
- ํ์ฑ ํ์ง ๋ํญ ๊ฐ์ โ PDF/HWPX/HWP5/XLSX ์ ํฌ๋งท ํ์ง ์ ์ 73โ93์ .
- ํ๋ก๋์
๋ฆฌ๋ทฐ 17๊ฑด ์์ โ CLI
--no-header-footerํ๋๊ทธ ๋ฐ์ ๋ฒ๊ทธ, MCP XLSX/DOCX ํ์ฅ์ ํ์ฉ, ZIP bomb ๋ณดํธ ๊ณต์ ์ ํธํ, href XSS ์ด๊ท ๊ฐํ, PDF timeout ํ์ด๋จธ ์ ๋ฆฌ, HWP5 BinData O(n) ์ต์ ํ, cluster indexOf O(nยฒ)โO(n), SSRF IPv6 ์ฐจ๋จ ๋ฑ.
v1.7.x ๋ณ๊ฒฝ์ฌํญ
- ์ด๋ฏธ์ง ์ถ์ถ (HWP/HWPX) โ ZIP ์ํธ๋ฆฌ์ HWP5 BinData ์คํธ๋ฆผ์์ ๋ฐ์ด๋๋ฆฌ ์ด๋ฏธ์ง ์ถ์ถ.
- ๋ถ๋ถ ํ์ฑ (Graceful Degradation) โ ๊ฐ๋ณ ํ์ด์ง ์คํจ๊ฐ ์ ์ฒด ํ์ฑ์ ์ค๋จํ์ง ์์.
- ์งํ๋ฅ ์ฝ๋ฐฑ โ
onProgress์ฝ๋ฐฑ. CLI์์[3/15 pages]ํํ ํ์. - ํ์ผ ๊ฒฝ๋ก ์ง์ ์
๋ ฅ โ
parse("path/to/file.hwp")๋ฌธ์์ด ์ค๋ฒ๋ก๋. - PDF ๋จธ๋ฆฌ๊ธ/๋ฐ๋ฅ๊ธ ํํฐ๋ง โ
removeHeaderFooter์ต์ . - ๋ณด์ ๊ฐํ โ ZIP bomb ์ถ์ , SSRF ๋ฐฉ์ง, XSS ๋ฐฉ์ด, ๋๋ฐ์ดํธ ๊ฐ์ง, PDF ํ์์์.
- pdfjs-dist v5 ํธํ โ constructPath ์ฐ์ฐ์ ํ์ ๋ณ๊ฒฝ ๋์.
v1.6.1 ์์ ์ฌํญ
- HWP5 ํ ์ด๋ธ ์ ์คํ์ ์์ โ LIST_HEADER ํ์ฑ ์ 2๋ฐ์ดํธ ์คํ์ ๋ฐ๋ฆผ์ผ๋ก rowAddr๋ฅผ colSpan์ผ๋ก ์๋ชป ์ฝ๋ ์น๋ช ์ ๋ฒ๊ทธ ์์ . 3์ด ํ ์ด๋ธ์ด 6์ด๋ก ๋ปฅํ๊ธฐ๋๋ ๋ฌธ์ ํด๊ฒฐ. colAddr/rowAddr ๊ธฐ๋ฐ ์ง์ ๋ฐฐ์น๋ก ๋ณํฉ ํ ์ด๋ธ ์ ํ๋ ํฅ์.
- HWP5 TAB ์ ์ด๋ฌธ์ ์์ โ TAB(0x0009) ์ธ๋ผ์ธ ์ปจํธ๋กค์ 14๋ฐ์ดํธ ํ์ฅ ๋ฐ์ดํฐ ์คํต ๋๋ฝ์ผ๋ก
เฃฤ์ฐ๋ ๊ธฐ ๋ฌธ์๊ฐ ์ถ๋ ฅ๋๋ ๋ฒ๊ทธ ์์ .
v1.6.0 ๊ธฐ๋ฅ
- ํด๋ฌ์คํฐ ๊ธฐ๋ฐ ํ ์ด๋ธ ๊ฐ์ง (PDF) โ ์ ์๋ PDF์์ ํ ์คํธ ์ ๋ ฌ ํจํด์ผ๋ก ํ ์ด๋ธ ๊ตฌ์กฐ ์ถ๋ก . baseline ๊ทธ๋ฃนํ + X์ขํ ํด๋ฌ์คํฐ๋ง์ผ๋ก 2์ด ์ด์ ํ ์ด๋ธ ๊ฐ์ง. ์ ๊ธฐ๋ฐ ๊ฐ์ง๊ฐ ์คํจํ ๊ฒฝ์ฐ์ ์ค๊ฐ ๊ณ์ธต fallback.
- ํ๊ตญ์ด ํน์ ํ
์ด๋ธ ๊ฐ์ง โ
๊ตฌ๋ถ/ํญ๋ชฉ/์ข ๋ฅ/๊ธฐ์ค๋ฑ ํ๊ตญ ๊ณต๋ฌธ์ key-value ํจํด์ ์๋์ผ๋ก 2์ด ํ ์ด๋ธ๋ก ๋ณํ. - ํ๊ตญ์ด ์ด์ ๋๊น ๋ณต์ โ PDF ์ ๋ด ํ๊ธ ๋ฌธ์๋ณ ๋ ๋๋ง์ผ๋ก ์ธํ ๋ฏธ์ธ ๊ฐญ ์ฒ๋ฆฌ ๊ฐ์ . ์ ์ค๋ฐ๊ฟ ๋ณํฉ ์๊ณ๊ฐ 8์๋ก ํ์ฅ, 1๊ธ์ ์กฐ์ฌ ์๋ ์ฐ๊ฒฐ.
- ๋น ํ ์ด๋ธ ํํฐ๋ง โ ์ฅ์์ฉ ์ ์์ ์๊ธด ๋น ํ ์ด๋ธ ์๋ ์ ๊ฑฐ.
v1.5.0 ๊ธฐ๋ฅ
- ์ ๊ธฐ๋ฐ ํ ์ด๋ธ ๊ฐ์ง (PDF) โ OpenDataLoader ํต์ฌ ์๊ณ ๋ฆฌ์ฆ ํฌํ . PDF ๊ทธ๋ํฝ ๋ช ๋ น์์ ์ํ/์์ง ์ ์ ์ถ์ถํ๊ณ , ๊ต์ฐจ์ ์ผ๋ก ๊ทธ๋ฆฌ๋ ๊ตฌ์ฑ, bbox overlap์ผ๋ก ํ ์คํธโ์ ๋งคํ. colspan/rowspan ์๋ ๊ฐ์ง. ์ ์๋ PDF๋ ๊ธฐ์กด ํด๋ฆฌ์คํฑ fallback.
- IRBlock v2 โ 6๊ฐ์ง ๋ธ๋ก ํ์
:
heading,paragraph,table,list,image,separator. ์ ํ๋:bbox,style,pageNumber,level,href,footnoteText. - ParseResult v2 โ
outline(๋ฌธ์ ๊ตฌ์กฐ),warnings(์คํต๋ ์์, ์จ๊น ํ ์คํธ) ํ๋ ์ถ๊ฐ. - PDF ๊ฐ์ โ XY-Cut ์ฝ๊ธฐ ์์, ํฐํธ ํฌ๊ธฐ ๊ธฐ๋ฐ ํค๋ฉ ๊ฐ์ง, hidden text ํํฐ๋ง (ํ๋กฌํํธ ์ธ์ ์ ๋ฐฉ์ด), ๋ชจ๋ ๋ธ๋ก์ ๋ฐ์ด๋ฉ ๋ฐ์ค.
- HWP5 ๊ฐ์ โ CHAR_SHAPE ํ์ฑ, ์คํ์ผ ๊ธฐ๋ฐ ํค๋ฉ ๊ฐ์ง, OLE/์ด๋ฏธ์ง ์คํต ๊ฒฝ๊ณ .
- HWPX ๊ฐ์ โ header.xml ์คํ์ผ ํ์ฑ, ํ์ดํผ๋งํฌ/๊ฐ์ฃผ ์ถ์ถ.
- ๋ฆฌ์คํธ ๊ฐ์ง โ ํ ์ด๋ธ ๋ค ๋ฒํธ ๋ฌธ๋จ์ ordered list ๋ธ๋ก์ผ๋ก ์๋ ๋ณํ.
- MCP ์๋ฒ โ parse_document ์๋ต์
outline,warningsํฌํจ.
v1.4.x ๊ธฐ๋ฅ
- ๋ฌธ์ ๋น๊ต (Diff) โ IR ๋ ๋ฒจ ๋ธ๋ก ๋น๊ต๋ก ์ ๊ตฌ๋์กฐํ ์์ฑ. HWPโHWPX ํฌ๋ก์ค ํฌ๋งท ์ง์.
- ์์ ์ธ์ โ ๊ณต๋ฌธ์ ํ ์ด๋ธ์์ label-value ์ ์๋ ์ถ์ถ. ์ฑ๋ช , ์์, ์ ํ๋ฒํธ ๋ฑ.
- ๊ตฌ์กฐํ ํ์ฑ โ
IRBlock[]๊ณผDocumentMetadata์ ์ง์ ์ ๊ทผ. ๋งํฌ๋ค์ด ๋์ด์ ๋ฐ์ดํฐ ํ์ฉ. - ํ์ด์ง ๋ฒ์ โ
parse(buffer, { pages: "1-3" })โ ํ์ํ ํ์ด์ง๋ง ๋น ๋ฅด๊ฒ. - Markdown โ HWPX โ ์ญ๋ณํ. AI๊ฐ ์์ฑํ ๋ด์ฉ์ ๋ฐ๋ก ๊ณต๋ฌธ์๋ก.
- OCR ์ฐ๋ โ ์ด๋ฏธ์ง ๊ธฐ๋ฐ PDF๋ ํ ์คํธ ์ถ์ถ (Tesseract, Claude Vision ๋ฑ ํ๋ก๋ฐ์ด๋ ์ง์ ์ ๊ณต).
- Watch ๋ชจ๋ โ
kordoc watch ./์์ ํจ -d ./๋ณํ๊ฒฐ๊ณผ --webhook https://... - MCP 7๊ฐ ๋๊ตฌ โ parse_document, detect_format, parse_metadata, parse_pages, parse_table, compare_documents, parse_form
- ์๋ฌ ์ฝ๋ โ
"ENCRYPTED","ZIP_BOMB","IMAGE_BASED_PDF"๋ฑ ๊ตฌ์กฐํ๋ ์๋ฌ ํธ๋ค๋ง
์ค์น
npm install kordoc
# PDF ํ์ฑ์ด ํ์ํ๋ฉด (์ ํ)
npm install pdfjs-dist
๋น ๋ฅธ ์์
๋ฌธ์ ํ์ฑ
import { parse } from "kordoc"
import { readFileSync } from "fs"
const buffer = readFileSync("์ฌ์
๊ณํ์.hwpx")
const result = await parse(buffer.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.buffer, {
์ฑ๋ช
: "ํ๊ธธ๋",
์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ: "900101-1234567",
์ฃผ์: "์์ธํน๋ณ์ ๊ด์ง๊ตฌ ๋ฅ๋๋ก 120",
}, { format: "hwpx-preserve" })
writeFileSync("์ ์ฒญ์_์์ฑ์๋ฃ.hwpx", Buffer.from(result.buffer!))
// result.filled โ [{ label: "์ฑ๋ช
", value: "ํ๊ธธ๋" }, ...]
// result.unmatched โ ๋งค์นญ ์คํจํ ํค ๋ชฉ๋ก
HWPX ์์ฑ (์ญ๋ณํ)
import { markdownToHwpx } from "kordoc"
const hwpxBuffer = await markdownToHwpx("# ์ ๋ชฉ\n\n๋ณธ๋ฌธ ํ
์คํธ\n\n| ์ด๋ฆ | ์ง๊ธ |\n| --- | --- |\n| ํ๊ธธ๋ | ๊ณผ์ฅ |")
writeFileSync("์ถ๋ ฅ.hwpx", Buffer.from(hwpxBuffer))
ํ์ด์ง ๋ฒ์ ์ง์
const result = await parse(buffer, { pages: "1-3" }) // 1~3 ํ์ด์ง๋ง
const result = await parse(buffer, { pages: [1, 5, 10] }) // ํน์ ํ์ด์ง
OCR (์ด๋ฏธ์ง PDF)
const result = await parse(buffer, {
ocr: async (pageImage, pageNumber, mimeType) => {
return await myOcrService.recognize(pageImage)
}
})
CLI
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 watch ./์์ ํจ -d ./๋ณํ๊ฒฐ๊ณผ # ํด๋ ๊ฐ์ ๋ชจ๋
npx kordoc watch ./๋ฌธ์ --webhook https://api/hook # ์นํ
์๋ฆผ
MCP ์๋ฒ (Claude / Cursor / Windsurf)
์๋ ์ค์น (์ถ์ฒ):
npx -y kordoc setup
๋ํํ์ผ๋ก AI ํด๋ผ์ด์ธํธ๋ฅผ ๊ฐ์งํด ์ค์ ํ์ผ์ ์๋ ํจ์น. Windows ์์ cmd /c npx ๋ํ๋ ์๋. ์์ธ๋ ์ 30์ด ์ค์น ์น์
.
์๋ ๋ฑ๋ก (macOS / Linux):
{
"mcpServers": {
"kordoc": {
"command": "npx",
"args": ["-y", "kordoc", "mcp"]
}
}
}
์๋ ๋ฑ๋ก (Windows โ Claude Desktop ์ด .cmd ๋ฅผ ๋ชป ์ฐพ์ ๋):
{
"mcpServers": {
"kordoc": {
"command": "cmd",
"args": ["/c", "npx", "-y", "kordoc", "mcp"]
}
}
}
8๊ฐ ๋๊ตฌ:
| ๋๊ตฌ | ์ค๋ช |
|---|---|
parse_document | HWP/HWPX/PDF/XLSX/DOCX โ ๋งํฌ๋ค์ด (๋ฉํ๋ฐ์ดํฐ ํฌํจ) |
detect_format | ๋งค์ง ๋ฐ์ดํธ๋ก ํฌ๋งท ๊ฐ์ง |
parse_metadata | ๋ฉํ๋ฐ์ดํฐ๋ง ๋น ๋ฅด๊ฒ ์ถ์ถ |
parse_pages | ํน์ ํ์ด์ง ๋ฒ์๋ง ํ์ฑ |
parse_table | N๋ฒ์งธ ํ ์ด๋ธ๋ง ์ถ์ถ |
compare_documents | ๋ ๋ฌธ์ ๋น๊ต (ํฌ๋ก์ค ํฌ๋งท) |
parse_form | ์์ ํ๋๋ฅผ JSON์ผ๋ก ์ถ์ถ |
fill_form | ์์ ํ ํ๋ฆฟ์ ๊ฐ ์ฑ์ฐ๊ธฐ (HWPX ์๋ณธ ์์ ๋ณด์กด) |
API
ํต์ฌ ํจ์
| ํจ์ | ์ค๋ช |
|---|---|
parse(buffer, options?) | ํฌ๋งท ์๋ ๊ฐ์ง โ Markdown + IRBlock[] |
parseHwpx(buffer, options?) | HWPX ์ ์ฉ |
parseHwp(buffer, options?) | HWP 5.x ์ ์ฉ |
parsePdf(buffer, options?) | PDF ์ ์ฉ |
parseXlsx(buffer, options?) | XLSX ์ ์ฉ |
parseDocx(buffer, options?) | DOCX ์ ์ฉ |
parseHwpml(buffer, options?) | HWPML (XML ๊ธฐ๋ฐ HWP) ์ ์ฉ |
detectFormat(buffer) | "hwpx" | "hwp" | "hwpml" | "pdf" | "xlsx" | "docx" | "unknown" |
๊ณ ๊ธ ํจ์
| ํจ์ | ์ค๋ช |
|---|---|
compare(bufferA, bufferB, options?) | IR ๋ ๋ฒจ ๋ฌธ์ ๋น๊ต |
extractFormFields(blocks) | IRBlock[]์์ ์์ ํ๋ ์ธ์ |
fillForm(buffer, values, options?) | ์์ ํ ํ๋ฆฟ์ ๊ฐ ์ฑ์ฐ๊ธฐ (markdown/hwpx/hwpx-preserve) |
fillFormFields(blocks, values) | IRBlock[] ๊ธฐ๋ฐ ํ๋ ๊ฐ ๊ต์ฒด |
fillHwpx(buffer, values) | HWPX XML ์ง์ ์กฐ์ (์๋ณธ ์์ ๋ณด์กด) |
markdownToHwpx(markdown) | Markdown โ HWPX ์ญ๋ณํ |
blocksToMarkdown(blocks) | IRBlock[] โ Markdown ๋ฌธ์์ด |
ํ์
import type {
ParseResult, ParseSuccess, ParseFailure, FileType,
IRBlock, IRTable, IRCell, CellContext,
DocumentMetadata, ParseOptions, ErrorCode,
DiffResult, BlockDiff, CellDiff, DiffChangeType,
FormField, FormResult, FillResult, HwpxFillResult, FillOutputFormat,
OcrProvider, WatchOptions,
} from "kordoc"
์ง์ ํฌ๋งท
| ํฌ๋งท | ์์ง | ํน์ง |
|---|---|---|
| HWPX (ํ์ปด 2020+) | ZIP + XML DOM | ๋งค๋ํ์คํธ, ์ค์ฒฉ ํ ์ด๋ธ, ๋ณํฉ ์ , ์์ ZIP ๋ณต๊ตฌ |
| HWP 5.x (ํ์ปด ๋ ๊ฑฐ์) | OLE2 + CFB | ๋ฐฐํฌ์ฉ ๋ณตํธํ, ์์ CFB ๋ณต๊ตฌ, ๊ฐ์ฃผ/ํ์ดํผ๋งํฌ, 21์ข ์ ์ด๋ฌธ์, ์ด๋ฏธ์ง ์ถ์ถ |
| HWPML 2.x (XML ๊ธฐ๋ฐ HWP) | XML DOM | HeadingType ๊ธฐ๋ฐ ํค๋ฉ ๊ฐ์ง, ๋ณํฉ ์ , DoS ๋ฐฉ์ด |
| pdfjs-dist | ์ ๊ธฐ๋ฐ ํ ์ด๋ธ, XY-Cut ์ฝ๊ธฐ ์์, ํค๋ฉ ๊ฐ์ง, OCR | |
| XLSX (Excel) | ZIP + XML DOM | ๊ณต์ ๋ฌธ์์ด, ๋ณํฉ ์ , ๋ค์ค ์ํธ, ์์ ํ์ |
| DOCX (Word) | ZIP + XML DOM | ์คํ์ผ heading, ๋ฒํธ ๋งค๊ธฐ๊ธฐ, ๊ฐ์ฃผ, ์ด๋ฏธ์ง ์ถ์ถ |
๋ณด์
ํ๋ก๋์ ๊ธ ๋ณด์ ๊ฐํ: ZIP bomb ๋ฐฉ์ง, XXE/Billion Laughs ๋ฐฉ์ง, ์์ถ ํญํ ๋ฐฉ์ง, ๊ฒฝ๋ก ์ํ ์ฐจ๋จ, MCP ์๋ฌ ์ ์ , ํ์ผ ํฌ๊ธฐ ์ ํ(500MB). ์์ธํ ๋ด์ฉ์ SECURITY.md ์ฐธ์กฐ.
๋ง๋ ์ฌ๋
๋ํ๋ฏผ๊ตญ ์ง๋ฐฉ๊ณต๋ฌด์. ๊ด์ง๊ตฌ์ฒญ์์ 7๋ ๊ฐ HWP ํ์ผ๊ณผ ์ธ์ฐ๋ค๊ฐ ์ด๊ฑธ ๋ง๋ค์์ต๋๋ค. 5๊ฐ ๊ณต๊ณต ํ๋ก์ ํธ์์ ์์ฒ ๊ฑด์ ์ค์ ๊ด๊ณต์ ๋ฌธ์๋ฅผ ํ์ฑํ๋ฉฐ ๊ฒ์ฆํ์ต๋๋ค.
๋ผ์ด์ ์ค
์ด ํ๋ก์ ํธ๋ ์๋ ์คํ์์ค๋ฅผ ํฌํจํฉ๋๋ค:
- rhwp (MIT, edwardkim) โ HWP5 ๋ฐฐํฌ์ฉ ๋ณตํธํ ๋ฐ lenient CFB ํ์ฑ ์๊ณ ๋ฆฌ์ฆ
- OpenDataLoader PDF (Apache 2.0, Hancom Inc.) โ PDF ํ ์ด๋ธ ๊ฐ์ง ์๊ณ ๋ฆฌ์ฆ
- cfb (Apache 2.0, SheetJS) โ HWP5 OLE2 ์ปจํ ์ด๋ ํ์ฑ
- pdfjs-dist (Apache 2.0, Mozilla) โ PDF ํ ์คํธ ์ถ์ถ
- JSZip (MIT, Stuart Knightley ์ธ) โ ZIP ๊ธฐ๋ฐ ํฌ๋งท ํ์ฑ
์์ธํ ๋ด์ฉ์ NOTICE ํ์ผ์ ์ฐธ์กฐํ์ธ์.
