jsPDF 사용법
1. about
pdf 를 생성하는 Javascript 라이브러리이다.
1.1. License
MIT
1.2. 참고자료
- 공식 홈페이지 : https://parall.ax/products/jspdf
- github : https://github.com/parallax/jsPDF
- 공식 문서 : https://rawgit.com/MrRio/jsPDF/master/docs/index.html
- Live Demo : http://raw.githack.com/MrRio/jsPDF/master/index.html
구글에서 상위로 검색되는 https://artskydj.github.io/jsPDF/docs/jsPDF.html 대신 공식문서를 사용하는 것을 권한다.
2. 사용법
2.1. legacy 호환성
jsPDF 는 최신버전에서도 IE 11 과 legacy Firefox 를 지원하고 있다.
Javascript 로 PDF 를 생성하는 또 다른 라이브러리인 pdfmake 는 최신 버전에서 IE 지원을 종료하였고, pdfmake 에서 파생된 PDF-LIB, PDFKit 도 지원을 종료하였거나, 종료될 운명이고, legacy Firefox 에서도 에러가 발생한다.
IE 11 은 한참 전에 떠나 보냈어야 했다. edge 를 설치했다면, IE 11 은 사용할 수 없고, IE 11 을 사용할 수 있는 PC 란 edge 를 설치하지 않은
Windows 7
혹은 그 이하 일 텐데,Windows 7
은 chrome 업데이트도 받을 수 없고, Firefox 업데이트는 받을 수 있지만Windows 7
자체를 차단해 놓은 사이트들이 많아서 정상적인 인터넷 사용은 불가능하다고 할 것이다.Windows 7
는 현재 Windows 용 legacy 프로그램을 구동하거나 테스트 목적으로 운영하는 수준이다.
2.2. API
github 혹은 인터넷에서 쉽게 구할 수 있는 예제는 다음과 같다.
<script src="https://cdn.jsdelivr.net/npm/jspdf@2.5.2/dist/polyfills.umd.js"></script> <script src="https://cdn.jsdelivr.net/npm/jspdf@2.5.2/dist/jspdf.umd.min.js"></script>
if (!window.jsPDF) window.jsPDF = window.jspdf.jsPDF; var doc = new jsPDF(); doc.text("Hello world!", 10, 10); doc.save("a4.pdf");
doc.text
함수의 2번째, 3번째 파라미터는 각각 x, y 좌표이다.
2번째 줄을 추가하려면, 1번째 줄의 height 를 구한 다음, 이를 2번째 줄의 3번째 파라미터에 더해줘야 한다.
API 로 뭔가 하려면 Live Demo 의 "String Splitting" 을 참조하고, jsPDF-AutoTable 같은 것들도 검토한다.
pdfmake, PDF-LIB, PDFKit, 혹은 Node.js 전용의 pdfme 수준의 API 를 지원하지는 않지만, HTML 을 PDF 로 변환하는 jsPDF.html 함수만으로 충분하다고 생각한다.
2.3. 폰트 지원
공식 문서 등에 따르면, 한글과 같은 "Unicode Characters / UTF-8" 를 위한 폰트는 ttf 파일을 base64 로 변환해서 추가할 수 있다.
pdfmake 는 미리 base64 로 변환 할 필요 없이, 인터넷 주소로 추가할 수 있다.
다만, Live Demo 의 "Japanese" 편에 의하면 폰트를 ttf 파일의 인터넷 주소로 추가하는 예제가 있는데, 다음의 소스는 이를 적절히 변경한 것이다.
<script src="https://cdn.jsdelivr.net/npm/jspdf@2.5.2/dist/polyfills.umd.js"></script> <script src="https://cdn.jsdelivr.net/npm/jspdf@2.5.2/dist/jspdf.umd.min.js"></script>
if (!window.jsPDF) window.jsPDF = window.jspdf.jsPDF; var doc = new jsPDF(); doc.addFont("//cdn.jsdelivr.net/font-nanum/1.0/nanumgothic/v3/NanumGothic-Regular.ttf", "Nanum Gothic", "normal"); doc.setFont("Nanum Gothic", "normal"); doc.setFontSize(20); doc.text("なに", 20, 20); doc.text("한글", 20, 50); doc.save("한글.pdf");
공식 문서 가 현행화되지 않은 것으로 보인다.
2.4. html2canvas 와 함께 사용
jsPDF 는 주로 html2canvas 와 사용하는 것으로 보인다.
인터넷 검색에 주로 걸리는 것도 html2canvas 를 이용해서 html 을 canvas 로 변환하고, 다시 jsPDF 의 addImage 함수를 이용해서 pdf 에 canvas 를 이미지로 추가하는 것이다.
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/jspdf@2.5.2/dist/polyfills.umd.js"></script> <script src="https://cdn.jsdelivr.net/npm/jspdf@2.5.2/dist/jspdf.umd.min.js"></script>
if (!window.jsPDF) window.jsPDF = window.jspdf.jsPDF; var doc = new jsPDF({ orientation: "landscape", format: "a4", unit: "pt" }); var html = document.createElement("div"); html.setAttribute("style", "box-sizing: border-box; width:297mm; height: 210mm; background-color: #f3f3f3; border: 1px solid black;padding:2cm;"); html.appendChild(document.createTextNode("안녕")); document.getElementsByTagName("body")[0].appendChild(html); html2canvas(html, { // scale: 2 scale: window.devicePixelRatio }).then(function(canvas) { var ratio = canvas.width/doc.internal.pageSize.width; var width = Math.floor(canvas.width / ratio) - 20; var height = Math.floor(canvas.height / ratio) - 20; doc.addImage(canvas, 10, 10, width, height); doc.save("demo.pdf"); });
한글 폰트와 관련된 이슈가 발생할 여지가 없지만, 글자가 이미지로 표현되는 아쉬움도 있다.
html2pdf.js 도 위와 같이 html -> canvas -> image -> pdf 로 변환한다.
2.5. jsPDF 의 html 함수를 사용하는 방법
html2canvas 와 함께 사용하지만, 이미지를 추가하는 방식이 아니기 때문에, 한글이 깨지는 폰트와 관련된 이슈가 발생하는 한편, 더 깔끔한 PDF 문서를 얻을 수 있고, 한글 폰트 등 몇 가지 문제만 해결하면 가장 쓸만한 방법이다.
<script src="//cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/jspdf@2.5.2/dist/polyfills.umd.js"></script> <script src="https://cdn.jsdelivr.net/npm/jspdf@2.5.2/dist/jspdf.umd.min.js"></script>
var style = document.createElement('link'); style.setAttribute("rel", "stylesheet"); style.href = "//cdn.jsdelivr.net/font-nanum/1.0/nanumgothic/nanumgothic.css"; style.onload = function() { var html = document.createElement("div"); html.setAttribute("style", "box-sizing: border-box; width:21cm; height: 29.7cm; background-color: #f3f3f3; border: 1px solid black; padding:2cm; margin:0px;"); var p = document.createElement("p"); p.appendChild(document.createTextNode("안녕")); html.appendChild(p); document.getElementsByTagName("body")[0].appendChild(html); $(html).css("font-family", "Nanum Gothic"); $(html).find("*").each(function() { if($(this).css("font-family") != "Nanum Gothic") { $(this).css("font-family", "Nanum Gothic"); } }); if (!window.jsPDF) window.jsPDF = window.jspdf.jsPDF; var doc = new jsPDF({ orientation: "p", // orientation: "landscape", format: "a4", unit: "pt" }); doc.addFont("//cdn.jsdelivr.net/font-nanum/1.0/nanumgothic/v3/NanumGothic-Regular.ttf", "Nanum Gothic", "normal"); doc.setFont("Nanum Gothic", "normal"); var computedStyleWidth = $(html).outerWidth(); var computedStyleHeight = $(html).outerHeight(); var scale = doc.internal.pageSize.width/Math.ceil(computedStyleWidth); var canvasWidth = Math.floor(computedStyleWidth); var canvasHeight = Math.floor(computedStyleHeight); doc.html( html, { callback: function(pdf){ pdf.save("demo.pdf"); }, margin: [0,0,0,0], html2canvas: { scale: scale, height: canvasHeight, width: canvasWidth } } ); } style.onerror = function(error) { console.log(error); } document.getElementsByTagName('HEAD').item(0).appendChild(style);
3. jsPDF 의 html 함수를 사용 할 때 유의사항
3.1. 폰트
3.1.1. jsPDF 의 doc.addFont
함수로 한글폰트를 추가한다.
doc.addFont("//cdn.jsdelivr.net/font-nanum/1.0/nanumgothic/v3/NanumGothic-Regular.ttf", "Nanum Gothic", "normal");
폰트 이름이 "Nanum Gothic" 라는 것을 상기한다.
3.1.2. 폰트 이름에 한글이 포함되면 안된다.
폰트 이름을 한글로 하면, console 에 다음과 같은 에러가 출력된다.
jsPDF PubSub Error Invalid PDF Name Object: 나눔고딕, Only accept ASCII characters.
실행이 멈추지는 않지만, jsPDF 에서 폰트를 가져오지 못했을 것이므로 한글은 깨질 것이다.
3.1.3. @font-face
가 먼저 loading 되어야 한다.
font-family
가 "Nanum Gothic" 인 @font-face
가 먼저 loading 되어 있어야 한다.
한글이 깨지지 않지만, 웹브라우저에서 보이는 글자의 넓이와 pdf 에서 보이는 글자의 넓이가 다르기 때문에 여러 문제가 발생하게 된다.
글자 간격 같은 것에서 문제가 생기고, 가운데 정렬에서는 위치가 정확치 않고, 오른쪽 정렬에서는 오른쪽 border 를 침범하고, 왼쪽 정렬에서도 오른쪽 border 와의 간격이 가깝다면 글자 간격이 넓어져서 오른쪽 border 를 침범할 수 있다.
글자가 약간씩 겹쳐보이는 등의 오류가 보인다면,
웹브라우저에서 폰트를 미처 다 로딩되기 전에
jsPDF.html
이 호출된 것이다.
폰트 정보를 담고 있는 css 를 실시간으로 로딩하는 것은 웹브라우저에 따라 폰트 로딩이 완료되었다는 이벤트를 정확하게 받을 수 없으므로, 다음과 같이 웹페이지에 css 를 삽입해 놓는 것을 권한다.
<link rel="preload" href="//cdn.jsdelivr.net/font-nanum/1.0/nanumgothic/nanumgothic.css" as="style" /> <link rel="stylesheet" href="//cdn.jsdelivr.net/font-nanum/1.0/nanumgothic/nanumgothic.css" />
더불어 다음과 같이 페이지가 충분히 로딩된 다음에 호출될 수 있도록 처리한다.
var fontLoading = false; $(window).on("load", function() { if(document.fonts) { document.fonts.ready.then(function(fontFaceSet) { fontLoading = true; }); } else { //TODO (IE) } }); if(fontLoading) { jsPDF.html(); }
$(document).ready();
의 경우 웹브라우저에 따라서 문제가 생기는 경우가 있고, IE 11 과 같이 document.fonts 를 지원하지 않는 웹브라우저의 경우 hasfont.js 와 같은 것으로 폰트가 로딩되었는지 확인하고도, window.setTimeout 으로 약간의 시차를 두고 jsPDF 가 호출되도록 해야 한다.
3.1.4. pdf 로 변환할 html element 의 font-family
는 jsPDF 의 doc.addFont
로 추가한 폰트 이름 중에 1개이어야 한다.
$(html).css("font-family", "Nanum Gothic");
pdf 로 변환할 html element 아래에 있는 어떤 요소에서 font-family
를 명시적으로 지정했다면,
다음과 같이 하위 요소의 font-family
를 모두 "Nanum Gothic"
으로 변경한다.
$(html).find("*").each(function() { if($(this).css("font-family") != "Nanum Gothic") { $(this).css("font-family", "Nanum Gothic"); } });
예제를 기준으로
doc.addFont
로 추가한 폰트가 "Nanum Gothic" 1개 이므로,
pdf 로 변환할 html element 아래에 있는 모든 요소의 font-family
는 "Nanum Gothic" 이어야 한다.
위의 코드를 삭제하고,
다음과 같은 코드를 추가해서
pdf 로 변환할 html element 하위 요소 중
어떤 요소의 font-family
를 "Nanum Gothic" 이 아닌 다른 것으로 만들면
한글이 깨진다.
p.setAttribute("style", "font-family: NanumGothic");
"Nanum Gothic" 에서 공백만 제거하였다.
3.2. scale
웹브라우저는 pixel 을 기본 단위로 사용하고, jsPDF는 생성자에서 공급한 unit 을 기본단위로 사용한다.
jsPDF 의 21cm(=210mm) 는 595.28 pt 이고, 446.46 px (pt 의 0.75 = 72 / 96) 인데, 다음과 같은 방법으로 확인 할 수 있다.
var doc = new jsPDF({ orientation: "p", unit: "pt", format: "a4" }); console.log(doc.internal.pageSize.width); doc = new jsPDF({ orientation: "p", unit: "px", format: "a4" }); console.log(doc.internal.pageSize.width);
웹브라우저의 21cm(=210mm) 는 595.35 pt 로 거의 동일이지만, pixel 값은 793.8 px (pt * 96 / 72) 로 jsPDF 와 반대로 더 커지게 된다.
웹브라우저의 계산방법은 CSS 값과 단위 를 참조한다.
이를 보정하는 2가지 방법이 있다.
첫 번째는
hotfixes: ["px_scaling"]
를 option 으로 추가하는 것이다.
2 번째는
html2canvas
옵션에 scale
, width
, height
을 각각 추가하는 방법인데,
unit 이 px 가 아닌 경우에도 널리 사용할 수 있고,
계산은 다음과 같다.
var computedStyleWidth = $(html).outerWidth(); var computedStyleHeight = $(html).outerHeight(); var scale = doc.internal.pageSize.width/Math.ceil(computedStyleWidth); var canvasWidth = Math.floor(computedStyleWidth); var canvasHeight = Math.floor(computedStyleHeight);
canvasWidth
,canvasHeight
를 생략하거나,Math.ceil
혹은Math.floor
를 생략하면, 페이지가 넘어가는 일이 생긴다.
scale
를 구할 때 사용된
doc.internal.pageSize.width
값은
여백(margin) 이 포함되지 않은 값이다.
따라서 computedStyleHeight
나 computedStyleWidth
를 계산 할 때도
여백(margin) 이 포함되지 않도록 해야 한다.
computedStyleHeight
값이 너무 크면, 페이지가 넘어가고,
반대로 너무 작은 경우에는 페이지가 넘어가면서 넘어간 페이지에서 글자 등의 색상이 흰색으로 바뀌는 일이 생긴다.
페이지가 여러 장인 경우의 computedStyleHeight
에 대해서는 후술하기로 한다.
$(html)
이 div 같은 block 요소라면$(html).outerHeight()
는 하위 요소의outerHeight()
를 모두 더한 값 + padding 등 이 아니라, div 에 원래 부여했던 height 값에 기초한 값을 반환한다는 것에 주의한다.
scale 은 1보다 작은 값이 된다(unit 이 pt 라면 0.75 이고, unit 이 pt 가 아니라면 더 작은 값이 된다).
canvas 를 이미지로 추가하는 방법과 달리 scale 이 1보다 작은 값이어도 해상도와 관련된 문제가 생기지 않는다. canvas 를 이미지로 추가하는 방법에서도 ratio 라는 변수를 사용해서 이를 보정했었다.
이런 접근이라면, scale 값이 자동으로 결정되므로 jsPDF 생성자에 unit 파라미터를 pt 가 아닌 다른 단위로 공급할 수도 있다.
unit 파라미터를 다른 단위로 하게 되면, margin 값을 unit 파라미터와 같은 단위로 환산하는 번거로움이 줄어든다.
3.3. table border
HTML 테이블에서 border-collapse
스타일을 collapse
로 하면 안된다.
td 마다 border-top
, border-bottom
, border-left
, border-right
을 각각 설정해서 border 가 겹치지 않도록 해야 한다.
IE 11 에서는 border-width
값이 (예를 들어 0.002 cm = 0.07px) 와 같이 너무 작은 값이라면,
pdf로 변환했을 떄 border-width
가 균일하게 보이지 않는다.
Firefox 에서 border-width
가 (0.002 cm = 0.07px) 라면, Computed 는 1px (화면을 축소했다면 0.883333px 이나 더 작은 값) 이다.
<hr>
은border-style: none
으로 하고height: 0.002 cm
이라면,0.002 cm = 0.07px
는 너무 작은 값이어서 화면에 제대로 표시되지 않는 경우도 있다(Firefox 기준이며, 확대/축소 정도에 따라 다르다).
border-width
와 관련해서
jsPDF 의 px 와 pt 간 단위 변환이
웹브라우저의 그것과 반대인 것과 관련된
이슈도 있을 수 있는데,
hotfixes: ["px_scaling"]
옵션을 추가한다고 해서 개선되는 같지는 않다.
border-width
값이 (예를 들어 0.002 cm = 0.07px) 와 같이 너무 작은 값이면,
PDF 로 변환했을 때, border-width
가 균일하지 않다.
PDF 를 다시 HTML(table 은 canvas) 로 변경해서 보여주는 PDF.js 에서는 그렇지 않을 수 있겠지만, Acrobat Reader 같은 것으로 열면,
border-width
가 전체적으로 고르지 않게 보이는 것을 확인 할 수 있다.
ff 에서 border-width 를 0.002 cm = 0.07px
로 하면
Computed 는 1px (화면 축소를 했다면 0.883333px 혹은 더 작은 값) 이 되는 것처럼,
웹브라우저는 프로그래머가 입력한 값을 적당히 처리하게 된다.
논리적으로 접근하면 1px 보다 작은 값이라면 다음 중 1개로 처리 될 수 있을 것이다.
- 화면에 표시하지 않는 방법,
- 1px 로 표시하는 방법,
- 1px 로 표시하되 회색으로 변경해서 표시하는 방법
PDF 로 변환될 때는 1번, 2번, 3번이 뒤섞인다.
이를 해결하기 위해서는 border-width
가 너무 작은 값이 되지 않도록 해야 한다.
table border 를 일반적인 [한/글] 문서와 그것과 비슷한 두께로 만들기는 어려운 것으로 보인다.
개인적인 견해로는 table border 가 아예 표시되지 않는 것은 허용되지 않는 일이지만, 대부분의 사용자들이 Acrobat Reader 와 같은 전용의 PDF 뷰어를 설치하는 대신 PDF 뷰어로 웹브라우저를 사용하고 있고, PDF.js 에서는 시각적으로 이런 문제가 드러나지 않으므로, 이를 무시할 수 있다고 생각한다.
3.4. 웹브라우저 호환성
이 방식은 html -> canvas -> pdf 로 순차 변환하는 방식이고, 기본적인 웹브라우저 호환성 이슈는 당연한 것이고, 평소 눈에 잘 보이지 않았던 canvas 와 관련된 이슈와 함께 pdf 와 관련된 추가적인 이슈들도 등장한다.
예를 들어 border-width
값이 (예를 들어 0.002 cm = 0.07px) 와 같이 작은 값이라면,
화면에서는 모두 1px 로 표시되겠지만,
getComputedStyle 를 이용해서 내부적으로 계산된 값을 확인하면
Firefox 는 1px (화면을 축소했다면 0.883333px 이나 더 작은 값) 인 반면,
ie 11 은 0.07px 이고,
Firefox 나ie 11 모두 pdf 로 변환하면 border 가 균일하게 보이지 않는다.
ie 11 에서는 PDF 로 변환했을 때 border 가 사라지기도 한다.
ie 11 이라면 (같은 컴퓨터에 설치된 ff 에서와 비교해서) 견딜수 없는 수준으로 느리고, 로그 확인을 위해 Web Developer Tools 따위를 열어두었다면 더더욱 그렇다.
한편 html2canvas 가 지원하지 않는 css properties 도 있는데, 이에 대해서는 html2canvas 에서 Documentation 중 Features 에 대한 부분을 참조한다.
3.5. autoPaging
페이지가 아래로 넘치는 경우 다음과 같은 option 을 추가 함으로서, 글자가 중간에서 잘려나가는 등의 일은 피할 수 있다.
autoPaging: "text"
2번 째 이후의 페이지에서도 margin 이 적용되어야 하므로,
margin: [0,0,0,0]
을 다르게 주어야 하는데, 주의사항은 다음과 같다.
margin: [0,0,0,0]
값은 jsPDF 생성자에 공급했던 unit 값인 pt 단위로 환산한 값이어야 한다.margin = [marginTop, marginRight, marginBottom, marginLeft]
이다.
computedStyleHeight
값은 여전히 margin: [0,0,0,0]
을 기준으로 한 것이어야 하고,
이를 계산할 때도, 2 페이지부터는 각 페이지마다 (marginTop + marginBottom) 값을 추가로 더해준 값이어야 한다.
(총 페이지 수) * (1페이지의 computedStyleHeight
) 로 계산할 수도 있다.
$(html).outerHeight()
로 구해온computedStyleHeight
은$(html)
의box-sizing
가border-box
이므로, (29.7 * 3.78) = 1122.66 이어야 하지만, 최신버전의 FF 와 IE 11 에서 1122.52 로 0.06 만큼 적고, css 에서 height 값을 100배(2970 cm) 로 하면 112252 가 된다. 이는 cm 와 inch 사이의 단위환산에서 소수점 이하 자리와 관련된 문제로 보이고, 총 페이지의 수가 늘어났다면, 뒷 쪽의 페이지 경계에 있는 border 의 경우 오차를 눈으로 확인할 수 있을 정도이다.
autoPaging: "text"
의 경우 페이지가 나뉘는 곳이 table 이라면,
그 처리가 매끄럽지 않고,
경우에 따라서 사용할 수 없는 수준이 되기도 한다.
이 문제는 HTML 수준에서 미리 각각의 페이지로 분리한 다음에 pdf 로 변환하는 방법으로 해결할 수 밖에 없는 것으로 생각된다.
이런 방법은 고려해야 할 경우의 수가 많기 때문에 범용으로 사용가능한 라이브러리를 제작하기는 힘들다.
HTML 이 일정한 규칙에 따라 작성된 것이라고 전제 한 뒤에, 그 한도에서 동작하는 라이브러리를 작성하는 방법 정도를 사용할 수 있는데, 그럼에서 처리가 여간 까다로운 것이 아닌데, 대표적으로 다음과 같은 상황을 해결해야 한다.
<p>
태그의 내용이 여러 줄이고, 중간에서 잘라야 하는 경우<td>
를 잘라야 하는 경우 (border 나 rowspan 을 고려하면 더 복잡해 진다)
4. 총평
jsPDF 의 html 함수를 이용하는 방법이라면, 웹브라우저에서 PDF 를 생성하는 다른 방식들과 비교해서, 충분히 검토해볼 가치가 있다고 생각한다.
다만 서버 쪽의 PDF 생성 라이브러리와 비교하면 폰트와 관련된 아쉬움은 불가피하다.
한글 폰트의 경우 ttf 를 지원하는 cdn 이 많지 않기 때문에, 이 글의 예제와 같이 네이버에서 제공하는 나눔글꼴 을 이용하거나, ttf 파일을 서버에 올려서 client 에서 이를 다운로드 받게 해야 하는데, 대부분의 ttf 파일들은 용량도 크고, 저작권과 같은 문제도 고려해야 한다.
서버 쪽에서는 더 많은 선택지가 있는 것으로 보인다.
Apache PDFBox® 와 같이 API 기반의 라이브러리도 있지만, Apache™ FOP 와 같이 XSL-FO 로부터 PDF 를 생성하는 방법도 있고, 쓸만한 오픈소스 리포팅 도구들도 있다.
서버에 한글 폰트가 설치되어 있어야 하지만, Apache PDFBox® 나 Apache™ FOP 같이 서버 쪽 해결 방법은 용량이 매우 큰 ttf 파일을 클라이언트에 내려줄 필요가 없다는 장점이 있다.
폰트가 내장되는 방식이라면 저작권과 관련된 이슈는 반드시 해결해야 한다.
documents4j 나 간단하게 Automation 프로그램을 작성하는 방법도 있을 것이다.
서버에서 documents4j 를 포함한 Automation 방식으로 PDF 를 변환해주는 서비스를 한다면, Microsoft Office 프로그램 등의 서버용 License 를 받아야 하는 것은 물론이다.
OpenDocument 도 상관없다면 서버 쪽에서 JODConverter 같은 것도 검토해 볼 가치가 있을 것이다.
다만, 대한민국의 관공서나 그 근처는 [한/글]이 사실상 표준이나 다를바 없고, 관공서에서 OpenDocument 서식을 제공하는 일이 거의 없다.
그렇다고 하더라도 구색 맞추기 식으로 제작된 것들은 별 쓸모가 없을 수도 있다.
여러 상황들을 고려하면 [한/글] 문서를 OpenDocument 로 변환하는 결코 만만치 않은 작업이 기다리고 있을 가능성이 높다.
[한/글] 이 제공하는 도표 기능의 강력함은 [한/글] 문서를 다른 포맷의 문서를 변경하는 데 대단히 큰 난관이 되기도 한다.
[한/글] 이나 Microsoft Office 문서에서 출발한다고 가정하면, 서버용 License 를 받는 것이 일을 최소화하는 방법일 수 있겠다.
(주로 비용 문제로) [한/글] 이나 Microsoft Office 의 서버용 License 를 받는 것이 어렵다면, 검토 해 볼 수 있는 방안의 다음의 정도이다.
- [한/글] 이나 Microsoft Office 문서를 XSL-FO 로 변환하여 서버에서 Apache™ FOP 를 이용해서 PDF 로 변환하는 방법
- [한/글] 이나 Microsoft Office 문서를 HTML 로 변환하여 웹브라우저에서 jsPDF 를 이용해서 PDF 로 변환하는 방법
[한/글] (= hwpx) 이나 Microsoft Office 문서를 HTML 이나 XSL-FO 로 변환하는 라이브러리를 범용으로 만드는 일은 계산이 안되는 일이 분명하지만, 특정한 서식을 대상으로 한 라이브러리는 검토해 볼 만한 가치는 있다고 생각한다.
[한/글] 문서의 hwpx 포맷은 xml 파일들을 압축한 것이므로, binary 포맷(hwp)과는 달리 binary 를 읽는 일까지는 필요 없고, OpenDocument 이나 Microsoft Office 문서도 docx 와 같이 내부적으로는 xml 형식으로 저장된 것만 고려한다.
만약, [한/글] (= hwpx) 이나 Microsoft Office 문서를 HTML 이나 XSL-FO 중 어느 하나로 변환할 요량이라면, 작업자가 [한/글] (= hwpx) 이나 Microsoft Office 문서의 내부적인 것까지는 잘 모른다고 가정하고, HTML 이나 XSL-FO 중 작업자에게 더 익숙한 방식을 선택하면 될 일이다.
XSL-FO 를 이용하는 방법은 PDF 를 서버에서 생성하므로 환경이 정해져 있을 뿐만 아니라 환경을 임의로 조정 할 수도 있지만, 작업자가 XSL-FO 에 익숙하지 않다면, 위험한 시도일 가능성이 높다.
jsPDF 를 이용하는 방법은 결과물이 PDF를 생성한 웹브라우저의 종류나 버전에 따라 다소간의 차이가 나는 것을 감수해야 한다.