12 KiB
12 KiB
한글 파일(HWP) 미리보기 렌더링 고도화 작업 내역서
본 문서는 웹 브라우저(클라이언트) 환경에서 한글 문서(.hwp) 파일을 직접 파싱하고 렌더링하는 클라이언트 사이드 미리보기 엔진의 고도화 작업 및 디버깅 수행 내역을 상세히 기록한 문서입니다.
1. 주요 작업
클라이언트 뷰어 라이브러리(libs/hwp.js) 및 스타일시트, HTML 로드 방식을 개선하여 원본 문서와의 레이아웃 일치율을 비약적으로 끌어올리고 깨진 리소스(이미지/도형)를 복구하는 것을 목표로 하였습니다.
- 바이너리 압축 해제 및 이미지 MIME 안정화: 무압축 Raw 이미지 파싱 우회 및 다단계 압축해제 예외처리 폴백 구축, 오타로 인한 이미지 로딩 에러(images/png) 수정.
- 텍스트 영역 겹침 및 간격 보정: 글로벌 CSS 충돌로 인한 텍스트 줄 겹침 결함을 단락 및 스팬 인라인 스타일 강제 부여를 통해 보정.
- HWP 문서 내 자체 생성 도형(벡터) 복원 및 위치 정밀도 교정:
- 파싱 대상에서 유실되었던 직사각형, 타원, 선 등의 형상을 SVG 배경 레이어 렌더러로 복구.
- 도형의 기준 위치(
vertRelTo세로 기준: 문단/쪽/종이)에 따라 절대 배치(position: absolute) 및 좌표 배치를 분기하여, 도형이 정상 범위를 벗어나 페이지 바깥(회색 배경 부분)으로 밀려 나가는 겹침 오류를 완벽히 수정.
- 표(Table) 스타일 및 정렬 정밀 매핑: 셀 여백(Padding) 스타일 강제 적용 및 HWP 바이너리에 포함된 세로 정렬(Vertical Alignment) 속성을 CSS 속성에 1대1 일치화.
- 한글 기본 폰트 대체 매핑: 클라이언트 기기에 한양굴림, 한컴바탕 등 오피스 전용 폰트가 설치되어 있지 않을 경우를 대비하여 웹 폰트(Noto Serif/Sans KR)를 연동.
- WMF 벡터 파일 캔버스 디코딩 연동: 브라우저 표준 디코더가 읽지 못하는
.wmf벡터 그래픽 파일을 클라이언트 단에서 파싱하여 PNG 이미지로 변환 및 렌더링. - 뷰어 레이아웃 너비 확장 (가로 스크롤 제거):
- 기본 가로 너비가 좁아 A4 문서 미리보기 시 발생하던 불필요한 가로(횡) 스크롤바를 원천 제거하기 위해 우측 미리보기 영역 너비를 확장.
- 팝업 미리보기 창 라이브러리/스타일셋 동기화:
- 별도 팝업 창(
views/main/popup.html)에서 한글 미리보기를 열 때wmf.js와font.css로드 누락으로 인해 도형이 깨지거나 횡스크롤바가 발생하던 문제를 리소스 태그 삽입 및 인라인/클래스 스타일링 규격화로 정정.
- 별도 팝업 창(
2. 수행 내용
수행된 작업의 구체적인 파일별 수정 상세 명세입니다.
2.1 폰트 정의 추가 및 웹 폰트 매핑
- 대상 파일: font.css
- 내용:
- 구글 Noto Sans KR 및 Noto Serif KR 웹 폰트를 CSS 임포트하고 폰트 매핑을 정의했습니다.
2.2 WMF 디코더 스크립트 로드 추가
- 대상 파일: main.html
- 내용:
libs/hwp.js가 로딩되기 전wmf.js라이브러리를 로드하는 태그를 추가했습니다.
2.3 뷰어 레이아웃 너비 확장 및 정렬 보정
- 대상 파일: style_archive.css
- 내용:
- 우측 미리보기 컨테이너(
.archive-main-right)의 너비를 기존41rem에서 A4 가로폭(약 794px + 여백)이 충분히 수용되는 **55rem(880px)**으로 확장하여 가로 스크롤바가 생기지 않도록 수정했습니다. - 너비 변경에 따라 우측 영역에 맞물려 있던 팝업 메뉴 및 토글 단추 위치(
right: 41.5rem->right: 55.5rem)를 함께 조정했습니다.
- 우측 미리보기 컨테이너(
2.4 HWP 파서 및 렌더러 로직 전면 개선
- 대상 파일: hwp.js
- 내용:
① OLE 바이너리 이미지 압축 우회 및 안정화
- 이미지 데이터 파싱 시, 첫 4바이트 Magic Number(PNG, JPEG, GIF, WMF)를 검사하여 압축이 필요 없는 데이터는 드플레트(Decompress) 과정을 생략하고 직접 읽게 하였습니다.
- 압축 해제 실패 시 다단계 폴백 구조(
windowBits: -15->기본 inflate->inflateRaw->원본 raw 복사)를 구축하여 뷰어 크래시를 차단했습니다. - MIME 명칭 오타(
"images/"->"image/") 및 JPG 규격 명칭(image/jpeg)을 보정했습니다.
② 단락 및 텍스트 줄 겹침 결함 수정
drawText및drawParagraph메서드 내에서 텍스트가 삽입되는 각div스팬과 컨테이너에line-height: 1.65인라인 스타일을 적용해 부모 스타일시트에 의해 줄 영역이 위아래로 포개어지는 문제를 예방했습니다.
③ 도형(Rectangle/Ellipse/Line)의 SVG 배경 레이어 렌더링 고도화 및 좌표 보정
- HWP 파서의
visit메서드 내에 직사각형, 타원, 선, 호, 다각형, 자유곡선 레코드 ID들을 식별하도록 등록하고 도형 타입을 구분 지었습니다. drawParagraph렌더링 시 문단div요소를 쪽(Page)에 즉시 추가하여 자식 도형들의 절대 배치 위치 기준(parentNode)이 정상적으로 작동하도록 수정했습니다.drawShape메서드에서 도형의 세로 기준 설정(vertRelTo)을 분석합니다.vertRelTo === 2(문단 기준): 문단 컨테이너div에position: relative스타일을 적용하고, 도형을position: absolute; top: [verticalOffset]; left: [horizontalOffset];로 배치하여 본문 내에 정확히 안착시켰습니다.vertRelTo === 0 또는 1(종이/쪽 기준): 도형을position: absolute로 지정하고 부모 쪽 컨테이너(container.parentNode)의 절대 레이어에 직접 덧그려 올바른 위치를 맞췄습니다.- 이를 통해 기존에 상대 배치 마진(
marginTop) 누적으로 인해 본문 뒤로 엉뚱하게 밀려 나거나 페이지 바깥 회색 프레임으로 가라앉던 결함을 완벽히 해소했습니다.
④ 표 셀 세로 정렬(vertical-align) 파싱 및 여백(padding) 스타일링
visitCellListHeader파서 메서드가 셀 레코드 버퍼를 해독할 때, 세로 정렬 바이트(verticalAlign: 0-상단, 1-중앙, 2-하단) 데이터를 추가로 추출하여 전달하도록 개선했습니다.drawColumn렌더러가 td 엘리먼트를 조립할 때, 파싱된 셀 padding 값을 CSS 속성으로 가공하고 데이터가 0이거나 유실된 경우에는 가독성을 확보하도록 디폴트 규격 패딩(padding: 2px 5px;)을 바인딩했습니다.- 해독된 세로 정렬 상태 값을 CSS
vertical-align속성(top,middle,bottom)과 정확히 일치화시켜 테이블 안의 정렬을 완벽하게 재현했습니다.
⑤ WMF 이미지의 Canvas 드로잉 및 PNG 변환 연동
- 그림 객체(
isPicture) 렌더링 시 이미지 확장자가wmf인 경우wmf.jsAPI를 연동했습니다. - WMF 이미지 원본 크기를 측정하여 브라우저 메모리에 가상
<canvas>엘리먼트를 생성해 캔버스에 이미지를 렌더링한 후,canvas.toDataURL('image/png')를 추출해 div의backgroundImage에 바인딩했습니다.
2.5 팝업 미리보기 리소스 추가 로드 및 스타일셋 개선
- 대상 파일:
- 내용:
popup.html에font.css링크 및wmf.js스크립트를 추가하여 팝업 뷰어에서도 한글 기본 폰트 대체 및 WMF 벡터 도형이 실시간으로 변환되도록 연동했습니다.popup.js,pageRenderer.js,docPageRenderer.js파일 내의 HWP 렌더링 영역 스타일 인젝션 코드에서 컨테이너의 최대 너비를 **950px**로 확장 적용했습니다..hwpjs-viewer > div클래스에overflow-x: hidden !important스타일을 동적으로 입혀 불필요한 횡스크롤바 생성을 원천 차단하고,div[data-page-number]페이지 요소의 가로폭 축소 유실을 유발하던max-width: 100%설정을 완전히 제거하여 표와 도형이 찌그러지고 정렬이 어긋나는 레이아웃 파괴 버그를 예방하였습니다.
3. 검증 결과
수정 파일의 문법적 무결성 및 실제 동작 상태에 대한 검증 내용입니다.
3.1 JavaScript 구문 분석 검증 (Syntax Check)
- Node.js 구문 체크 명령어를 통과하여 수정된
libs/hwp.js파일에 어떠한 문법적 에러도 없음을 증명했습니다.
node -c "libs/hwp.js" => (오류 없이 성공적으로 컴파일 완료)
3.2 기능적 검증 요약
- 도형 좌표 보정: 본래 문단 뒤에 겹쳐 있어야 할 동그라미(Ellipse)와 연결선(Line) 등의 구조물들이 페이지 밖으로 탈탈 밀려나던 문제가 완전히 해결되어 본문 표 바로 밑에 원본과 동일하게 정밀 안착하는 것을 확인했습니다.
- 가로 스크롤 소거: 미리보기 화면을 띄웠을 때 횡스크롤바가 더 이상 나타나지 않으며, A4 규격의 본문과 여백이 전체적으로 여유롭게 한 화면에 들어오는 것을 확인했습니다.
- 이미지 및 테이블: WMF 이미지 디코딩 및 표의 세로 정렬/여백 등이 모두 원본 문서의 비주얼과 정합성이 유지됩니다.
4. 조치사항 (운영 및 유지보수 가이드)
프로젝트 운영 단계에서 발생 가능한 상황에 대한 대처 방안입니다.
- 클라이언트 캐시 갱신 (가장 중요)
- 백엔드 코드와 달리 프론트엔드 자바스크립트(
hwp.js,font.css) 및 스타일시트(style_archive.css) 파일은 클라이언트 브라우저가 강력하게 캐싱합니다. - 렌더링 개선 내역이 정상적으로 적용되지 않을 경우, 브라우저에서
Ctrl + F5(강제 새로고침)를 수행하거나 개발자 도구(F12)의 네트워크 탭에서 **'캐시 사용 안 함(Disable Cache)'**을 활성화한 후 재시도하십시오.
- 백엔드 코드와 달리 프론트엔드 자바스크립트(
- 폐쇄망(오프라인) 배포 시 폰트 로드 조치
- 현재 등록된 폰트는 구글 웹 폰트 CDN 주소를 사용합니다. 만약 외부 인터넷 접근이 불가능한 망분리/오폐쇄망 환경에 프로젝트가 배포될 경우,
@import주소의 구글 폰트를 가져오지 못해 폰트가 기본형으로 깨질 수 있습니다. - 조치 방안:
views/main/css/하위에fonts/디렉토리를 생성하고,NotoSansKR.woff2,NotoSerifKR.woff2파일을 서버에 저장한 후font.css에서 상대 경로(url('./fonts/...'))로 서빙하도록 경로를 전환해야 합니다.
- 현재 등록된 폰트는 구글 웹 폰트 CDN 주소를 사용합니다. 만약 외부 인터넷 접근이 불가능한 망분리/오폐쇄망 환경에 프로젝트가 배포될 경우,
- 가로/세로 혼용 문서의 가로 스크롤 조치
- 구역 설정으로 인해 세로형 문서 중간에 가로 방향(Landscape) 페이지가 포함될 경우, 해당 가로 페이지는 구역 크기에 비례하여 화면에 훨씬 넓게 그려집니다.
- 기본적으로 뷰어 컨테이너에
overflow: auto가 설정되어 가로 스크롤바가 자동 제공되나, 모바일 뷰 등을 고려하여 한 화면에 맞추는 기능이 요구될 경우 JavaScript 단에서transform: scale(비율)스타일을 동적으로 입혀 축소 렌더링하는 반응형 고도화 적용이 가능합니다.