브라우저 기반 Word 문서 미리보기 핵심 라이브러리
프론트엔드 환경에서 Word 문서(.docx)를 미리보기 형태로 표시해야 할 때, 서버 변환 없이 클라이언트 단독으로 해결할 수 있는 두 가지 대표 라이브러리를 살펴봅니다.
docx-preview: 원본 그대로의 렌더링
Office 화면과 거의 동일한 시각적 결과를 추구할 때 선택합니다. 페이지 나누기, 머리글/바닥글, 표 서식 등 문서의 레이아웃을 정밀하게 재현합니다.
npm install docx-preview
import { renderAsync } from 'docx-preview';
const previewDocument = async (fileStream, targetElement) => {
try {
await renderAsync(fileStream, targetElement);
} catch (err) {
console.error('문서 렌더링 실패:', err);
}
};
// 사용 예시
const fileData = await fetch('/sample.docx').then(r => r.blob());
previewDocument(fileData, document.querySelector('#viewer'));
mammoth: 구조 중심의 변환
Word 문서를 의미론적인 HTML로 변환하는 방식입니다. 시각적 정확도보다 콘텐츠 구조와 접근성을 우선시합니다.
npm install mammoth
import mammoth from 'mammoth';
const extractDocument = async (buffer) => {
const { value: htmlContent, messages: logs } = await mammoth.convertToHtml({
arrayBuffer: buffer
});
if (logs.length) {
console.log('변환 알림:', logs);
}
return htmlContent;
};
실전 적용 시나리오
시나리오 A: 문서 뷰어 구축
사용자가 업로드한 Word 파일을 "Office에서 보는 것처럼" 확인해야 하는 경우, docx-preview를 구성합니다.
const initializeViewer = async (documentUrl) => {
const response = await fetch(documentUrl);
const blobData = await response.blob();
const viewerConfig = {
className: 'word-viewer',
inWrapper: true,
breakPages: true,
renderHeaders: true,
renderFooters: true,
renderFootnotes: true,
ignoreWidth: false
};
await renderAsync(
blobData,
document.getElementById('preview-zone'),
document.getElementById('style-injection'),
viewerConfig
);
};
성능 고려사항: 100페이지 이상의 대용량 문서는 렌더링 지연 발생 가능. 필요 시 페이지 단위 지연 로딩 또는 가상 스크롤 적용 권장.
시나리오 B: 콘텐츠 편집 시스템
업로드된 Word 파일에서 텍스트를 추출하여 리치 텍스트 편집기에 주입하는 경우, mammoth가 적합합니다.
const transformForEditing = async (uploadedFile) => {
const buffer = await uploadedFile.arrayBuffer();
const styleRules = [
"p[style-name='Heading 1'] => h1",
"p[style-name='Heading 2'] => h2",
"p[style-name='Quote'] => blockquote",
"p[style-name='Code'] => pre"
];
const result = await mammoth.convertToHtml(
{ arrayBuffer: buffer },
{ styleMap: styleRules }
);
return {
html: result.value,
warnings: result.messages
};
};
고급 설정 및 최적화
docx-preview 세부 제어
| 옵션 | 기능 | 기본값 |
|---|---|---|
breakPages | 페이지 분리 표시 | true |
renderComments | 주석 렌더링 | false |
useBase64URL | 이미지 인코딩 방식 | false |
ignoreHeight | 페이지 높이 무시 | false |
// 단일 연속 문서로 표시 (페이지 나누기 제거)
renderAsync(blob, container, null, {
breakPages: false,
ignoreHeight: true,
className: 'seamless-document'
});
mammoth 이미지 처리 개선
기본 base64 인코딩은 문서 크기를 급격히 증가시킵니다. Blob URL 전환으로 메모리 사용량을 절감합니다.
const optimizedOptions = {
convertImage: mammoth.images.imgElement((imgData) =>
imgData.readAsArrayBuffer().then((rawBuffer) => {
const imageBlob = new Blob([rawBuffer], {
type: imgData.contentType
});
return {
src: URL.createObjectURL(imageBlob),
alt: imgData.altText || '문서 이미지'
};
})
)
};
mammoth.convertToHtml({ arrayBuffer: docBuffer }, optimizedOptions);
대안 방식: Microsoft Office Online 임베드
공개 문서의 경우 Microsoft 제공 뷰어를 활용할 수 있습니다.
<iframe
src="https://view.officeapps.live.com/op/embed.aspx?src=공개문서URL"
width="100%"
height="600"
frameborder="0">
</iframe>
제약조건: 문서가 인터넷에 공개되어 있어야 하며, 내부망 문서에는 적용 불가.
선택 가이드
| 기준 | docx-preview | mammoth |
|---|---|---|
| 시각적 정확도 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| HTML 깔끔함 | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| 번들 크기 | 중간 (~500KB) | 소형 (~100KB) |
| 스타일 커스터마이징 | 제한적 | 자유로운 |
| 복잡한 표/차트 | 완벽 지원 | 단순화 |
요약: 원본 레이아웃 보존이 중요하면 docx-preview, 텐츠 재가공 및 웹 최적화가 목표면 mammoth를 채택하세요.