본문으로 건너뛰기

© 2026 Molayo

HN분석2026. 06. 08. 07:25

Silurus/ooxml: 브라우저에서 렌더링되는 픽셀 단위로 정확한 Office 문서

요약

Claude를 통해 100% 생성된 Rust 및 TypeScript 기반의 Office Open XML 뷰어 라이브러리입니다. 브라우저에서 DOCX, XLSX, PPTX 문서를 픽셀 단위로 정확하게 렌더링하며 WebAssembly를 활용합니다.

핵심 포인트

  • Claude를 활용해 사람이 작성한 코드 없이 구현된 프로젝트
  • Rust 파서와 WebAssembly를 통한 고성능 문서 처리
  • Canvas 2D API 기반의 정밀한 브라우저 렌더링
  • 헤드리스 엔진 지원으로 커스텀 UI 구성 가능

이 코드베이스 전체 — Rust 파서 (parsers), TypeScript 렌더러 (renderers), 테스트, 그리고 툴링 (tooling) — 는 반복적인 프롬프팅 (prompting)을 통해 Claude (Anthropic의 AI 어시스턴트)에 의해 구현되었습니다. 이 저장소에는 사람이 작성한 애플리케이션 코드가 존재하지 않습니다.

<p align="center"> <img src="docs/images/icon.png" alt="office-open-xml-viewer" width="160" height="160"> </p>

office-open-xml-viewer

npm version

npm downloads

VS Code Marketplace

VS Code installs

license

데모 (Storybook)

HTML Canvas 엘리먼트 (element)로 렌더링되는 Office Open XML 문서용 브라우저 기반 뷰어입니다.
파서 (parsers)는 Rust로 작성되어 WebAssembly로 컴파일되며, 렌더러 (renderers)는 Canvas 2D API를 사용합니다.
각 포맷은 또한 호출자가 제공하는 임의의 캔버스 (canvas)에 렌더링되는 헤드리스 엔진 (DocxDocument / XlsxWorkbook / PptxPresentation)을 노출하므로, 내장된 뷰어에 갇히지 않고 스크롤 뷰 (scroll views), 썸네일 그리드 (thumbnail grids), 마스터-디테일 창 (master-detail panes) 등 자신만의 UI를 구성할 수 있습니다. Storybook 데모Examples 섹션을 참조하세요.

DOCXXLSXPPTX
docx
xlsx
pptx
npm install @silurus/ooxml
# 또는
pnpm add @silurus/ooxml

번들러 (Bundler) 참고 사항: 이 패키지는 .wasm 파일을 포함하고 있습니다. Vite를 사용하는 경우 vite-plugin-wasm을 추가하고, webpack을 사용하는 경우 experiments.asyncWebAssembly를 사용하세요.

번들 크기 참고 사항: 이 패키지는 ESM 전용(.mjs)입니다. npm의 Unpacked Size는 **선택 사항(opt-in)**인 수학 엔진(MathJax + STIX Two Math, ~3 MB)을 포함한 4개의 모든 엔트리 번들을 합산한 수치입니다. 실제로 앱에 포함되는 크기는 훨씬 작습니다. 필요한 형식만 임포트하세요 (예: @silurus/ooxml/pptx). 수학 엔진은 별도의 엔트리(@silurus/ooxml/math)입니다. 이 엔진은 사용자가 직접 임포트하여 뷰어(viewer)에 전달할 경우에만 번들에 포함됩니다 (수식 렌더링 참조). math 엔진을 전달하면 수식이 렌더링되며, 전달하지 않으면 엔진이 어디에서도 참조되지 않으므로 번들러가 ~3 MB를 트리 쉐이킹(tree-shake)하여 완전히 제거합니다 (수식은 단순히 건너뛰어집니다). 이 엔진은 완전히 독립적입니다: 네트워크 통신이나 교차 출처(cross-origin) 요청이 필요하지 않습니다.


빠른 시작 (Quick Start)

import { DocxViewer } from '@silurus/ooxml/docx';
import { XlsxViewer } from '@silurus/ooxml/xlsx';
import { PptxViewer } from '@silurus/ooxml/pptx';
...

수식 렌더링 (Rendering equations)

.docx / .pptx 파일의 OMML 수식(m:oMath / m:oMathPara)은 MathJax + STIX Two Math를 사용하여 렌더링됩니다. 해당 엔진은 약 3 MB이므로 **선택 사항(opt-in)**으로 제공됩니다. 별도의 @silurus/ooxml/math 엔트리에서 math 엔진을 임포트하여 뷰어에 전달하십시오. 엔진을 전달하면 수식이 렌더링되지만, 전달하지 않으면 엔진이 어디에서도 참조되지 않으므로 번들러가 ~3 MB를 트리 쉐이킹(tree-shake)하여 완전히 제거합니다 (수식은 단순히 건너뛰어집니다). 이 엔진은 완전히 독립적입니다: 네트워크 통신이나 교차 출처(cross-origin) 요청이 필요하지 않습니다.

import { DocxViewer } from '@silurus/ooxml/docx';
import { math } from '@silurus/ooxml/math';

