HwpForge
Health Uyari
- License รขโฌโ License: Apache-2.0
- Description รขโฌโ Repository has a description
- Active repo รขโฌโ Last push 0 days ago
- Low visibility รขโฌโ Only 7 GitHub stars
Code Gecti
- Code scan รขโฌโ Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
- Permissions รขโฌโ No dangerous permissions requested
This tool is a Rust library and MCP server designed for the programmatic creation, reading, and conversion of Korean Hancom (HWP/HWPX) documents. It enables AI agents and developers to seamlessly convert Markdown to HWPX and perform JSON round-trip editing on these files.
Security Assessment
The overall risk is rated as Low. The automated code scan reviewed 12 files and found no dangerous patterns. It does not request any dangerous system permissions, shows no evidence of making unauthorized network requests, and contains no hardcoded secrets or shell execution commands. Because it is written in Rust, it benefits from strong memory safety guarantees, further reinforced by the project's strict "unsafe-forbidden" policy. The primary concern is that as a document parser, it could theoretically be exposed to malformed or malicious files, but the underlying code itself appears safe and non-invasive.
Quality Assessment
The project is in excellent health and demonstrates strong engineering practices. It is actively maintained, with repository activity as recent as today. It is well-documented, thoroughly tested (claiming over 2,200 passed tests and 92% code coverage), and properly licensed under the permissive Apache-2.0 and MIT licenses. The only notable drawback is its low current visibility, boasting only 7 GitHub stars. Consequently, the community trust level is high from a code-quality standpoint, but low in terms of widespread real-world battle-testing.
Verdict
Safe to use, though developers should remain aware that the project is still early in its community adoption lifecycle.
Rust library for programmatic control of Korean HWPX documents โ MarkdownโHWPX conversion, JSON round-trip editing, MCP server for AI agents ๐ฅ
HwpForge ๐ฅ
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
Codex CLI (ํฐ๋ฏธ๋)
~/.codex/config.toml์ ์ถ๊ฐ:
[mcp_servers.hwpforge]
command = "npx"
args = ["-y", "@hwpforge/mcp"]
๋๋ CLI๋ก:
codex mcp add hwpforge -- npx -y @hwpforge/mcp
Claude Desktop (์ฑ)
์ค์ ํ์ผ์ ํธ์งํฉ๋๋ค:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"hwpforge": {
"command": "npx",
"args": ["-y", "@hwpforge/mcp"]
}
}
}
ChatGPT Desktop (์ฑ)
Settings โ Tools โ Add MCP Server์์:
- Name:
hwpforge - Command:
npx -y @hwpforge/mcp
๋๋ ์ค์ ํ์ผ์ ์ง์ ํธ์ง:
{
"mcpServers": {
"hwpforge": {
"command": "npx",
"args": ["-y", "@hwpforge/mcp"]
}
}
}
Cursor (์๋ํฐ)
ํ๋ก์ ํธ ๋ฃจํธ์ .cursor/mcp.json ์์ฑ:
{
"mcpServers": {
"hwpforge": {
"command": "npx",
"args": ["-y", "@hwpforge/mcp"]
}
}
}
Antigravity (์๋ํฐ)
... ๋๋กญ๋ค์ด โ MCP Store โ Manage MCP Servers โ View raw config (mcp_config.json)์ ์ถ๊ฐ:
{
"mcpServers": {
"hwpforge": {
"command": "npx",
"args": ["-y", "@hwpforge/mcp"]
}
}
}
๋ฑ๋กํ๋ฉด 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๊ฐ ํ๊ธ ๋ฌธ์ ์ฝ๊ธฐ)
| ๐ ํ๊ธ ์๋ณธ (.hwpx) | ๐ Markdown ๋ณํ ๊ฒฐ๊ณผ |
![]() |
![]() |
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 = MdEncoder::encode_lossy(&validated).unwrap();
println!("{}", markdown); // LLM์ด ๋ฐ๋ก ์ดํดํ ์ ์๋ Markdown
๊ธฐ์กด .hwpx ํ์ผ์ Markdown์ผ๋ก ๋ณํํ๋ฉด Claude, GPT ๋ฑ ์ด๋ค LLM์ด๋ ํ๊ธ ๊ณต๋ฌธ์๋ฅผ ์ฆ์ ์ฝ๊ณ ๋ถ์ํ ์ ์์ต๋๋ค.
โ๏ธ Markdown โ HWPX ๋ณํ
use hwpforge::md::MdDecoder;
use hwpforge::hwpx::{HwpxEncoder, HwpxRegistryBridge};
let md_doc = MdDecoder::decode_with_default("# ์ ๋ชฉ\n\nMarkdown์์ ๋ณํ!").unwrap();
let bridge = HwpxRegistryBridge::from_registry(&md_doc.style_registry).unwrap();
let rebound = bridge.rebind_draft_document(md_doc.document).unwrap();
let validated = rebound.validate().unwrap();
let image_store = hwpforge::core::ImageStore::new();
let bytes = HwpxEncoder::encode(&validated, bridge.style_store(), &image_store).unwrap();
Feature Flags
| Feature | ๊ธฐ๋ณธ๊ฐ | ์ค๋ช |
|---|---|---|
hwpx |
Yes | HWPX encoder/decoder |
md |
โ | Markdown โ Core ๋ณํ |
full |
โ | ๋ชจ๋ ๊ธฐ๋ฅ ํฌํจ |
# Markdown ์ง์ ํฌํจ
hwpforge = { version = "0.5", features = ["full"] }
๐ ์ง์ ์ฝํ ์ธ
| ์นดํ ๊ณ ๋ฆฌ | ์์ |
|---|---|
| ํ ์คํธ | Run, character shape, paragraph shape, style (22๊ฐ ํ์ปด ๊ธฐ๋ณธ ์คํ์ผ) |
| ๊ตฌ์กฐ | Table (์ค์ฒฉ), Image (๋ฐ์ด๋๋ฆฌ + ๊ฒฝ๋ก), TextBox, Caption |
| ๋ ์ด์์ | ๋ค๋จ, ํ์ด์ง ์ค์ , ๊ฐ๋ก/์ธ๋ก ๋ฐฉํฅ, ์ ๋ณธ ์ฌ๋ฐฑ, master page |
| ๋จธ๋ฆฌ๊ธ/๋ฐ๋ฅ๊ธ | Header, Footer, ์ชฝ๋ฒํธ (autoNum) |
| ๊ฐ์ฃผ/๋ฏธ์ฃผ | ๊ฐ์ฃผ, ๋ฏธ์ฃผ |
| ๋ํ | ์ , ํ์, ๋ค๊ฐํ, ํธ, ๊ณก์ , ์ฐ๊ฒฐ์ (์ฑ์, ํ์ , ํ์ดํ ์ง์) |
| ์์ | HancomEQN script ํ์ |
| ์ฐจํธ | 18์ข chart type (OOXML ํธํ) |
| ์ฐธ์กฐ | ์ฑ ๊ฐํผ, ์ํธ ์ฐธ์กฐ, ํ๋ (๋ ์ง/์๊ฐ/์์ฝ), ๋ฉ๋ชจ, ์์ธ |
| ๋ง๋ง/๊ฒน์นจ | ๋ง๋ง (dutmal), ๊ธ์ ๊ฒน์นจ |
| Markdown | GFM decode, lossy + lossless encode, YAML frontmatter |
์ํคํ ์ฒ
HwpForge๋ ๋ ์ด์ด๋ฅผ ๋๋ ์ ์๊ฐํ๋ ํ๋ก์ ํธ์ ๋๋ค.
foundation: ๊ณตํต primitive, unit, index, errorcore: ํฌ๋งท ๋ ๋ฆฝ ๋ฌธ์ ๋ชจ๋ธ๊ณผ shared semanticsblueprint: ์คํ์ผ ์ ์์ ํ ํ๋ฆฟ ๊ณ์ธตsmithy-*: ํฌ๋งท๋ณ codec๊ณผ bridgebindings-*: CLI / MCP / Python ์ง์ ์
๋ ์ด์ด ๊ตฌ์กฐ
%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '14px', 'lineColor': '#BDBDBD'}}}%%
flowchart TB
F["foundation<br/>primitive types<br/>units / indices / errors"]:::foundation
C["core<br/>shared document model<br/>list / tab / paragraph semantics"]:::core
B["blueprint<br/>style registry<br/>template authoring"]:::blueprint
SHX["smithy-hwpx<br/>HWPX read/write"]:::smithy
SH5["smithy-hwp5<br/>HWP5 read / audit / re-emission path"]:::smithy
SMD["smithy-md<br/>Markdown bridge"]:::smithy
CLI["bindings-cli<br/>Hammer"]:::binding
MCP["bindings-mcp<br/>Anvil MCP Server"]:::binding
PY["bindings-py<br/>stub"]:::binding
F --> C
C --> B
C --> SHX
C --> SH5
C --> SMD
B --> SHX
B --> SMD
SHX --> CLI
SH5 --> CLI
SMD --> CLI
SHX --> MCP
SMD --> MCP
SHX --> PY
classDef file fill:#FFFDE7,stroke:#F9A825,color:#5D4037
classDef smithy fill:#FFF3E0,stroke:#FB8C00,color:#E65100
classDef core fill:#E3F2FD,stroke:#42A5F5,color:#0D47A1
classDef blueprint fill:#F3E5F5,stroke:#AB47BC,color:#4A148C
classDef foundation fill:#FAFAFA,stroke:#BDBDBD,color:#424242
classDef binding fill:#E8F5E9,stroke:#43A047,color:#1B5E20
๋ฐ์ดํฐ ํ๋ฆ
%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '14px', 'lineColor': '#BDBDBD'}}}%%
flowchart LR
HWP5[".hwp"]:::file --> SH5["smithy-hwp5"]:::smithy
MD[".md"]:::file --> SMD["smithy-md"]:::smithy
HWPX[".hwpx"]:::file <--> SHX["smithy-hwpx"]:::smithy
SH5 --> CORE["core document"]:::core
SHX <--> CORE
SMD <--> CORE
CORE --> SHX
CLI["CLI"]:::binding --> SH5
CLI --> SHX
CLI --> SMD
MCP["MCP"]:::binding --> SHX
MCP --> SMD
classDef file fill:#FFFDE7,stroke:#F9A825,color:#5D4037
classDef smithy fill:#FFF3E0,stroke:#FB8C00,color:#E65100
classDef core fill:#E3F2FD,stroke:#42A5F5,color:#0D47A1
classDef binding fill:#E8F5E9,stroke:#43A047,color:#1B5E20
ํต์ฌ ์์น: ๊ตฌ์กฐ(Structure)์ ์คํ์ผ(Style)์ ๋ถ๋ฆฌํฉ๋๋ค. core๋ shared semantics์ ์คํ์ผ ์ฐธ์กฐ๋ฅผ ๋ค๊ณ , blueprint๋ ์คํ์ผ ์ ์๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. smithy-* ๊ณ์ธต์ด ํฌ๋งท surface๋ฅผ ์ฐ๊ฒฐํฉ๋๋ค.
์ค์ ์์ ๊ฐ์ฅ ์์ฃผ ์ฐ๋ ๊ฒฝ๋ก๋ ๋ค์ ์ ์ ๋๋ค.
- Markdown โ HWPX
- HWPX โ Markdown / JSON
- HWP5 โ HWPX โ audit / inspect
ํ๋ก์ ํธ ํํฉ
| ์งํ | ๊ฐ |
|---|---|
Tracked Rust src LOC |
~83,962 |
| ํ ์คํธ | 2,207๊ฐ (cargo-nextest) |
| ์์ค ํ์ผ | 137 .rs |
| Crate ์ | 10๊ฐ |
| ์ปค๋ฒ๋ฆฌ์ง | 92.65% |
| Clippy ๊ฒฝ๊ณ | 0 |
| Unsafe ์ฝ๋ | 0 |
๊ฐ๋ฐ
ํ์ ์๊ตฌ์ฌํญ
- Rust 1.88+ (MSRV)
- (๊ถ์ฅ) cargo-nextest โ ๋ณ๋ ฌ ํ ์คํธ ์คํ
- (์ ํ) pre-commit โ git hook ์๋ํ
MSRV ์ ์ฑ
- ํ์ฌ MSRV๋ Rust 1.88์ ๋๋ค.
- HwpForge๋ stable์์ 4 ๋ฆด๋ฆฌ์ค ๋ค์ฒ์ง ๋ฒ์ ์ ๊ธฐ๋ณธ MSRV ์ ์ฑ ์ผ๋ก ์ ์งํฉ๋๋ค.
Cargo.toml์rust-version์ด ๋จ์ผ ์ง์ค์์ด๋ฉฐ, CI์Verify โบ MSRVjob์ด ์ด ๊ณ์ฝ์ ๊ฒ์ฆํฉ๋๋ค.- MSRV ์ํฅ์ด ํ์ํ๋ฉด PR์์ ์ด์ ๋ฅผ ๋ช
์ํ๊ณ ,
Cargo.toml, CI, CHANGELOG๋ฅผ ํจ๊ป ๊ฐฑ์ ํฉ๋๋ค. - ๊ฐ๋ฐ์ฉ ๊ธฐ๋ณธ ํด์ฒด์ธ์ ๋ ์ต์ ์ผ ์ ์์ต๋๋ค. ํธํ์ฑ ํ๋จ ๊ธฐ์ค์ ์ต์ stable์ด ์๋๋ผ MSRV + CI ํต๊ณผ ์ฌ๋ถ์ ๋๋ค.
โ๏ธ ๋ช ๋ น์ด
make ci # fmt + clippy + test + deny + lint (CI์ ๋์ผ)
make test # cargo nextest run
make clippy # cargo clippy (๋ชจ๋ target, ๋ชจ๋ feature, -D warnings)
make fmt-fix # rustfmt ์๋ ํฌ๋งท
make doc # rustdoc ์์ฑ (๋ธ๋ผ์ฐ์ ์์ ์ด๋ฆผ)
make cov # coverage ๋ฆฌํฌํธ (90% gate)
ํ๋ก์ ํธ ๊ตฌ์กฐ
HwpForge/
โโโ crates/
โ โโโ hwpforge/ # Umbrella crate (re-exports)
โ โโโ hwpforge-foundation/ # ๊ธฐ๋ณธ ํ์
(HwpUnit, Color, Index<T>)
โ โโโ hwpforge-core/ # ๋ฌธ์ ๋ชจ๋ธ (์คํ์ผ ์ฐธ์กฐ๋ง)
โ โโโ hwpforge-blueprint/ # YAML ํ
ํ๋ฆฟ (Figma ํจํด)
โ โโโ hwpforge-smithy-hwpx/ # HWPX codec (ZIP+XML โ Core)
โ โโโ hwpforge-smithy-md/ # Markdown codec (MD โ Core)
โ โโโ hwpforge-smithy-hwp5/ # HWP5 decode/projection + inspect/convert helpers
โ โโโ hwpforge-bindings-py/ # Python bindings (stub)
โ โโโ hwpforge-bindings-cli/ # CLI ๋๊ตฌ (hwpforge, shipped)
โ โโโ hwpforge-bindings-mcp/ # MCP Server (hwpforge-mcp)
โโโ tests/ # ํตํฉ ํ
์คํธ + golden fixture
โโโ examples/ # curated showcase + interop artifacts
โโโ showcase/
โโโ interop/
๊ธฐ์ฌ
๋ฒ๊ทธ ์์ , ํฌ๋งท ๋ฆฌ์์น, ํ ์คํธ ๋ณด๊ฐ, ๋ฌธ์ ๊ฐ์ ๋ชจ๋ ํ์ํฉ๋๋ค.
- ์์ ์ ๊ฐ์ด๋: CONTRIBUTING.md
- ํนํ ํ์ธํ ๊ฒ: release-plz๊ฐ ์ฐ๋ ์ปค๋ฐ prefix (
feat,fix,perf,refactor) - ํนํ ํ์ธํ ๊ฒ: MSRV ์ ์ฑ ๊ณผ dependency/MSRV ์์น ๊ธฐ์ค
- ํนํ ํ์ธํ ๊ฒ: ๋ฌธ์ ๋ณ๊ฒฝ ์
mdbook build์ markdown lint ๊ฒ์ฆ - ํนํ ํ์ธํ ๊ฒ: ๋ก์ปฌ docs toolchain์ CI์ ๊ฐ์ pinned ๋ฒ์ (
mdbook 0.4.52,mdbook-admonish 1.20.0,mdbook-mermaid 0.16.2)์ ์ฐ๋ ํธ์ด ๋ซ์ต๋๋ค. ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์make install-tools - ํนํ ํ์ธํ ๊ฒ: CI required checks๋ฅผ ๊นจ์ง ์๋ ๋ฒ์์์์ ๋ณ๊ฒฝ ๋ถ๋ฆฌ
๋ก๋๋งต
ํ์ฌ ์ํ์ ๋ค์ ๋จ๊ณ
- HWP5 ์ฝ๊ธฐ/์ ๊ฒ/์ฌ์ถ๋ ฅ ๊ฒฝ๋ก โ
convert-hwp5,audit-hwp5,census-hwp5 - HWP5 public API ํ๋ โ umbrella crate surface์ broader parity ์ ๋ฆฌ
- MCP ์๋ฒ โ Claude, Cursor ๋ฑ AI ๋๊ตฌ๊ฐ tool๋ก ์ง์ HWPX ์์ฑยท๊ฒ์ฆยทํธ์ง (8๊ฐ ๋๊ตฌ + 4 ๋ฆฌ์์ค + 3 ํ๋กฌํํธ)
- CLI ๋๊ตฌ โ
hwpforge convert doc.md doc.hwpxํ ์ค ๋ณํ (7๊ฐ ๋ช ๋ น์ด) - HWPX ์์ ์ง์ โ ์์ ์ปจํธ๋กค, ๋ณ๊ฒฝ ์ถ์ , OLE ๊ฐ์ฒด
- Python ๋ฐ์ธ๋ฉ โ
pip install hwpforge๋ก ์ค์น, PyPI ๋ฐฐํฌ
๋ผ์ด์ ์ค
๋ค์ ์ค ํ๋๋ฅผ ์ ํํ ์ ์์ต๋๋ค:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
Acknowledgements
HwpForge๋ ๊ฑฐ์ธ๋ค์ ์ด๊นจ ์์ ์ ์์ต๋๋ค.
- Hancom โ HWPX ํฌ๋งท์ ๊ณต๊ฐ ๋ฌธ์์ KS X 6101 (OWPML) ๊ตญ๊ฐ ํ์ค์ด ์์๋ค๋ฉด ์ด ํ๋ก์ ํธ๋ ์์์กฐ์ฐจ ํ ์ ์์์ต๋๋ค. ํฌ๋งท์ ๊ณต๊ฐํด ์ฃผ์ Hancom์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
- openhwp โ Rust๋ก HWP/HWPX๋ฅผ ๋ค๋ฃจ๋ IR ๊ธฐ๋ฐ ์ํคํ ์ฒ ์ค๊ณ์์ ํฐ ์๊ฐ์ ๋ฐ์์ต๋๋ค. HwpForge์ Core ๋ ์ด์ด๊ฐ ์กด์ฌํ ์ ์์๋ ๊ฒ์ openhwp์ด ๋จผ์ ๊ทธ ๊ธธ์ ๊ฑธ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
- hwpxlib โ Java๋ก ์์ฑ๋ ๊ฐ์ฅ ์ฑ์ํ HWPX ๊ตฌํ์ฒด์ ๋๋ค. ์คํ๊ณผ ์ค์ ๋์์ ์ฐจ์ด๋ฅผ ํ์ ํ๋ ๋ฐ ๊ฒฐ์ ์ ์ธ ์ฐธ๊ณ ๊ฐ ๋์์ต๋๋ค.
- hwp.js โ HWP5 ํฌ๋งท์ quirks์ edge case๋ฅผ ๊ผผ๊ผผํ ๋ฌธ์ํํ ํ๋ก์ ํธ์ ๋๋ค. ๋ฐ์ด๋๋ฆฌ ํฌ๋งท์ ์ด๋์ด ๊ตฌ์์ ๋ฐํ ์ค ๋๋ถ์ ์ํ์ฐฉ์ค๋ฅผ ํฌ๊ฒ ์ค์ผ ์ ์์์ต๋๋ค.
- hwpx-owpml-model โ Hancom์ด ์ง์ ๊ณต๊ฐํ C++ OWPML ๋ชจ๋ธ ๊ตฌํ์ฒด๋ก, ์คํค๋ง ํด์์ ์ต์ข ๊ธฐ์ค์ผ๋ก ์ผ์์ต๋๋ค.
- Rust ์ํ๊ณ โ serde, quick-xml, pulldown-cmark, zip ๋ฑ ๋ฐ์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค ๋๋ถ์ HwpForge ์ ์ฒด๋ฅผ zero unsafe ์์ Rust๋ก ๊ตฌํํ ์ ์์์ต๋๋ค. Rust ์ปค๋ฎค๋ํฐ์ Ferris ๐ฆ์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
- Claude by Anthropic โ HwpForge์ ์ค๊ณ, ๊ตฌํ, ํ ์คํธ, ๋ฌธ์ํ ์ ๊ณผ์ ์์ Claude Code๊ฐ ๊ฐ๋ฐ ํํธ๋๋ก ํจ๊ปํ์ต๋๋ค. LLM-first๋ฅผ ํ๋ฐฉํ๋ ํ๋ก์ ํธ๋ต๊ฒ, AI์ ์ฌ๋์ด ํ์ ํ์ฌ ๋ง๋ค์ด๋ธ ๊ฒฐ๊ณผ๋ฌผ์ ๋๋ค.
- Codex by OpenAI โ HwpForge์ ๊ตฌํ ๊ฒํ , ๋ฆฌํฉํฐ๋ง, ํ๊ท ์ ๊ฒ, ์์ ํ๋ฆ ์ ๋ฆฌ ๊ณผ์ ์์ ์ค์ง์ ์ธ ๊ฐ๋ฐ ํํธ๋๋ก ๊ธฐ์ฌํ์ต๋๋ค.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi

