Hwp2md
HWP(한글 워드프로세서) 문서를 Markdown으로 변환하는 도구
Install / Use
/learn @roboco-io/Hwp2mdREADME
hwp2md
HWP(한글 워드프로세서) 문서를 Markdown으로 변환하는 CLI 도구
개요
이 프로젝트는 HWP/HWPX 문서를 Markdown으로 변환합니다. HWP는 복잡한 테이블 레이아웃, 중첩 표, 다단 구성 등 Markdown에서 직접 표현하기 어려운 구조를 포함할 수 있습니다. 이러한 구조적 차이를 극복하기 위해 2단계 파이프라인 아키텍처를 사용하며, 필요시 LLM을 활용하여 더 읽기 쉬운 Markdown을 생성합니다.
아키텍처
flowchart LR
subgraph Input
HWP[HWP/HWPX 문서]
end
subgraph Stage1[Stage 1: Parser]
direction TB
Parser{Parser}
Parser --> |HWPX| HWPX[HWPX Parser]
Parser --> |HWP| HWP5[HWP5 Parser]
Parser -.-> |선택적| Upstage[Upstage Document Parse]
HWPX --> IR[IR - 중간 표현]
HWP5 --> IR
end
subgraph Stage2[Stage 2: LLM - 선택적]
LLM{LLM Provider}
LLM --> |Anthropic| Claude
LLM --> |OpenAI| GPT
LLM --> |Google| Gemini
LLM --> |Upstage| Solar
LLM --> |Local| Ollama
end
subgraph Output
MD1[기본 Markdown]
MD2[향상된 Markdown]
end
HWP --> Parser
IR --> MD1
Upstage -.-> MD1
IR -.-> LLM
MD1 -.-> LLM
LLM -.-> MD2
| Stage | 설명 | 출력 | |-------|------|------| | Stage 1 (Parser) | 문서를 파싱하여 중간 표현(IR)으로 변환 | 구조화된 기본 Markdown | | Stage 2 (LLM) | LLM을 사용하여 IR을 깔끔한 Markdown으로 포맷팅 | 가독성이 향상된 Markdown |
Stage 1만으로도 기본적인 변환이 가능하지만, 복잡한 레이아웃의 문서는 Stage 2(LLM)를 통해 가독성을 크게 향상시킬 수 있습니다.
설치
Go 설치 (권장)
go install github.com/roboco-io/hwp2md/cmd/hwp2md@latest
바이너리 다운로드
GitHub Releases에서 플랫폼별 바이너리를 다운로드할 수 있습니다.
| 플랫폼 | 아키텍처 | 파일 |
|--------|----------|------|
| Windows | x64 | hwp2md_*_windows_amd64.zip |
| macOS | Intel | hwp2md_*_darwin_amd64.tar.gz |
| macOS | Apple Silicon | hwp2md_*_darwin_arm64.tar.gz |
| Linux | x64 | hwp2md_*_linux_amd64.tar.gz |
사용법
기본 변환 (Stage 1만)
# HWPX 파일을 Markdown으로 변환
hwp2md document.hwpx -o output.md
# HWP 5.x 파일을 Markdown으로 변환
hwp2md document.hwp -o output.md
# 표준 출력으로 변환
hwp2md document.hwpx
Note:
convert명령어는 기본 명령이므로 생략할 수 있습니다.hwp2md document.hwpx와hwp2md convert document.hwpx는 동일합니다.
Upstage Document Parse 사용 (Stage 1 - 선택적)
기본 내장 파서로 충분하지 않은 경우, Upstage Document Parse API를 선택적으로 사용할 수 있습니다. OCR 기반으로 복잡한 레이아웃이나 스캔된 문서를 더 정확하게 인식합니다.
# Upstage Document Parse 사용
export UPSTAGE_API_KEY="your-api-key"
hwp2md document.hwpx --parser upstage
# 환경변수로 설정
export HWP2MD_PARSER="upstage"
hwp2md document.hwpx
Note: Upstage Document Parse는 API 키가 필요하며 사용량에 따라 비용이 발생합니다. 대부분의 HWPX 문서는 내장 파서로 충분히 변환됩니다.
LLM 포맷팅 (Stage 2)
LLM을 사용하면 더 자연스럽고 읽기 쉬운 Markdown을 생성할 수 있습니다.
# Anthropic Claude 사용 (기본)
export ANTHROPIC_API_KEY="your-api-key"
hwp2md convert document.hwpx --llm
# OpenAI GPT 사용
export OPENAI_API_KEY="your-api-key"
hwp2md convert document.hwpx --llm --provider openai
# Google Gemini 사용
export GOOGLE_API_KEY="your-api-key"
hwp2md convert document.hwpx --llm --provider gemini
# Upstage Solar 사용
export UPSTAGE_API_KEY="your-api-key"
hwp2md convert document.hwpx --llm --provider upstage
# Ollama 사용 (로컬)
hwp2md convert document.hwpx --llm --provider ollama --model llama3.2
IR 추출
# JSON 형식으로 IR 추출
hwp2md extract document.hwpx -o output.json
# 텍스트 형식으로 추출
hwp2md extract document.hwpx --format text
환경 변수
| 변수 | 설명 |
|------|------|
| HWP2MD_PARSER | 파서 선택 (native, upstage) - 기본: native (upstage는 선택적) |
| HWP2MD_LLM | true로 설정하면 LLM 포맷팅 활성화 |
| HWP2MD_MODEL | 사용할 모델 이름 (프로바이더 자동 감지) |
| HWP2MD_BASE_URL | 프라이빗 API 엔드포인트 (Bedrock, Azure, 로컬 서버) |
| ANTHROPIC_API_KEY | Anthropic API 키 |
| OPENAI_API_KEY | OpenAI API 키 |
| GOOGLE_API_KEY | Google Gemini API 키 |
| UPSTAGE_API_KEY | Upstage API 키 (LLM 및 Document Parse) |
| OLLAMA_HOST | Ollama 서버 주소 (기본: http://localhost:11434) |
모델 이름으로 프로바이더가 자동 감지됩니다:
claude-*→ Anthropicgpt-*,o1-*,o3-*→ OpenAIgemini-*→ Google Geminisolar-*→ Upstage- 그 외 → Ollama (로컬)
프라이빗 테넌시
AWS Bedrock, Azure OpenAI, 로컬 서버 등 프라이빗 엔드포인트를 사용할 수 있습니다:
# AWS Bedrock
hwp2md convert document.hwpx --llm --model claude-3-sonnet --base-url https://bedrock-runtime.us-east-1.amazonaws.com
# Azure OpenAI
hwp2md convert document.hwpx --llm --model gpt-4 --base-url https://your-resource.openai.azure.com
# 로컬 서버
hwp2md convert document.hwpx --llm --model llama3.2 --base-url http://localhost:8080
지원 포맷
| 포맷 | 상태 | 설명 | |------|------|------| | HWPX | ✅ 지원 | XML 기반 개방형 포맷 (한컴오피스 2014+) | | HWP 5.x | ✅ 지원 | OLE2/CFB 바이너리 포맷 (한글 2002~2022) | | HWP 3.x | 미정 | 레거시 바이너리 포맷 |
HWP 5.x 지원 기능
| 기능 | 상태 | |------|------| | 문단/텍스트 | ✅ 지원 | | 테이블 (셀 병합 포함) | ✅ 지원 | | 이미지 참조 | ⚠️ 부분 지원 | | 압축 문서 | ✅ 지원 | | 암호화/DRM 문서 | ❌ 미지원 |
LLM 프로바이더
| 프로바이더 | 기본 모델 | 설명 |
|------------|-----------|------|
| anthropic | claude-sonnet-4-20250514 | Anthropic Claude |
| openai | gpt-4o-mini | OpenAI GPT (Azure, Bedrock 호환) |
| gemini | gemini-1.5-flash | Google Gemini |
| upstage | solar-pro | Upstage Solar |
| ollama | llama3.2 | 로컬 Ollama 서버 |
컨트리뷰션
개발 환경 설정
# 저장소 클론
git clone https://github.com/roboco-io/hwp2md.git
cd hwp2md
# 의존성 다운로드
go mod download
# Git hooks 설치 (필수)
make hooks
# 빌드
make build
요구사항
- Go 1.24 이상
- golangci-lint (lint 검사)
- Claude Code (권장) - AI 페어 프로그래밍 도구
권장: 이 프로젝트는 Claude Code를 활용한 AI 협업 개발로 진행되었습니다. 복잡한 파서 로직이나 새로운 기능 구현 시 Claude Code 사용을 권장합니다. 자세한 내용은 바이브 코딩 튜토리얼을 참조하세요.
개발 워크플로우
flowchart TB
subgraph Local[로컬 개발]
Code[코드 작성]
end
subgraph PreCommit[pre-commit hook]
direction TB
Gofmt[gofmt 포맷 검사]
Lint[golangci-lint]
UT[Unit Tests]
end
subgraph PrePush[pre-push hook]
E2E[E2E Tests]
end
subgraph CI[GitHub Actions]
Test[Test Workflow]
Release[Release Workflow]
end
Code --> |git commit| PreCommit
Gofmt --> |통과| Lint
Lint --> |통과| UT
UT --> |통과| Commit[커밋 완료]
Commit --> |git push| PrePush
E2E --> |통과| Push[푸시 완료]
Push --> CI
Test --> |v* 태그| Release
Release --> Binary[바이너리 배포]
Git Hooks
make hooks로 설치되는 Git hooks가 코드 품질을 자동으로 검증합니다:
| Hook | 실행 시점 | 검증 항목 | 실패 시 | |------|----------|----------|--------| | pre-commit | 커밋 전 | gofmt + golangci-lint + Unit Tests | 커밋 차단 | | pre-push | 푸시 전 | E2E Tests | 푸시 차단 |
pre-commit 검증 순서
- gofmt - Go 코드 포맷팅 검사 (Go만 있으면 항상 실행)
- golangci-lint - 정적 분석 (설치된 경우에만 실행)
errcheck: 에러 반환값 무시 검출ineffassign: 사용되지 않는 할당 검출unused: 사용되지 않는 코드 검출staticcheck: 정적 분석- 기타 linter들 (
.golangci.yml참조)
- Unit Tests -
./internal/...패키지 테스트
참고: gofmt는 golangci-lint에 포함되어 있지만, golangci-lint가 Go 버전 불일치 등으로 실행되지 않는 환경에서도 기본 포맷팅 검사를 보장하기 위해 별도로 먼저 실행합니다.
# hooks 설치
make hooks
# 수동 실행
make test # unit tests + e2e tests
make lint # golangci-lint
make fmt # gofmt 자동 수정
make test-e2e # e2e tests만
테스트 구조
| 종류 | 경로 | 설명 |
|------|------|------|
| Unit Tests | internal/*/ | 패키지별 단위 테스트 |
| E2E Tests | tests/ | CLI 통합 테스트, LLM 연동 테스트 |
# 전체 테스트
make test
# unit tests만
go test -race ./internal/...
# e2e tests만
go test -race ./tests/...
# 특정 테스트
go test -v -run TestName ./internal/parser/hwpx/
GitHub Actions
| Workflow | 트리거 | 동작 |
|----------|--------|------|
| Test | push, PR | lint + unit tests + e2e tests |
| Release | v* 태그 | goreleaser로 크로스 플랫폼 바이너리 빌드 및 배포 |
프로젝트 구조
hwp2md/
├── cmd/hwp2md/ # CLI 엔트리포인트
├── internal/
│ ├── cli/ # CLI 명령 구현
│ ├── config/ # 설정 관리
│ ├── formatter/ # 출력 서식 처리 (공문서 항목 기호 변환 등)
│ ├── ir/ # 중간 표현 (Intermediate Representation)
│ ├── llm/ # LLM 프로바이더
│ │ ├── anthropic/ # Anthropic Claude
│ │ ├── openai/ # OpenAI GPT
│ │ ├── gemini/ # Google Gemini
│ │ ├── upstage/ # Upstage Solar
│ │ └── ollama/ # Local Ollama
│ └── parser/ # 문서 파서
│ ├── hwpx/ # HWPX 파서 (XML 기반)
│ ├── hwp5/ # HWP 5.x 파서 (바이너리)
│ └── upstage/ # Upstage Document Parse (선택적)
├── docs/ # 문서
└── tests/ # 테스트 데이터
변환 품질 예시
실제 변환 결과를 확인하여 품질을 평가할 수 있습니다.
Stage 1 (Parser 비교)
동일한 문서를 내장 파서와 Upstage Document Parse로 변환한 결과를 비교할 수 있습니다.
| 파서 | 결과 | 설명 | |------|------|------| | 원본 | 한글 테스트.hwpx, PDF | 테스트용 한글 문서 (공무원 채용 공고) | | Native | 결과 보기 | 내장 HWPX 파서 (기본) | | Upstage | 결과 보기 | Upstage Document Parse API (선택적) |
Stage 2 (LLM 비교)
동일한 문서를 여러 LLM으로 변환한 결과를 비교할 수 있습니다.
| LLM | 결과 | 모델 | |-----|------|------| | Claude | 결과 보기 | claude-sonnet-4-20250514 | | GPT | 결과 보기 | gpt-4o-mini | | Gemini | 결과 보기 | gemini-2.0-flash | | Solar | 결과 보기 | solar-pro |
Stage 1은 문서 구조를 그대로 추출하며, Stage 2는 LLM을 통해 더 읽기 쉬운 형태로 정리합니다.
테스트 파일 출처: 한국문화원 문서 뷰어 테스트 예시
문서
기술 문서
Related Skills
node-connect
343.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
92.1kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
343.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
343.3kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
