Files
PM_test/한글파일미리보기작업내역.md
2026-06-19 17:58:47 +09:00

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.jsfont.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)을 보정했습니다.

② 단락 및 텍스트 줄 겹침 결함 수정

  • drawTextdrawParagraph 메서드 내에서 텍스트가 삽입되는 각 div 스팬과 컨테이너에 line-height: 1.65 인라인 스타일을 적용해 부모 스타일시트에 의해 줄 영역이 위아래로 포개어지는 문제를 예방했습니다.

③ 도형(Rectangle/Ellipse/Line)의 SVG 배경 레이어 렌더링 고도화 및 좌표 보정

  • HWP 파서의 visit 메서드 내에 직사각형, 타원, 선, 호, 다각형, 자유곡선 레코드 ID들을 식별하도록 등록하고 도형 타입을 구분 지었습니다.
  • drawParagraph 렌더링 시 문단 div 요소를 쪽(Page)에 즉시 추가하여 자식 도형들의 절대 배치 위치 기준(parentNode)이 정상적으로 작동하도록 수정했습니다.
  • drawShape 메서드에서 도형의 세로 기준 설정(vertRelTo)을 분석합니다.
    • vertRelTo === 2 (문단 기준): 문단 컨테이너 divposition: 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.js API를 연동했습니다.
  • WMF 이미지 원본 크기를 측정하여 브라우저 메모리에 가상 <canvas> 엘리먼트를 생성해 캔버스에 이미지를 렌더링한 후, canvas.toDataURL('image/png')를 추출해 div의 backgroundImage에 바인딩했습니다.

2.5 팝업 미리보기 리소스 추가 로드 및 스타일셋 개선

  • 대상 파일:
  • 내용:
    • popup.htmlfont.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. 조치사항 (운영 및 유지보수 가이드)

프로젝트 운영 단계에서 발생 가능한 상황에 대한 대처 방안입니다.

  1. 클라이언트 캐시 갱신 (가장 중요)
    • 백엔드 코드와 달리 프론트엔드 자바스크립트(hwp.js, font.css) 및 스타일시트(style_archive.css) 파일은 클라이언트 브라우저가 강력하게 캐싱합니다.
    • 렌더링 개선 내역이 정상적으로 적용되지 않을 경우, 브라우저에서 Ctrl + F5(강제 새로고침)를 수행하거나 개발자 도구(F12)의 네트워크 탭에서 **'캐시 사용 안 함(Disable Cache)'**을 활성화한 후 재시도하십시오.
  2. 폐쇄망(오프라인) 배포 시 폰트 로드 조치
    • 현재 등록된 폰트는 구글 웹 폰트 CDN 주소를 사용합니다. 만약 외부 인터넷 접근이 불가능한 망분리/오폐쇄망 환경에 프로젝트가 배포될 경우, @import 주소의 구글 폰트를 가져오지 못해 폰트가 기본형으로 깨질 수 있습니다.
    • 조치 방안: views/main/css/ 하위에 fonts/ 디렉토리를 생성하고, NotoSansKR.woff2, NotoSerifKR.woff2 파일을 서버에 저장한 후 font.css에서 상대 경로(url('./fonts/...'))로 서빙하도록 경로를 전환해야 합니다.
  3. 가로/세로 혼용 문서의 가로 스크롤 조치
    • 구역 설정으로 인해 세로형 문서 중간에 가로 방향(Landscape) 페이지가 포함될 경우, 해당 가로 페이지는 구역 크기에 비례하여 화면에 훨씬 넓게 그려집니다.
    • 기본적으로 뷰어 컨테이너에 overflow: auto가 설정되어 가로 스크롤바가 자동 제공되나, 모바일 뷰 등을 고려하여 한 화면에 맞추는 기능이 요구될 경우 JavaScript 단에서 transform: scale(비율) 스타일을 동적으로 입혀 축소 렌더링하는 반응형 고도화 적용이 가능합니다.