...

동일한 math 엔진은 PptxViewer 및 헤드리스(headless) DocxDocument / PptxPresentation API(옵션에서 math를 받음)에서도 작동합니다. xlsx는 수식 지원이 없으며 엔진을 참조하지 않습니다.


<details> <summary><strong>아키텍처 다이어그램 (Architecture diagram)</strong></summary>
flowchart TB
    subgraph build["🦀  빌드 타임 (Build-time)  (Rust → WebAssembly)"]
        direction LR
...

세 가지 형식 모두 동일한 구조를 따릅니다: 워커(worker)가 WASM을 통해 .docx / .xlsx / .pptx 아카이브를 파싱(parse)하고, 메인 스레드(main thread)로 JSON 모델을 전달하면 렌더러(renderer)가 캔버스(canvas)에 그립니다. 렌더링은 메인 스레드에서 유지되어 캔버스가 문서의 FontFaceSet을 공유할 수 있습니다. 워커 내의 OffscreenCanvas는 자체적인 폰트 레지스트리(font registry)를 가지며, 설치된 테마 웹폰트(webfonts)와 미세하게 다른 텍스트 측정값(및 줄 바꿈 위치)을 생성하며 조용히 시스템 폰트로 폴백(fallback)하게 됩니다. @silurus/ooxml-core는 세 가지 렌더러가 모두 의존하는 교차 형식 프리미티브(cross-format primitives)를 보유하고 있습니다: 통합 차트 렌더러(막대 / 선 / 영역 / 레이더 / 폭포형), 도형 헬퍼(resolveFill, applyStroke, buildCustomPath, hexToRgba), autoResize 뷰어 유틸리티, 그리고 공유된 타입 정의(type definitions)입니다.

주요 파일

파일역할
packages/docx/parser/src/lib.rsRust WASM 파서 — DOCX ZIP → Document JSON
...
</details>

프레임워크 예시 (Framework Examples)

