HwpForge
Rust library for programmatic control of Korean HWPX documents โ MarkdownโHWPX conversion, JSON round-trip editing, MCP server for AI agents ๐ฅ
Install / Use
/learn @ai-screams/HwpForgeQuality Score
Category
Development & EngineeringSupported Platforms
README
HwpForge ๐ฅ
<div align="center">Rust๋ก ํ๊ธ(HWP/HWPX) ๋ฌธ์๋ฅผ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์ ์ด
Hancom ํ๊ธ ํ์ผ ์ฝ๊ธฐ, ์ฐ๊ธฐ, ๋ณํ
HwpForge๋?
HwpForge๋ HWPX ๋ฌธ์(ZIP + XML, KS X 6101)๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํ ์คํ์์ค ์์ Rust ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ํ๊ตญ์์ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ์๋ํ๋ก์ธ์์ธ Hancom ํ๊ธ์ ์ต์ ํฌ๋งท์ ์ง์ํฉ๋๋ค.
์ง์ ๋ฒ์
| ํ๊ธ ๋ฒ์ | ํฌ๋งท | ์ฝ๊ธฐ | ์ฐ๊ธฐ | ์คํ์ผ ์ธํธ | | ----------------- | ------------ | ---- | ---- | ------------------------------ | | ํ๊ธ 2014 ~ 2020 | HWPX (.hwpx) | โ | โ | Classic (18 styles) | | ํ๊ธ 2022 ~ 2024 | HWPX (.hwpx) | โ | โ | Modern (22 styles, ๊ธฐ๋ณธ๊ฐ) | | ํ๊ธ 2025+ | HWPX (.hwpx) | โ | โ | Latest (23 styles) | | ํ๊ธ 97 ~ 2010 | HWP5 (.hwp) | โ | โ | โ |
- HWPX: OWPML ๊ตญ๊ฐํ์ค (KS X 6101) ๊ธฐ๋ฐ, ZIP + XML ์ปจํ ์ด๋
- HWP5: ๊ตฌํ ๋ฐ์ด๋๋ฆฌ ํฌ๋งท. ํ์ฌ๋ CLI ์ค์ฌ์ ์ฝ๊ธฐ/์ ๊ฒ/์ฌ์ถ๋ ฅ ๊ฒฝ๋ก๋ฅผ ์ ๊ณตํฉ๋๋ค (
convert-hwp5,audit-hwp5,census-hwp5) - ์คํ์ผ ์ธํธ๋
HancomStyleSetenum์ผ๋ก ์ ํ ๊ฐ๋ฅ (๊ธฐ๋ณธ: Modern)
LLM-first ์ค๊ณ ๐ฅ โ AI ์นํ์ ์ธ Markdown๊ณผ ๊ณต์ ํ๊ธ ๋ฌธ์ ํฌ๋งท(HWPX), ๋ ์ธ๊ณ๋ฅผ ์์ฐ์ค๋ฝ๊ฒ ์์ต๋๋ค. LLM์ด Markdown์ผ๋ก ์์ฑํ ๋ด์ฉ์ ๊ณต๋ฌธ์ ๊ท๊ฒฉ์ HWPX๋ก ์ปดํ์ผ๋๊ณ ๐, ๋ฐ๋๋ก ๊ธฐ์กด HWPX ๋ฌธ์๋ AI๊ฐ ์ฝ๊ฒ ์ฝ์ ์ ์๋ ๊ตฌ์กฐ๋ก ๊บผ๋ผ ์ ์์ต๋๋ค โ๏ธ.
- ๐ HWPX ์์ ๊ฐ์ด๋ ๋ค์ด๋ก๋ โ HwpForge API๋ก ์์ฑํ 4์น์ ๋ฐ๋ชจ ๋ฌธ์ (ํ๊ธ์์ ์ด์ด๋ณด์ธ์)
- HWPX Reader for AI โ ๊ธฐ์กด ํ๊ธ ๋ฌธ์(.hwpx)๋ฅผ Markdown์ผ๋ก ๋ณํํ์ฌ LLM์ด ์ฆ์ ์ดํด ๊ฐ๋ฅ
- Full HWPX codec โ HWPX ํ์ผ์ ์์ค ์์ด ๋์ฝ๋ฉ/์ธ์ฝ๋ฉ (lossless roundtrip)
- Markdown bridge โ GFM Markdown๊ณผ HWPX ๊ฐ ์๋ฐฉํฅ ๋ณํ (์ฝ๊ธฐ + ์ฐ๊ธฐ)
- YAML style template โ Figma Design Token์ฒ๋ผ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์คํ์ผ ์ ์ (ํฐํธ, ํฌ๊ธฐ, ์์)
- Type-safe API โ branded index, typestate validation, zero unsafe code
๋น ๋ฅธ ์์
์ค์น
# Cargo.toml์ ์ถ๊ฐ
cargo add hwpforge
# Markdown ์ง์ ํฌํจ
cargo add hwpforge --features full
๋๋ Cargo.toml์ ์ง์ ์ถ๊ฐ:
[dependencies]
hwpforge = "0.5"
๐จ Hammer โ CLI๋ก ์์ํ๊ธฐ
CLI ๋๊ตฌ hwpforge(Hammer)๋ฅผ ์ค์นํ๋ฉด ํฐ๋ฏธ๋์์ ๋ฐ๋ก ๋ฌธ์๋ฅผ ์์ฑํ๊ณ ํธ์งํ ์ ์์ต๋๋ค.
cargo install hwpforge-bindings-cli
# Markdown โ HWPX ๋ณํ
hwpforge convert report.md -o report.hwpx
# HWPX ๊ตฌ์กฐ ํ์ธ
hwpforge inspect report.hwpx
# HWPX โ Markdown ๋ณํ (AI๊ฐ ํ๊ธ ๋ฌธ์ ์ฝ๊ธฐ)
hwpforge to-md report.hwpx -o report.md
# HWPX โ JSON ์ถ์ถ (AI ํธ์ง์ฉ)
hwpforge to-json report.hwpx --section 0 > section0.json
# JSON โ HWPX ์ง์ ์์ฑ
hwpforge from-json section0.json -o new.hwpx
# JSON์ผ๋ก ์น์
๊ต์ฒด
hwpforge patch report.hwpx --section 0 < modified.json -o updated.hwpx
# JSON Schema ์ถ๋ ฅ (AI agent์ฉ)
hwpforge schema document
AI-first ์ค๊ณ: CLI๋ AI agent(Claude Code ๋ฑ)๊ฐ ์ฃผ ์ฌ์ฉ์์ ๋๋ค. Markdown์ผ๋ก ๋ฌธ์๋ฅผ ์์ฑํ ๋ค, JSON round-trip์ผ๋ก ๊ธฐ์กด ์คํ์ผ์ ๋ณด์กดํ๋ฉด์ section ๋จ์๋ก ์ ๋ฐํ๊ฒ ํธ์งํ ์ ์์ต๋๋ค.
--jsonํ๋๊ทธ๋ก ๋ชจ๋ ๋ช ๋ น์ด๊ฐ machine-readable ์ถ๋ ฅ์ ์ง์ํฉ๋๋ค.
โ๏ธ Anvil โ MCP Server (Beta)๋ก AI๊ฐ ์ง์ ํ๊ธ ๋ฌธ์๋ฅผ ๋ค๋ฃจ๋ค
Claude Code, Codex CLI, Claude, ChatGPT, Cursor, Antigravity ๋ฑ MCP ์ง์ AI ๋๊ตฌ์์ ํ๊ธ ๋ฌธ์๋ฅผ ์ง์ ์์ฑํ๊ณ ํธ์งํ ์ ์์ต๋๋ค. ํ์ฌ MCP surface๋ ๋ฒ ํ์ด๋ฉฐ, HWP5 ๊ฒฝ๋ก๋ MCP๊ฐ ์๋๋ผ CLI workflow๋ฅผ ์ฐ์ ํฉ๋๋ค. "๋ณด๊ณ ์ ๋ง๋ค์ด์ค"๋ผ๊ณ ๋งํ๋ฉด, AI๊ฐ ์์์ .hwpx ํ์ผ์ ๋๋ฑ ๋ง๋ค์ด๋
๋๋ค.
AI ๋๊ตฌ์ ๋ฑ๋ก
ํ ์ค์ด๋ฉด ์ค์น + ๋ฑ๋ก์ด ๋๋ฉ๋๋ค. npm์ npx -y๊ฐ ์๋์ผ๋ก ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ค์ด๋ก๋ํฉ๋๋ค.
# npm (๊ถ์ฅ โ Rust ํด์ฒด์ธ ๋ถํ์)
claude mcp add hwpforge -- npx -y @hwpforge/mcp
# Cargo (Rust ๊ฐ๋ฐ์์ฉ)
cargo install hwpforge-bindings-mcp && claude mcp add hwpforge hwpforge-mcp
# ๋ชจ๋ ํ๋ก์ ํธ์์ ์ฌ์ฉ (๊ธ๋ก๋ฒ)
claude mcp add --global hwpforge -- npx -y @hwpforge/mcp
</details>
<details>
<summary><strong>Codex CLI</strong> (ํฐ๋ฏธ๋)</summary>
~/.codex/config.toml์ ์ถ๊ฐ:
[mcp_servers.hwpforge]
command = "npx"
args = ["-y", "@hwpforge/mcp"]
๋๋ CLI๋ก:
codex mcp add hwpforge -- npx -y @hwpforge/mcp
</details>
<details>
<summary><strong>Claude Desktop</strong> (์ฑ)</summary>
์ค์ ํ์ผ์ ํธ์งํฉ๋๋ค:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"hwpforge": {
"command": "npx",
"args": ["-y", "@hwpforge/mcp"]
}
}
}
</details>
<details>
<summary><strong>ChatGPT Desktop</strong> (์ฑ)</summary>
Settings โ Tools โ Add MCP Server์์:
- Name:
hwpforge - Command:
npx -y @hwpforge/mcp
๋๋ ์ค์ ํ์ผ์ ์ง์ ํธ์ง:
{
"mcpServers": {
"hwpforge": {
"command": "npx",
"args": ["-y", "@hwpforge/mcp"]
}
}
}
</details>
<details>
<summary><strong>Cursor</strong> (์๋ํฐ)</summary>
ํ๋ก์ ํธ ๋ฃจํธ์ .cursor/mcp.json ์์ฑ:
{
"mcpServers": {
"hwpforge": {
"command": "npx",
"args": ["-y", "@hwpforge/mcp"]
}
}
}
</details>
<details>
<summary><strong>Antigravity</strong> (์๋ํฐ)</summary>
... ๋๋กญ๋ค์ด โ MCP Store โ Manage MCP Servers โ View raw config (mcp_config.json)์ ์ถ๊ฐ:
{
"mcpServers": {
"hwpforge": {
"command": "npx",
"args": ["-y", "@hwpforge/mcp"]
}
}
}
</details>
๋ฑ๋กํ๋ฉด 9๊ฐ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค
| ๋๊ตฌ | ํ๋ ์ผ | ํ๋ง๋ |
| -------------------- | ----------------------- | ------------------------------------ |
| hwpforge_convert | Markdown โ HWPX ๋ณํ | "์ด ๋งํฌ๋ค์ด์ ํ๊ธ ํ์ผ๋ก!" |
| hwpforge_inspect | HWPX ๊ตฌ์กฐ ํ์ธ | "์ด ๋ฌธ์ ๋ญ๊ฐ ๋ค์ด์์ด?" |
| hwpforge_to_json | HWPX โ JSON ์ถ์ถ | "์ด ์น์
๋ด์ฉ ์ข ๊บผ๋ด๋ด" |
| hwpforge_patch | JSON์ผ๋ก ์น์
๊ต์ฒด | "์ด ๋ถ๋ถ๋ง ๋ฐ๊ฟ์ ๋ค์ ์ ์ฅํด" |
| hwpforge_templates | ์คํ์ผ ํ๋ฆฌ์
์กฐํ | "์ด๋ค ํ
ํ๋ฆฟ ์ธ ์ ์์ด?" |
| hwpforge_validate | HWPX ๊ตฌ์กฐ/๋ฌด๊ฒฐ์ฑ ๊ฒ์ฆ | "์ด ํ์ผ ๋ฌธ์ ์๋์ง ํ์ธํด" |
| hwpforge_restyle | ์คํ์ผ ํ๋ฆฌ์
์ผ๊ด ์ ์ฉ | "์ด ๋ฌธ์ ํฐํธ ๋ฐ๊ฟ์ค" |
| hwpforge_from_json | JSON โ HWPX ์ง์ ์์ฑ | "์ด JSON์ผ๋ก ํ๊ธ ํ์ผ ๋ง๋ค์ด" |
| hwpforge_to_md | HWPX โ Markdown ๋ณํ | "์ด ํ๊ธ ๋ฌธ์๋ฅผ Markdown์ผ๋ก ๊บผ๋ด์ค" |
์ ๋ฐ์ดํธ / ์ญ์
npm์ npx -y๊ฐ ํญ์ ์ต์ ๋ฒ์ ์ ๊ฐ์ ธ์ค๋ฏ๋ก ๋ณ๋ ์
๋ฐ์ดํธ๊ฐ ํ์ ์์ต๋๋ค.
# Cargo ์ฌ์ฉ์๋ง ํด๋น
cargo install hwpforge-bindings-mcp --force # ์
๋ฐ์ดํธ
cargo uninstall hwpforge-bindings-mcp # ์ญ์
์ MCP? CLI(Hammer)๋ AI๊ฐ
bash๋ช ๋ น์ ์คํํด์ผ ํ์ง๋ง, MCP(Anvil)๋ AI๊ฐ ๋ค์ดํฐ๋ธ ๋๊ตฌ๋ก ์ง์ ํธ์ถํฉ๋๋ค. ํ์ผ ๊ฒฝ๋ก ํ์ฑ๋, stdout ํด์๋ ํ์ ์์ต๋๋ค. JSON-RPC๋ก ์์ฒญํ๋ฉด ๊ตฌ์กฐํ๋ JSON์ผ๋ก ์๋ต โ ๊น๋ํฉ๋๋ค.
๐จ ๋ฌธ์ ์์ฑ
use hwpforge::core::{Document, Draft, Paragraph, Run, Section, PageSettings};
use hwpforge::foundation::{CharShapeIndex, ParaShapeIndex};
let mut doc = Document::<Draft>::new();
doc.add_section(Section::with_paragraphs(
vec![Paragraph::with_runs(
vec![Run::text("Hello, ํ๊ธ!", CharShapeIndex::new(0))],
ParaShapeIndex::new(0),
)],
PageSettings::a4(),
));
โ๏ธ HWPX๋ก ์ธ์ฝ๋ฉ
use hwpforge::hwpx::{HwpxEncoder, HwpxStyleStore};
use hwpforge::core::ImageStore;
let validated = doc.validate().unwrap();
let style_store = HwpxStyleStore::with_default_fonts("ํจ์ด๋กฌ๋ฐํ");
let image_store = ImageStore::new();
let bytes = HwpxEncoder::encode(&validated, &style_store, &image_store).unwrap();
std::fs::write("output.hwpx", &bytes).unwrap();
โ๏ธ HWPX ๋์ฝ๋ฉ
use hwpforge::hwpx::HwpxDecoder;
let result = HwpxDecoder::decode_file("input.hwpx").unwrap();
println!("์น์
์: {}", result.document.sections().len());
โ๏ธ HWPX โ Markdown ๋ณํ (AI๊ฐ ํ๊ธ ๋ฌธ์ ์ฝ๊ธฐ)
<div align="center"> <table> <tr> <td align="center"><strong>๐ ํ๊ธ ์๋ณธ (.hwpx)</strong></td> <td align="center"><strong>๐ Markdown ๋ณํ ๊ฒฐ๊ณผ</strong></td> </tr> <tr> <td><img src="https://raw.githubusercontent.com/ai-screams/HwpForge/main/assets/hwpx-original.png" width="400" alt="ํ๊ธ ์๋ณธ ๋ฌธ์"></td> <td><img src="https://raw.githubusercontent.com/ai-screams/HwpForge/main/assets/hwpx-to-md-result.png" width="400" alt="Markdown ๋ณํ ๊ฒฐ๊ณผ"></td> </tr> </table> </div>use hwpforge::hwpx::HwpxDecoder;
use hwpforge::md::MdEncoder;
let decoded = HwpxDecoder::decode_file("government_report.hwpx").unwrap();
let validated = decoded.document.validate().unwrap();
let markdown =