<details> <summary><strong>React 19</strong></summary>
// React 19.1 — vite.config.ts에 vite-plugin-wasm 필요
import { useEffect, useRef, useState } from 'react';
import { PptxViewer } from '@silurus/ooxml/pptx';
...
</details> <details> <summary><strong>Vue 3.5</strong></summary>
<!-- Vue 3.5 — useTemplateRef는 3.5+ 기능입니다 -->
<script setup lang="ts">
import { useTemplateRef, onMounted, ref } from 'vue';
...
</details> <details> <summary><strong>Angular 19</strong></summary>
// Angular 19 — 시그널(signal) 기반 상태를 사용하는 독립형 컴포넌트(standalone component)
import {
  Component, ElementRef, viewChild,
...

Angular 워크스페이스에서 "allowSyntheticDefaultImports": true를 추가하고, @angular-builders/custom-webpack을 구성하거나(또는 esbuild 빌더를 사용) WASM 지원을 설정하세요.

</details> <details> <summary><strong>Svelte 5</strong></summary>
<!-- Svelte 5 — 룬(runes) 구문 ($props, $state) -->
<script lang="ts">
  import { onMount } from 'svelte';
...
</details> <details> <summary><strong>SolidJS 1.9</strong></summary>
// SolidJS 1.9
import { createSignal, onMount, onCleanup } from 'solid-js';
import { PptxViewer } from '@silurus/ooxml/pptx';
...
</details> <details> <summary><strong>Qwik 2</strong></summary>
// Qwik 2.0 — dynamic import to keep WASM out of SSR bundle
import { component$, useSignal, useVisibleTask$ } from '@builder.io/qwik';
import type { PptxViewer as PptxViewerType } from '@silurus/ooxml/pptx';
...
</details>

기능 지원 (Feature Support)

Word (.docx)

카테고리기능상태
문서페이지 렌더링
...

Excel (.xlsx)

카테고리기능상태
통합 문서여러 시트, 시트 이름
...

PowerPoint (.pptx)

카테고리기능상태
슬라이드슬라이드 렌더링
...

텍스트 선택에 대한 참고 사항. DOCX / PPTX / XLSX 전반에 걸쳐, 텍스트 선택은 현재 글리프(glyph)를 캔버스에 렌더링하고 투명한 DOM 레이어를 오버레이하여 캔버스 텍스트 위치를 미러링함으로써 네이티브 브라우저 선택을 구현합니다. 이 이중 레이어 접근 방식은 의도적인 임시 방편입니다: 캔버스 drawElement API가 (WICG/html-in-canvas에서 제안되었으며, 현재 Chromium Origin Trial에 있음) 브라우저 전반으로 배포되면, 프로젝트는 캔버스가 DOM을 직접 미러링하는 단일 DOM-as-source-of-truth 파이프라인으로 마이그레이션할 계획이며 — z-order 정확도와 네이티브 선택/a11y를 유지하면서 중복을 제거합니다.


동반 패키지 (Companion packages)

동반 패키지 (Companion packages)

  • packages/markdown/@silurus/ooxml-markdownooxml-md CLI는 워크스페이스 WASM 파서(parsers)를 통해 .pptx / .docx / .xlsx 파일을 GitHub 스타일 마크다운(GitHub-flavoured markdown)으로 변환합니다. MCP 서버와 동일한 프로젝션(projection)을 사용합니다 (데모 슬라이드 기준 원본 XML보다 약 21배 작으며, 일반 텍스트 추출기보다는 약 8% 큽니다). 저장소 전체의 대량 변환을 위한 Node20 기반의 GitHub Action을 포함합니다.
  • packages/node/ — DOM이나 Web Worker 의존성 없이 워크스페이스 WASM 아티팩트(artifacts)를 대상으로 parsePptx / parseDocx / parseXlsx / parseXlsxAllSheets를 노출하는 Node 측 파서(@silurus/ooxml-node)입니다. CI 체크, 헤드리스 렌더링 파이프라인(headless rendering pipelines), CLI 도구에 유용합니다. ooxml-thumbnail CLI를 포함합니다 (첫 번째 단계는 pptx 전용이며, skia-canvas가 필요합니다).
  • packages/vscode-extension/.docx, .xlsx, .pptx에 대한 CustomEditorProvider를 등록하는 VS Code 확장 프로그램(ooxml-viewer)입니다. 또한 (선택 사항으로) ooxml-mcp-server를 자동 설치 및 등록하여, 동일한 창 내의 AI 코딩 에이전트(Copilot Agent 모드, Claude 등)가 전용 도구를 통해 해당 파일들을 읽을 수 있도록 합니다.
  • packages/mcp-server/ — AI 에이전트(Claude, Copilot, Codex 등)를 위해 파서를 도구(tools)로 노출하는 Rust 기반 MCP 서버(ooxml-mcp-server)입니다. 에이전트가 unzip 명령어를 실행하지 않고도 OOXML 파일을 검사할 수 있도록 구조화된 쿼리(docx_get_structure, xlsx_get_cell_range, pptx_get_slide_structure 등)를 제공합니다. macOS / Linux / Windows용 사전 빌드된 바이너리가 각 GitHub Release에 첨부되어 있으며, VS Code 확장 프로그램이 필요할 때 이를 다운로드합니다.

개발 (Development)

# 의존성 설치
pnpm install

...

WASM 빌드 (개별 패키지)

cd packages/docx/parser && wasm-pack build --target web && cp pkg/docx_parser_bg.wasm  pkg/docx_parser.js  ../src/wasm/
cd packages/xlsx/parser && wasm-pack build --target web && cp pkg/xlsx_parser_bg.wasm  pkg/xlsx_parser.js  ../src/wasm/
cd packages/pptx/parser && wasm-pack build --target web && cp pkg/pptx_parser_bg.wasm pkg/pptx_parser.js ../src/wasm/

보안 및 개인 정보 보호 (Security & Privacy)

  • Canvas 전용 렌더링. 문서는 디코딩되어 HTMLCanvasElement에 그려집니다. 소스 파일에서 스크립트, 링크, 폼 또는 기타 활성 콘텐츠는 실행되거나 DOM에 주입되지 않습니다.
  • ZIP 압축 해제 용량 제한 (cap). 소스 아카이브의 각 항목은 기본적으로 512 MiB의 압축 해제된 출력이 제한되어 zip-bomb DoS를 방지합니다. maxZipEntryBytes (바이트)로 개별 뷰어에서 재정의할 수 있습니다. 이는 대용량 임베디드 미디어가 포함된 합법적인 프레젠테이션을 위해 값을 높이거나, 신뢰할 수 없는 입력에 대한 예산을 강화하기 위해 낮출 수 있습니다:
    new PptxViewer(canvas, { maxZipEntryBytes: 64 * 1024 * 1024 }); // 64 MiB
    
    DocxViewer, PptxViewer, 및 XlsxViewer에서 통일적으로 지원됩니다. 0 또는 음수 값은 기본값으로 폴백(fallback)합니다.
  • 기본적으로 네트워크 사용 안 함. 이 라이브러리는 원격 측정(telemetry)이나 분석을 전송하지 않으며, 요청하지 않는 한 타사 서비스와 통신하지 않습니다. 특히, 테마 웹폰트(XLSX의 Office 폰트 메트릭 대체용)는 관련 Viewer / load(...) 옵션에 useGoogleFonts: true를 전달하지 않는 한 Google Fonts에서 로드되지 않습니다 — 이는 DocxViewer, PptxViewer, 및 XlsxViewer에서 통일적으로 지원됩니다. 이 옵션을 활성화하면 최종 사용자 브라우저가 fonts.googleapis.com으로 HTTP 요청(IP 및 User-Agent)을 보내게 되며, 이는 귀하의 애플리케이션에 GDPR 영향을 미칠 수 있으므로 대신 @font-face를 통해 필요한 폰트를 자체 호스팅하는 것을 고려하십시오.
  • XML 파싱. 외부 엔티티를 해결하지 않는 roxmltree를 사용합니다 (기본적으로 XXE-안전).

라이선스 (License)

MIT

AI 자동 생성 콘텐츠

본 콘텐츠는 HN AI Posts의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0