(UI컴포넌트)webPonent CHART 2.1.0 버전 업그레이드

안녕하세요.

HTML5 기반의 데이터 인포그래픽 컴포넌트 webPonent CHART의 Visual Radar Chart 추가 버전 업그레이드 소식을 안내드립니다.

webPonent Visual Radar CHART

추가된 Radar 차트의 기능 및 사용환경은 아래와 같습니다.

(Radar CHART)

- 여러 개의 데이터를 한번에 보여주기 유용

- 데이터 개수에 따라 다각형 세팅 가능

- 차트 눈금 개수 지정 가능

- Tick 모양(, 사각형, 삼각형, , 다이아몬드) 설정 가능

- Tooltip을 이용해서 커서가 틱을 가리킬 때 해당 데이터를 불러올 수 있음

- 시계열 사용 가능

- 애니메이션 효과 사용 가능

- 범례 사용 가능

- 데이터의 크기를 패턴으로 나타낼 수 있음

 

(사용환경)

- 서버: 모든 서버

- 언어: 개발언어에 종속되지 않음(html, css, javascript로 구현)

- 브라우저: IE(8이상 최신버전), 크롬, 파이어폭스, 사파리 등

- 모바일: HTML5 SVG를 지원하는 모든 단말기

- 통신: json 혹은 text 형식의 데이터를 ajax(url)이나 배열 형태로 통신

 

Radar차트는, 솔루션 홈페이지에 있는 전용에디터 또는 트라이얼을 다운받아 체험해 보실 수 있습니다.

[webPonent CHART 특징] 

[webPonent 데모 페이지]

[webPonent 트라이얼 페이지] 

 

webPonent CHART 기능

New Multi-Channel Dynamic CMS

[웹포넌트 차트] webPonent Visual Gauge Chart

[웹포넌트 차트] webPonent Visual Gauge Chart



webponent CHART 2.0.6 버전이 릴리즈 되었습니다. (짝짝짝)

2.0.6버전에 맞추어 새롭게 추가된 Gauge Chart에 대해 작성해보려 합니다.


gauge chart는 크게는 원형 게이지(angular), 선형 게이지(Linear), 실린더(cylinder), 온도계(thermometer) 이렇게 크게는 4가지, 세부적으로는 8가지 타입으로 구성되어져 있습니다.


디자인 테마로는 기본 디자인(Basic), 블랙 디자인, 라이트 그레이 디자인 3가지 종류가 있습니다.


여기에 option과 style을 주어 원하는 색상의, 모양의 게이지를 만드실 수 있습니다.

예를 들면, 하나의 실린더도 필요에 맞게, 나만의 스타일로 변경 가능합니다.



사이즈 조절!  색상 조절!  위치 조절! 


사용자가 어떠한 용도로, 어떠한 형태로 만들어서 사용할지 모르기 때문에 최대한 많은 부분을 변수로 

고 필요에 맞게 변경할 수 있도록 노력했습니다. 

웹포넌트 퍼블리셔 를 통해 테스트하실 수 있습니다. )




라파엘.js를 사용하여 그리기 


Raphael JS는 벡터 그래픽을 웹에 그려주는 가벼운 자바스크립트 프레임워크입니다. 

처음 접해본 라파엘.js는 비쥬얼적으로 결과가 바로바로 보여지니 뿌듯하고 재밌었습니다.  사실, 처음에 

각도에 대한 계산이 제일 큰 복병이었습니다. ㅠ_ㅠ 

( 다른 오픈소스들을 찾아보고 참조해보았지만... 아..... 수학...... 수학과 어디계시죠 )


하지만, 무수한 수의 대입과 그에 따라 그려지는 차트들을 보면서 점점 코드에 대해 이해가 되었습니다.

사실, 수학적 원리보다는 다양한 수를 넣고 실행해보면서 어느 방향으로 간다던지, 시작 지점이 어디인

 등을 파악하고 이를 응용했습니다. 그렇게 탄생한 원형게이지 차트와 실린더 차트는 더 많은 손이 가고 

신경이 쓰였던 type입니다.


<원형 게이지 차트> normal(좌), multi, dual(우)

<선형 게이지 차트> Solid(좌), Pointer, LED(우)



<실린더 차트 & 온도계 차트>




- 스크립트 분산의 필요성 

초기 개발때, 하나의 자바스크립트에 타입별로 나누어 코드를 작성하였더니, 공통으로 사용하지만 위치

나 스타일이 타입에 따라 다른 것들이 많았습니다. 이러한 차이점을 구분에 있어 가정문도 늘어나고 많

은 반복문들이 들어가게 되면서 코드의 복잡도가 증가하고 비효율적인 코드들이 하나둘씩 생기기 시작

했습니다


모든 차트들이 제기능을 시작 할때 쯤 , '더 늦기전에 나눠야겠다!' 라고 생각하여 타입별 스크립트 분산

작업을 시작하였습니다.


스크립트를  나누고 난 후 작동원리나 부가적인 옵션들은 동일하므로 한곳을 수정하면 나머지 스크립트

들도 수해야했으며 그럴때마다 왔다 갔다 하면서 헷갈리기도 하고, 타입별로 조금씩 다른 차이점에 대

해서도 고려해야 했습니다.

BUT, 만약 한개의 스크립트에 있었다면 더더더 복잡한 코드가 되지 않았을까? 하는 생각이듭니다.


                                



사실 처음부터 정리를 잘했다면 번거로운 작업이 줄었을지도 모릅니다. 생각해보면 Naming에 있어서도

오픈소스로 공개 된 Gauge Chart를 참조했다면 더 쉬웠을지도 모르죠. 하지만 누가봐도 딱 그걸말하는

구나! 하고 생각할 수 있는 Naming을 찾으며 주변에 물어보고, 검색엔진에 쳐보며 노력했습니다. 


이렇게 탄생한 Webponent Gauge CHART! 유용하게 사용되었으면 좋겠습니다. 감사합니다.


"A mistake is a signal that
it is time to learn something new, something you didn't know before"

                                                                                                           - Robert Kiyosaki






더 많은 gauge chart에 대한 자세한 기능과 샘플을 확인하고 싶으시다면 아래 관련 사이트 목록에 있는 사이트들을 방문해주시길 바랍니다. 감사합니다. ^_^


웹포넌트 관련 사이트 목록

 사이트명

설명

 웹포넌트 공식 사이트

 웹포넌트 공식 사이트로 제품에 대한 상세 설명 보기, 트라이얼 다운로드가 가능합니다.

 웹포넌트 퍼블리셔

 웹포넌트 차트, 그리드에 관련한 예제 코드를 보거나 편집할 수 있습니다.

 기술지원 사이트

 제품에 대한 질문을 게시할 수 있으며, 구매하신 고객의 경우 제품문의를 할 수 있습니다. FAQ, 버전 이력, 공지사항을 확인할 수 있습니다.

 웹포넌트 샘플 사이트

  웹포넌트 차트, 그리드에 관련한 예제를 확인할 수 있습니다.

 



New Multi-Channel Dynamic CMS

[웹포넌트 가상키보드] 다운로드부터 설치까지!!

[웹포넌트 가상키보드] 

다운로드부터 설치까지 같이 해볼까요?







두달전쯤 webPonent VIRTUAL KEY(웹포넌트 가상키보드)를 출시하고 '박토끼' MD가 직접 소개글을 써주셨는데요. 이번글에서는 제가 가상키보드를 다운로드에서 부터 설치까지 진행해보고 직접 사용까지 해보겠습니다.

 

웹포넌트 가상키보드는 가격이 저렴할뿐만 아니라 30일간 사용 할 수 있는 트라이얼 버전을 제공해서 무료로 현재 서비스하는 페이지에 직접 적용 시켜 바로 확인 할 수 있습니다.

 

바로 다운로드할 수 있는 페이지로 가볼게요!

웹사이트로 이동 을 누르시면 웹포넌트 사이트로 이동하는데요 

아래와 같이 중간쯤에 보면 CHART, GRID 제품외에 가상키보드 제품 메뉴가 보입니다. 



위에 빨간색 네모박스 버튼을 누르면 트라이얼 다운로드 페이지로 이동합니다. 거기서 아래 버튼을 누르시면 다운로드 받을수 있습니다.


다운로드 바로가기


다운받은 zip파일을 압축을 풀면 30일간 사용할 수 있는 라이센스 파일과 keypad관련 zip파일이 또 나오는데요.


webPonent-VirtualKey-1.0.0.zip 을 다시 압축을 풀면 아래와 같이 파일을 확인 할 수 있습니다.



 


간단하게 파일을 설명드리자면 keypad 디렉토리에는 가상키보드에서 사용되는 이미지 파일과 스크립트 파일등 필요한 리소스가 포함되어 있고 샘플 페이지도 포함되어 있습니다. (sample.html

다음으로 WEB-INF에는 eltz-keypad.jar 과 가상키보드 구동에 필요한 서블릿 정보가 있는 web.xml 이 있습니다.

마지막으로 index.html은 샘플 페이지로 이동 시켜주는 스크립트만 있고 꼭 필요한 파일은 아닙니다.


자, 이제 필요한 파일은 준비가 되었으니 간단하게 설치해보고 구동 시켜보도록 하겠습니다.


아참! 이번 데모에서 IDE는 이클립스(mars)를 사용하고 JDK는 1.7을 사용 하겠습니다. 그리고 WAS는 tomcat6 을 사용하겠습니다.


그럼 고고고!!


첫번째로 압축을푼 파일들을 이클립스 프로젝트로 옮겨보도록 할게요.




이번 데모를 위한 프로젝트라 구성이 심플하죠? 

참고로 result.jsp, sample.html, index.html 3가지 파일은 샘플을 위한 파일이므로 실제로 적용 될때는 필요 없는 파일입니다.


이제 두번째로 간단하게 설정값들을 변경해줘야 합니다.

keypad/js/keypad.js 파일 7,8 라인에 KEYPAD_HOME, KEYPAD_CONTEXT_ROOT 변수에 기본 값이 세팅되어 있습니다. 

KEYPAD_HOME 은 keypad디렉토리의 위치인데요 기본값이 /keypad/ 으로 되어있을겁니다.

지금 데모에서 처럼 루트 디렉토리 바로 아래에 위치한 경우에는 변경할 필요가 없습니다. 다만 디렉토리 위치가 다르다면 해당 위치에 맞게 수정해주셔야 합니다.

다음 설정값으로 KEYPAD_CONTEXT_ROOT 은 WAS의 Context Path인데요 기본값이 '/' 으로 되어 있습니다.

이값도 마찬가지로 서버설정에 맞춰서 수정해주시면 됩니다.

저는 아래와 같이 Context Path를 '/'로 되어있기 때문에 기본값들을 변경하지 않을게요~!

자, 이제 한가지 작업만 더 해주시면 끝납니다. 어떤 작업이 남았을까요??

네 맞습니다! 라이센스 파일을 추가해야 합니다 ㅋㅋ

좀 전에 위에서 첫번째 압축을 풀어서 나온 webPonent.virtualKey.license 이 녀석을 추가 하셔야 하는데요.

이 라이센스 파일을 WEB-INF 디렉토리 바로 아래에 추가 하셔야 합니다. 아무데나 추가 하시면 안되요 ㅠㅠ


그럼 요놈 써보고 우왕~! 마음에 들어서 정식라이센스를 구입하시면 라이센스 파일만 교체하면 되겠죠?? 


이제 서버가 가동 시키면 됩니다. 서버를 Start 하고 localhost 접속하시면 샘플 페이지가 뜹니다.

80포트가 아니면 포트도 붙여주세요 ^^;;



자, 이렇게 샘플페이지가 두둥 떴습니다~!!

숫자+문자 입력과 숫자만 입력하는 password input으로 구성된 심플한 페이지 입니다.

문자 password를 누르시면 아래와 같이 기본테마가 적용된 QWERTY 자판이 뜨죠? 지금 디바이스가 PC기 때문에 PC모드로 나타납니다. mobile이나 tablet으로 접속하시면 각각 다른 크기와 모습으로 나올거에요~

참고로 mobile에서는 pc에서 없는 다른 키입력 방식이 추가 되어있습니다. 꼭 확인해보세요

뭐 사실 지금 부터는 여기 에서도 확인 가능해요ㅋㅋ



혹시 키보드 색상이 마음에 안드시나요??

걱정마세요! 왼쪽 상단에 테마를 선택하는 셀렉트 박스가 있습니다. 여기서 이것저것 바꿔보세요~ 마음에 드는 색상이 나오셨나요? .... 부족하다면 더 추가 해야겠네요 말씀해주세요..


저는 개인적으로 블랙02 테마가 마음에 드네요 ㅎㅎㅎ


비밀번호를 테스트삼아 입력하고 OK를 눌러볼까요? 저는 'abcd'를 하고 Let me in 버튼을 눌렀습니다.

그럼 비밀번호가 암호화되어서 서버로 전성되고 샘플로 만들어진 서버에서 복호화 한다음 'abcd' 값을 정상적으로 다시 보내줬네요.



가상키보드로 작성된 모든 값은 암호화되서 서버로 전송이 됩니다.

확인해볼까요?


위와 같이 알 수 없는 문자로 암호화되서 전달되어 정상적인 가상키보드의 Request가 아니면 복호화 할 수 없어 개인정보를 안전하게 지킬 수 있습니다.


그럼 응답도 한번 보죠.


위와 같이 정상적으로 복호화되서 응답이 왔네요~~


이번글은 여기에서 마무리 하고 다음 블로그에서는 웹포넌트 가상키보드가 제공하는 다양한 API 설명과 각 입력모드에 따른 사용법을 자세히 다뤄 보도록 하겠습니다.



웹포넌트 사이트에서는 제품의 구성도(구조와 플로우), 기능 설명, 데모, 개발문서, 관련자료 등 웹포넌트 가상키보드와 관련된 컨텐츠를 보실 수 있습니다.  


 webPonent VIRTUAL KEY 특징 

 http://www.webponent.com/products/keypad/feature.cmd

 webPonent VIRTUAL KEY 데모

 http://www.webponent.com/products/keypad/demo.cmd

 webPonent VIRTUAL KEY 개발문서

 http://www.webponent.com/products/keypad/devdoc.cmd

 webPonent VIRTUAL KEY 사용법

 http://www.webponent.com/products/keypad/guide.cmd

 webPonent VIRTUAL KEY 관련자료

 http://www.webponent.com/products/keypad/refData.cmd

 webPonent VIRTUAL KEY 가격

 http://www.webponent.com/products/keypad/price.cmd


웹포넌트 가상키보드의 구매 문의는 02-784-2503 혹은 이 포스팅의 댓글로도 가능합니다. ^^)
























New Multi-Channel Dynamic CMS

[웹포넌트 가상키보드] 웹 사이트를 안전하게 만드는 가장 손쉬운 방법

[웹포넌트 가상키보드] 

웹 사이트를 안전하게 만드는 가장 손쉬운 방법





저번주 금요일, 웹포넌트 2차 리뉴얼 사이트를 오픈하면서 새롭게 webPonent VIRTUAL KEY(웹포넌트 가상키보드)를 동시에 출시하였습니다! 새롭게 출시한 제품은 여태까지 웹포넌트에서 선보인 데이터 시각화 및 처리에 유용했던 CHART, GRID와는 조금 다른 성격입니다. '웹 사이트를 안전하게 만드는 가장 손쉬운 방법'이라는 캐치프레이즈에 걸맞게 아주 간편하게 웹 사이트에 보안키패드를 사용할 수 있게 해주는 제품입니다. 


시중 은행 사이트에 들어가면 꼭 보게 되는 것은 바로 가상키보드 입니다. 가상키보드는 말 그대로 물리적인 키보드가 아니라 화면에 가상으로 나타나는 키보드입니다. 멀쩡한 키보드가 있는데, 왜 굳이 불편한 가상키보드를 사용해야할까요? 생각해보신적 있으신가요?


바로 '정보를 보호하기 위해서'입니다. 전화번호나 주민등록번호, 은행 계좌의 비밀번호 등과 같이 개인의 중요한 정보를 직접 키보드로 입력하게 되면 문제가 발생할 수 있습니다. 해킹프로그램이 사용자가 키보드로 입력하는 키값을 탈취하여 개인정보를 빼낼 수 있기 때문입니다. 그래서 금융거래가 일어나는 사이트는 키보드로 직접 입력해도 안전하도록 키보드 보안프로그램을 필수적으로 설치해야만 합니다. 보안프로그램을 설치하지 않은 사용자는 가상키보드로 이용할 수 있도록 입력하는 박스 옆에 '가상키보드' 혹은 '마우스로 입력'이라는 버튼을 두곤합니다. 


이쯤에서 한 번 떠올려볼까요? 금융권 이외의 다른 웹사이트에서 가상키보드를 본적이 있으신가요? 아마 잘 없으실 겁니다. 이처럼 금융 관련 사이트가 아닌 웹사이트에서 사용자의 개인 정보 보호에 대한 대비는 미미합니다. 금전 거래는 은행 사이트에서만 일어나는 것이 아니죠. 수없이 많은 온라인쇼핑몰에서도 금전거래는 발생합니다. 그리고 아무런 보안도 되어 있지 않은 사이트에 우리는 전화번호나 주민등록번호, 집주소 등 일상생활에서 각종 사기 범죄에 사용될 수 있는 개인 정보를 아무렇지 않게 입력합니다. 또한 사내에서 사용하는 시스템에서는 회사에서 누출되지 않아야할 정보들이 웹브라우저를 통해 입력되고 서버로 전송되는 경우도 있습니다. 


이미 본인이 서비스하고 있는 웹사이트에서 사용자가 입력하는 정보에 대해 보호해야할 필요성을 느끼고 계셨을 수도 있습니다. 그러나 보안프로그램 사용하는 것을 망설이셨다면 아마도 가격 요인이 가장 크지 않을까 싶습니다. 유명 보안프로그램들의 금액은 약 1,000만원 수준으로 조금은 부담스럽게 느껴질 수 있습니다. 은행 웹사이트처럼 사이트 전체에서 중요한 정보가 오가는 것이 아니라, 일부 화면에서만 보안이 필요한 경우에는 보안프로그램을 사이트에 도입하는 것이 더더욱 망설여지셨을 것입니다. 사이트가 무거워지기도 하고 말이죠.


이런 분들에게 안성맞춤인 제품이 바로 웹포넌트 가상키보드입니다. 99만원(!!!)이라는 합리적인 가격으로 손쉽게 보안을 향상시켜줍니다. 웹포넌트 가상키보드는 HTML5 기반의 일상적인 보안을 위한 컴포넌트로, 기존에 서비스 중인 사이트에 소스 몇 줄만 추가하면 키보드를 설치할 수 있습니다. 





[웹포넌트 사이트 가상키보드 페이지 바로가기]



웹포넌트 가상키보드는 가격과 편리한 추가 뿐만 아니라 8가지의 색상 테마와 키 입력 방식 지원, 멀티 디바이스 지원, 모바일에서의 다양한 입력방식과 배치 방식 지원 등의 특징이 있습니다. 지원환경은 Java jdk1.5~1.7, 브라우저 IE8이상 / Chrome / FireFox / Safari / Opera, 안드로이드 2.2 Froyo 이상, ios 4.2.1 이상입니다. 


웹포넌트 사이트에서는 제품의 구성도(구조와 플로우), 기능 설명, 데모, 개발문서, 관련자료 등 웹포넌트 가상키보드와 관련된 컨텐츠를 보실 수 있습니다.  



 webPonent VIRTUAL KEY 특징 

 http://www.webponent.com/products/keypad/feature.cmd

 webPonent VIRTUAL KEY 데모

 http://www.webponent.com/products/keypad/demo.cmd

 webPonent VIRTUAL KEY 개발문서

 http://www.webponent.com/products/keypad/devdoc.cmd

 webPonent VIRTUAL KEY 사용법

 http://www.webponent.com/products/keypad/guide.cmd

 webPonent VIRTUAL KEY 관련자료

 http://www.webponent.com/products/keypad/refData.cmd

 webPonent VIRTUAL KEY 가격

 http://www.webponent.com/products/keypad/price.cmd


웹포넌트 가상키보드의 구매 문의는 02-784-2503 혹은 이 포스팅의 댓글로도 가능합니다. ^^)








New Multi-Channel Dynamic CMS

PhantomJS로 GRID&CHART를 PDF 출력하기 (4편 : Event Listners)


안녕하세요. CX사업부 MD 태태입니다.

오래간만에 PhantomJS 를 이용하여 PDF를 생성하는 글을 포스팅합니다.

지난 3번의 포스팅을 통하여 기본적인 PhantomJS를 통한 PDF출력에 대해 살펴보았는데, 이번 글에서는 PhantomJS에서 제공하는 다양한 Event listener에대해 살펴보겠습니다.

웹화면을 PDF형식으로 출력하다보면 예상치않은 웹상의 오류에 대해 대처해야하거나, JavaScript로직의 실행시점을 알아야 하는등 다양한 문제가 발생할 수 있습니다. 이럴 때 사용할 수 있도록 PhantomJS는 몇가지 Event listener를 제공해주고 있는데, 이번 포스팅에서는 webPonent 제품을 개발할 때 유용하게 사용되었던 것들을 중심으로 소개하고 설명해드리도록 하겠습니다.


  • onError
PhantomJS로 웹페이지에 접속을 처음 시도할 때 가장 난감한 경우는 웹페이지 자체에서 나는 에러때문에 제대로 스크립트가 실행되지 않을 경우일 것입니다. 이 리스너는 이럴 경우 사용하는 리스너입니다. 글로 길게 설명하기 보다는 실제 예제코드를 통해서 설명해 드리겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var webPage = require('webpage');
var page = webPage.create();
 
page.onError = function(msg, trace) {
    var msgStack = ['ERROR: ' + msg];
 
    if (trace && trace.length) {
        msgStack.push('TRACE:');
        trace.forEach(function(t) {
            msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
        });
    }
 
    console.error(msgStack.join('\n'));
};
 
page.open('http://test.com/'function(status) {
    console.log('Status: ' + status);
    phantom.exit();
});
cs
간단한 PhantomJS script입니다. http://test.com(이 URL은 코드 이해를 돕기 위한 가상의 URL입니다.)로 접속해서 상태만 로그출력한 후 종료하도록 작성되어 있습니다. 그리고 page.onError 객체에는 메시지를 받아서 콘솔에 출력하도록 작성했습니다.

http://test.com/의 내용은 아래 코드와 같습니다.

1
2
3
4
5
6
7
8
9
10
11
<html>
<head>
    <title></title>
</head>
<body>
<h1>테스트 페이지입니다.</h1>
<script>
    console.log(value);
</script>
</body>
</html>
cs
설명이 필요하지 않을정도로 간단한 HTML코드입니다. 단, 스크립트에서 콘솔로 value라는 변수를 출력하는데 코드 어디에도 value변수를 선언하지 않았지요. 스크립트 오류가 발생할 것입니다.

이제 결과를 확인해 보겠습니다.

콘솔창에 JavaScript에러 메세지가 출력된 것을 확인할 수 있습니다. 이렇게 onError 리스너는 스크립트 에러와 같은 페이지상의 에러가 발생했을 때 실행되는 이벤트리스너입니다.

  • onConsoleMessage
JavaScript의 console.log() 함수를 이용해서 콘솔을 출력 할 수 있다는 것을 알고계실 것입니다. onConsoleMessage는 그런 콘솔메시지가 출력될 때 호출되는 리스너입니다. 쉬운 개념이니 바로 간단한 예시를 보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var webPage = require('webpage');
var page = webPage.create();
 
page.onError = function(msg, trace) {
    var msgStack = ['ERROR: ' + msg];
 
    if (trace && trace.length) {
        msgStack.push('TRACE:');
        trace.forEach(function(t) {
            msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
        });
    }
 
    console.error(msgStack.join('\n'));
};
 
page.onConsoleMessage = function(msg) {
  console.log('CONSOLE: ' + msg);
};
 
page.open('http://test.com/'function(status) {
    console.log('Status: ' + status);
    phantom.exit();
});

cs


위에서 사용된 script에 onConsoleMessage에 대한 정의가 추가 되었습니다. 또한 HTML파일을 살펴보면
1
2
3
4
5
6
7
8
9
10
11
12
<html>
<head>
    <title></title>
</head>
<body>
<h1>테스트 페이지입니다.</h1>
<script>
    var value = "This is PhantomJS test page.";
    console.log(value);
</script>
</body>
</html>
cs
위에선 없었떤 value변수에 대한 선언이 추가되었습니다. 이제는 value 변수가 선언되지 않았다는 에러 대신에 value함수에 할당된 텍스트메시지가 로그에 출력되겠지요. 그럼 결과를 확인하겠습니다.

'This is PhantomJS test page.'라는 메시지가 출력되었지요. 위 페이지코드의 스크립트 실행결과와 완전히 동일한 결과입니다. 이 리스너또한 페이지의 로그를 확인하고 싶을 때 유용하게 사용되는 리스너입니다.


  • onInitialized
웹 페이지가 생성되었지만 아직 페이지 전체가 load되지 않았을 때 발생되는 이벤트 리스너입니다. 아래에서 설명되는 onLoadFinished와 함께 예제를 설명하겠습니다.

  • onLoadFinished
웹 페이지가 생성된 후 모든 객체가 load된 후에 발생되는 이벤트리스너입니다. 단 이 이벤트가 발생되는 시점이 JavaScript의 모든 로직이 다 실행되었다는 의미는 아니기 때문에 구분해서 사용해야 합니다.

그러면 이제 onInitialized 리스너와 함께 코드예시를 확인해 보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var webPage = require('webpage');
var page = webPage.create();
 
page.onError = function(msg, trace) {
    var msgStack = ['ERROR: ' + msg];
 
    if (trace && trace.length) {
        msgStack.push('TRACE:');
        trace.forEach(function(t) {
            msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
        });
    }
 
    console.error(msgStack.join('\n'));
};
 
page.onConsoleMessage = function(msg) {
    console.log('CONSOLE: ' + msg);
};
 
page.onInitialized = function() {
    console.log("onInitialized");
}
 
page.onLoadFinished = function (status) {
    console.log("onLoadFinished Status : " + status);    
}
 
page.open('http://test.com/'function(status) {
    console.log('Status: ' + status);
    phantom.exit();
});
cs

onInitialized, onLoadFinished 리스너를 등록한 후 이벤트 발생 시점의 차이를 확인 해 보겠습니다.

확인결과 onInitialized 이벤트가 먼저 발생되고 (Page opened) onLoadFinished 이벤트가 발생된 후 page.open() 함수의 콜백함수가 실행되는 것을 확인 할 수 있습니다.

이 결과에 따라서 onInitialized 이벤트 리스너에는 페이지가 로딩되기 전 등록해야 하는 웹 이벤트 리스너를 등록하거나 변수, 객체를 선언하는 용도로 사용하고, onLoadFinished 리스너에 페이지가 로딩된 후의 동작을 등록해서 사용하면 시점이 어긋나지 않고 사용할 수 있을 것입니다.


  • onCallback
마지막으로 onCallback 이벤트 리스너입니다. 개인적으로 webPonent 용 PhantomJS script를 작성할 때 가장 큰 도움을 받았고, 많은 분들이 가장 빈번하게 사용하지 않을까 하는 리스너입니다. 이 리스너는 사용자가 원하는 시점에 이벤트를 발생시킬 수 있습니다. window.callPhantom() 함수를 통해서 client-side에서 이벤트를 발생시킬 수 있고, server-side에서는 다시 return값을 발생시켜서 넘겨줄 수도 있습니다. webPonent CHART나 GRID의 복잡한 JavaScript 로직이 끝나는 시점에 이 이벤트를 발생시켜서 시간손실을 최소화하여 더 신속하게 PDF문서를 생성할 수 있는 로직을 작성할 수 있었습니다.
그럼 마찬가지로 예제를 보여드리겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
<head>
    <title></title>
</head>
<body>
<h1>테스트 페이지입니다.</h1>
<script>
    if (typeof window.callPhantom === 'function') {
        var status = window.callPhantom({
            message: 'Hello'
        });
 
        console.log(status);
    }
</script>
</body>
</html>
cs

먼저 onCallback 리스너 테스트를 위한 HTML 코드입니다. 스크립트상에서 window.callPhantom 객체가 function type으로 존재하면 JSON Object를 인자로 넘겨서 호출합니다. 이 때의 결과값을 status변수에 저장한 후 console에 출력하는 로직이 작성되어 있습니다.


이 페이지를 여는 PhantomJS script를 보면 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var webPage = require('webpage');
var page = webPage.create();
 
page.onCallback = function(data) {
    if (data && data.message && (data.message.toLowerCase() === 'hello')) {
        return "World!";
    } else {
        return 'Say hello please.';
    }
};
 
page.onConsoleMessage = function(msg) {
  console.log('CONSOLE: ' + msg);
};
 
page.open('http://localhost:1010/'function(status) {
    phantom.exit();    
});
cs

onCallback 이벤트 리스너를 등록하여서 data 객체의 message가 'hello'이면 'World!'를 아니면 'Say hello please.'를 반환하는 로직을 작성했습니다. 이 로직의 결과를 살펴보겠습니다.

2번째 결과는 message 요소에 'hello'대신 다른 문자열을 대입하고 실행해본 결과입니다. onConsoleMessage를 통해 출력된 콘솔메세지를 확인하실 수 있습니다. 이 리스너를 통해 조금 더 세부적으로 시점을 알 수 있습니다.


이정도가 가장 유용하게 쓰일 수 있는 이벤트 리스너입니다. 이렇듯 리스너를 사용하면 훨씬 더 세부적이고 디테일한 시점에따른 기능을 추가할 수 있습니다. 비단 PDF출력 뿐 아니라도 PhantomJS의 여러기능들을 사용할 때 활용하실 수 있었으면 좋겠습니다.






New Multi-Channel Dynamic CMS

[웹포넌트 그리드] 일반 HTML 테이블의 한계를 뛰어넘는 데이터 그리드!

[웹포넌트 그리드] 

일반 HTML 테이블의 한계를 뛰어넘는 데이터 그리드!






Q1. 데이터 그리드는 왜 사용할까요?


데이터를 표현하기 위해서 일반 HTML 테이블을 쓰는 것은 보편적인 관행이었습니다. 데이터에 레코드가 많지 않거나 데이터를 사용자가 조작하게 하고 싶지 않는 한 일반적인 테이블을 사용해도 전혀 문제가 없습니다. 그러나 테이블에 수 백 건의 레코드를 사용하는 웹 애플리케이션을 구축할 때라면, 일반 HTML 테이블로 데이터를 표현하는 데에 아주 큰 사용상 결함을 겪게 될 것입니다. 


예를 들어, 일반 테이블로 1000건의 데이터를 표현한다고 가정해보겠습니다. 하나의 로우(<tr>)당 30px 이라고 한다면, 제목(thead)영역까지 포함하여 테이블의 길이는 30,030px이 될 것입니다. 24인치 모니터로 웹 페이지를 볼 때 스크롤을 사용하지 않고 한 번에 볼 수 있는 높이는 약 1000px 정도 입니다. 30,030px이라면 모니터 화면을 세로로 30개나 붙인 것과 유사한 길이 입니다. 만약 사용자가 이 정도로 길이가 긴 페이지에 접속했다면 엄청난 스압(스크롤 압박)을 견디지 못하고 바로 뒤로가기를 눌러버릴 것입니다. 게다가 렌더링하는 시간도 길어져 성능상의 문제도 발생하겠죠.


정렬, 필터링, 검색, 인라인 에디팅같은 기능들을 일반 HTML 테이블로 사용하기는 힘듭니다. 이와 같은 일반 HTML 테이블의 한계를 뛰어넘어, 대용량의 데이터를 표현하고 조작하는 데에 수월하기 위해 '그리드'를 사용하는 것입니다. 데이터 그리드는 정렬, 필터링, 검색, 페이지네이션, 심지어 인라인 에디팅 같은 기능을 제공함으로써 큰 데이터셋을 가진 HTML 테이블과 관련한 작업들을 수월하게 만들어줍니다.



Q2. 데이터 그리드는 어떻게 추가시킬 수 있나요?


 일반적인 테이블에 데이터 그리드 기능을 추가할 수 있는 방법은 두 가지가 있습니다. 첫번째 방법은 사용자가 테이블 데이터를 조작할 수 있도록 해주는 PHP나 .NET 같은 서버사이드 스크립팅을 사용하는 방법입니다. 두번째 추천하는 방법은 자바스크립트를 사용하여 테이블에 그리드를 바인드하는 것입니다.



Q3. 웹포넌트 그리드는 어떤 방식으로 작동하나요?


 웹포넌트 그리드는 위에서 언급한 두 가지 방법 중 두번째 방법인 자바스크립트를 사용하여 테이블에 그리드를 바인드시키는 방법으로 작동합니다. 기본적인 HTML 테이블 마크업을 작성하고, 스크립트를 이용하여 그리드를 초기화시키면 정적인 HTML 테이블이 그리드로 탈바꿈하게 됩니다. 그리드에 들어가는 데이터는 ajax를 사용해 비동기 방식으로 가져오며, 얻은 데이터를 웹포넌트 그리드의 appendRow 함수의 인자로 넘겨주면 그리드에 로우를 생성합니다. 다음은 웹포넌트 그리드를 초기화하는 예제 코드입니다.


<HTML 코드>


  1.            <table id="grid-table-1">
  2.  
  3.             </table>
  4.  
  5.             <script id="grid-template-1" type="text/template">
  6.                 <table width="100%" height="350px">
  7.                     <thead>
  8.                         <tr>
  9.                             <th name="col1" align="center">col1</th>
  10.                             <th name="col2" align="center">col2</th>
  11.                             <th name="col3" align="center">col3</th>
  12.                         </tr>
  13.                     </thead>
  14.                     <tbody>
  15.                         <tr>
  16.                             <td name="col1" bind="col1"></td>
  17.                             <td name="col2" bind="col2"></td>
  18.                             <td name="col3" bind="col3"></td>
  19.                         </tr>
  20.                     </tbody>
  21.                 </table>
  22.             </script>


<script 코드>

  1. var table1 = $('#grid-table-1');
  2. var template1 = $('#grid-template-1');
  3. var grid = webponent.grid.init(table1, template1);
  4. $.ajax({
  5.     dataType : 'json',
  6.     url : 'testData.json',
  7.     success : function (resp) {
  8.          grid.appendRow(resp);
  9.     }
  10. });

사용 방식이 아주 간단합니다. 단 몇줄의 javascript 추가만으로 일반적인 테이블 요소가 그리드로 바뀌게 됩니다. bind 속성은 ajax로 호출해오는 데이터의 키와 동일하게 하면 됩니다. 그러면 키에 맞는 value 텍스트가 테이블에 바인딩 되어 td 안으로 들어가게 됩니다. 

Q4. 웹포넌트 그리드에는 어떤 기능들이 있나요?

웹포넌트 그리드의 기능은 데이터 바인딩테마 변경컬럼 조작(리사이즈, 고정, 숨기기, 이동, 소팅, 필터링, 그룹화 등), 로우 조작(검색, 순서변경, 삭제, 렌더링 콜백, 멀티로우 등), 셀 편집페이징(서버, 클라이언트, 슬라이더 형식, 스크롤), Export(pdf, excel, csv), 이벤트 추가, 플러그인 등이 있습니다. 데이터 바인딩은 위에서 기본 예제코드를 통해 설명했기 때문에 템플릿 테마 변경부터 각각의 주요 기능에 대해 살펴보도록 하겠습니다. 


1. 테마 변경
웹포넌트 그리드는 총 6개의 테마를 포함하고 있습니다. 테마별로 각각의 css 파일을 제공하고 있습니다. 따라서 테마를 변경하실 때는 다른 수정작업 없이, import 하는 css 파일만 해당 테마의 css 파일로 설정해주기만 하면 됩니다. 











2. 컬럼 조작

2-1. 리사이즈 

컬럼과 컬럼 사이 테두리에 마우스를 올려놓으면 크기를 조절할 수 있습니다.  이 기능은 셀에 정보가 매우 길어서 보이지 않는 경우에 유용하게 사용할 수  있습니다.

 
2-2.고정 

컬럼의 인덱스를 인자로 넘겨서 setFixedColumn()이라는 그리드 함수를 호출하면 스크롤 영역에서 배제되어 그 자리에 고정되게됩니다. 컬럼이 많을 경우 왔다갔다 하면서 확인하지 않고, 특정 컬럼을 고정시켜 놓으면 매우 편하겠죠? 아래 코드에서 grid는 초기화를 통해 생성된 그리드 object를 의미합니다.

  1. grid.setFixedColumn(index);

 



2-3.숨기기


생성된 그리드에서 숨기고 싶은 컬럼은 setColumnVisibility() 함수를 통해 표시 여부를 설정할 수 있습니다. 다음은 그리드의 함수를 사용해서 특정 컬럼을 보이게 하는 함수와 숨기는 함수를 작성한 예제 코드 입니다.


  1. var columnNames = grid1.getColumnNames();
  2.  
  3. function hideColumn () {
  4.   var index = 1;
  5.   grid1.setColumnVisibility(columnNames[index]false);
  6. }
  7.  
  8. function showColumn () {
  9.   var index = 1;
  10.   grid1.setColumnVisibility(columnNames[index]true);
  11. }
  12.  



2-4.이동

특정 컬럼들의 위치를 이동시키는 기능입니다. 변경하려는 인덱스를 가진 컬럼 이름을 swapColumn의 인자로 넘겨주어 사용할 수 있습니다. 아래는 예제 코드입니다.

 

  1. var columnNames = grid1.getColumnNames();
  2.  
  3. function swapColumn () {
  4.  
  5.   var index1 = parseInt($('#column-index-1').val()) - 1;
  6.   var index2 = parseInt($('#column-index-2').val()) - 1;
  7.   grid1.swapColumn(columnNames[index1], columnNames[index2]);
  8. }



 2-5.소팅 

특정 컬럼의 값들로 정렬 시키는 기능입니다. 컬럼명 옆에 있는 작은 화살표를 누르면 그 컬럼의 값들로 재정렬됩니다. 만약 정렬을 원치 않는 컬럼일 경우에는 기본 테이블 마크업에 'sortable="false"' 속성을 주면 그 컬럼에는 정렬 화살표가 생기지 않습니다.



 2-6.필터링

이건 정말 편리한 기능입니다. 검색 기능이라고 봐도 무방할 것 같습니다. 특정 컬럼에서 원하는 값으로 필터링을 하면 필터링한 조건에 해당하는 로우들만 남게 됩니다. 위의 예제는 1번째 컬럼에서 '파'라는 글자가 들어간 로우만 필터링을 한 결과입니다. 아래는 예제 코드로, filterColumn() 함수에 해당하는 컬럼명과 key값을 넘겨주면 됩니다.

  1. var columnNames = grid1.getColumnNames();
  2. var index = 0;
  3. var key = '파';
  4. grid1.filterColumn(columnNames[index], key);
  
 
3. 셀 편집


셀 편집 기능은 흔히 '인라인 에디팅'이라고도 말하며, 그리드에서 직접 값을 편집할 수 있도록 해줍니다. 해당 셀을 클릭하면 커서가 생기면서 편집할 수 있게 됩니다. 사용자가 값을 조작하도록 만들 때 아주 유용하게 쓰일 수 있겠습니다.

4. 페이징

 페이징 방식에는 클라이언트에서 처리하는 방식과 서버에서 처리하는 방식 두 가지가 있습니다. 클라이언트 페이징 방식은 그리드를 초기화할 때, 페이징에 대한 옵션 정보를 담은 object를 초기화 함수의 인자로 넘겨주어 페이징 영역을 생성합니다. 서버 페이징 방식은 그리드를 초기화한 후, 제공하는 UI 플러그인을 사용하여 페이징 영역을 생성합니다.

클라이언트 페이징은 원하는 정보를 한 번에 가져와서 특정 페이지에서 나오는 데이터만 보여주는 방식입니다. 서버 페이징은 페이지 번호를 누를 때마다 번호에 맞는 데이터를 새롭게 조회하여, 그리드에 이전 값을 제거하고 새로 받아온 데이터를 추가시키는 방식으로 처리합니다. 서버 페이징이 코드는 조금 더 복잡해지지만, 데이터 건수가 많은 경우 해당 페이지의 데이터만 조회하므로 성능상의 이점이 있습니다.

아래 캡쳐 사진에는 일반적인 번호 형식의 페이징 처리가 되어있지만, 슬라이더 형식도 있으며 새 페이지로 전환될 때 애니메이션을 줄 수도 있습니다. 웹포넌트 퍼블리셔에서 좌측 메뉴 중 grid demo를 선택하고 '페이징 슬라이더'와 '페이징 애니메이션' 메뉴를 확인하실 수 있습니다.


5. Export

 또 하나의 매우 유용한 기능은 바로 생성한 그리드를 csv, excel, pdf로 export 할 수 있다는 것입니다. 엑셀의 경우 파일명과 시트명을 정해서 추출할 수 있습니다. 아래와 같은 등략율 순위 데이터 그리드를 csv, excel, pdf로 추출하여 첨부해 두었습니다. 결과물이 궁금하신 분들은 다운로드를 받아서 확인해 보실 수 있습니다. 


등락율순위.csv

등락율순위.pdf

등락율순위.xls

지금까지 웹포넌트 그리드의 기능들을 대략적으로 살펴보았습니다. 포스팅이 너무 길어지는 관계로 이 정도만 언급하였지만, 사실은 여기서 소개하지 못한 로우 조작, 이벤트, 플러그인 등 다른 기능들도 매우 많습니다. 캡쳐만으로는 전달할 수 없었지만, 대용량 데이터를 로드할 때 속도가 매우 빠르며 스크롤이 부드럽다는 특징도 있습니다. 혹시나 더욱 많은 샘플과 예제 코드를 확인하고 싶으신 분들은 아래 관련 사이트 목록에 있는 사이트를 방문해주시길 바랍니다. ^^ 아! 구매문의는 02-784-2503으로 언제든지 해주세요. 친절하게 안내해드리겠습니다.%EB%AF%B8%EC%86%8C



웹포넌트 관련 사이트 목록

 사이트명

설명

 웹포넌트 공식 사이트

 웹포넌트 공식 사이트로 제품에 대한 상세 설명 보기, 트라이얼 다운로드가 가능합니다.

 웹포넌트 퍼블리셔

 웹포넌트 차트, 그리드에 관련한 예제 코드를 보거나 편집할 수 있습니다.

 기술지원 사이트

 제품에 대한 질문을 게시할 수 있으며, 구매하신 고객의 경우 제품문의를 할 수 있습니다. FAQ, 버전 이력, 공지사항을 확인할 수 있습니다.

 웹포넌트 샘플 사이트

  웹포넌트 차트, 그리드에 관련한 예제를 확인할 수 있습니다.

 









New Multi-Channel Dynamic CMS

PhantomJS로 GRID&CHART를 PDF 출력하기 (3편 : Header & Footer에 이미지 넣기)

안녕하세요!! CX사업부 MD 태태입니다!

지난번에 우리가 문서 규격을 갖춘 PDF를 출력하고 헤더, 푸터 까지 출력했었죠.

그런데 기억하시나요?

그 때 우리는 한가지 문제에 직면했었습니다.

기억을 더듬기 위해 지난번 코드의 일부를 살펴보지요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
page.paperSize = {
    format: 'A4',
    orientation: 'portrait',
    margin: {
        left: '1cm',
        right: '1cm'
    },
    header: {
        height: '1cm',
        contents: phantom.callback(function () {
            var div = document.createElement('div');
            var img  = document.createElement('img');
            img.src = 'http://www.webponent.com/templets/default/img/default/img_logo.gif';
            img.style.height = '0.5cm';
 
            div.appendChild(img);
 
            return div.outerHTML;
        })
    },
    footer: {
        height: '1cm',
        contents: phantom.callback(function (pageNum, numPages) {
            var div = document.createElement('div');
            div.textContent = pageNum + '/' + numPages;
            div.style.color = 'red';
            div.style.textAlign = 'center';
 
            return div.outerHTML;
        })    
    }
}
cs

기억 나시나요??

우린 분명히 header에 이미지경로를 준 <img>태그를 집어넣었어요. webPonent 로고가 나오게 할 생각으로 말이죠. footer에는 페이지 정보에 빨간색으로 스타일을 주었었네요.


그런데 결과는?????

왓????? 나니????

footer는 의도한대로 출력이 되는데 header가 아무것도 나오지가 않지요.

처음에 PDF출력을 구현하면서 이 부분때문에 많이 놀랐었습니다.


자 그러면 이제 어떻게 해결했는지 확인해 봅시다.


해결의 실마리를 얻은 것은 이 github 이슈 였습니다.

간단히 정리해 보면 web상의 resource들이 모두 load되고 loadFinished 이벤트가 발생한 후에는 header,  footer의 HTML들을 파싱하지 않는 phantomJS 버그였던 것이죠.


그래서 생각한 방법은 본문 영역에 display:none 스타일의 이미지를 추가해 캐싱한 후에 그 이미지를 header나 footer에 사용하는 것 이었습니다.


그러면 실제로 테스트를 해보도록 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var headerImg = 'http://www.webponent.com/templets/default/img/default/img_logo.gif';
 
page.onLoadFinished = function(status) {
    console.log('onLoadFinished Status: ' + status);
 
 
    // 헤더, 푸터용 이미지 캡쳐 로직
    page.evaluate(function (headerImg) {
        var image = new Image();
        image.src = headerImg;
        image.style.display = 'none';
 
        document.body.appendChild(image);
    }, headerImg);
 
    // 캐싱을 위해 setTimeout 준 후 렌더링
    setTimeout(function () {
        page.render('screenshot.pdf');    // 스크린 캡쳐파일 생성
          phantom.exit();
    }, 500);
}
cs


onLoadFinished lisntner에 body 안에 이미지 태그를 삽입하는 로직을 추가 했습니다.

그리고 안전히 이미지가 캐싱되게 하기위해 setTimeout을 주고 렌더링을 했습니다.

그러면 결과를 확인해 볼까요?


정확하게 헤더에 이미지가 출력되는 것을 확인할 수 있습니다.


이렇게 PDF header, footer에 이미지 출력하는 부분까지 구현해 보았습니다.

웹포넌트 그리드 & 차트 모두 PDF로 출력이 가능한데 지금까지 제가 소개해 드린 phantomJS의 여러가지 렌더링 방법들이 녹아져있답니다.

계속해서 하나씩 소개해 드리도록 하겠습니다 ^^



New Multi-Channel Dynamic CMS

PhantomJS로 GRID&CHART를 PDF 출력하기 (2편 : 페이지설정, Header & Footer )

안녕하세요!! CX사업부 MD 태태입니다!


지난번 글 에서 PhantomJS를 이용해서 간단히 Google(우리의 구글신) 화면을 캡쳐했었습니다!

하지만 우리가 단순히 화면만 캡쳐할 거였으면 이미지로 만들었겠죠~

실제로 PhantomJS를 통하여 동일한 로직을 통해 이미지 파일을 추출할 수도 있습니다. (추출파일 확장자만 바꿔주면 되요)


그러나 우린 문서를 원합니다!! 이미지가 아닌 PDF 문서!


문서형식의 파일에는 여러가지 페이지에 대한 설정들이 들어가게 됩니다.

페이지 여백 설정, 방향설정,  페이지 Header, Footer설정, 페이지 크기 등 다양한 설정을 할 수 있어야 하겠지요.


그렇기 때문에 이번에는!

PhantomJS로 그리드&차트 PDF 출력하기 그 두번째 내용으로 PDF 문서의 페이지설정 및 Header와 Footer를 설정해 보도록 하겠습니다.





△실제 웹포넌트 사이트 레포팅 데모를 확인해 보시면 PDF Footer가 나오는 것을 확인하실 수 있습니다.(이미지 클릭!)



일단먼저 실제 웹포넌트 제품이 캡쳐된 이미지를 보실게요. 위 이미지 링크를 타고 가시면 확인하실 수 있는데, 간단하게 페이지의 하단에 페이지 숫자를 표현하고 있습니다. 실제 데모는 저렇듯 간단하디만 페이지 header, footer에는 문서의 제목, 페이지 번호, 이미지 등 다양한 정보를 삽입하실 수 있답니다.


자 그러면 장황한 설명은 이정도 하도록하고 바로 진행해 보도록 하지요!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Web Page를 Control 하기 위한 Web Page Module 객체 생성
var page = require('webpage').create();
 
// PhantomJS에서 화면을 어떤 사이즈로 출력할 것인지에 대한 값
// 미디어 쿼리도 동작
page.viewportSize = { width: 1024, height: 768 };
 
page.onLoadFinished = function(status) {
    console.log('onLoadFinished Status: ' + status);
 
    page.render('screenshot.pdf');    // 스크린 캡쳐파일 생성
      phantom.exit();
}
 
// 페이지 오픈
page.open('http://www.google.com'function(status) {
 
    console.log('open Status: ' + status);
 
    // status 인자를 통해 성공, 실패여부 확인
    if (status !== 'success') {
        console.log('Cannot open webpage');
        phantom.exit();
    } 
});
cs

지난번에 작성했던 코드 전문입니다. 짧지요? ㅋㅋ 


이제 여기에 Header, Footer처리를 붙여보겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Web Page를 Control 하기 위한 Web Page Module 객체 생성
var page = require('webpage').create();
 
// PhantomJS에서 화면을 어떤 사이즈로 출력할 것인지에 대한 값
// 미디어 쿼리도 동작
page.viewportSize = { width: 1024, height: 768 };
 
page.paperSize = {
    format: 'A4',
    orientation: 'portrait',
    margin: {
        left: '1cm',
        right: '1cm'
    },
    header: {
        height: '1cm',
        contents: phantom.callback(function () {
            return '<div>PhantomJS Header, Footer 예제입니다.</div>';
        })
    },
    footer: {
        height: '1cm',
        contents: phantom.callback(function (pageNum, numPages) {
            return '<div>' + pageNum + '/' + numPages + '</div>';
        })    
    }
}
 
page.onLoadFinished = function(status) {
    console.log('onLoadFinished Status: ' + status);
 
    page.render('screenshot1.pdf');    // 스크린 캡쳐파일 생성
      phantom.exit();
}
 
// 페이지 오픈
page.open('http://www.google.com'function(status) {
 
    console.log('open Status: ' + status);
 
    // status 인자를 통해 성공, 실패여부 확인
    if (status !== 'success') {
        console.log('Cannot open webpage');
        phantom.exit();
    } 
});
cs


8 ~ 27 line이 추가 되었습니다.

하나하나 설명해 드릴게요.


우선 모든 페이지 설정은 PhantomJS Web Page Module의 pageSize요소를 통해서 가능합니다.

PhantomJS 공식페이지에서는 PDF를 렌더링 할 때 web page의 크기을 정의하는 요소(the size of the web page when rendered as a PDF)라고 설명하고 있네요.


자 이제 처음사용된 요소들 부터 차례대로 설명하겠습니다.


format 우리가 흔히 아는 용지설정 이라고 생각하시면 될 것 같아요. A3, A4, A5, Legal, Letter, Tabloid를 지원한다고 하네요.


orientation은 왜 우리 인쇄할때 가로인쇄 세로인쇄 결정하죠?? 바로 그것입니다. portrait이 세로, landscape가 가로입니다.


margin은 우리가 아는 그 margin이에요. 문서의 여백을 설정할 수 있지요. top, left, bottom, right 다 따로 설정가능하지요.


설정 단위로는 mm, cm, in, px가 있습니다.


또한 위와같은 요소들을 사용하지 않고

{
  width: '200px',
  height: '300px',
  margin: '0px'
}

위와같이 객체안에 width, height을 직접 지정해 줄 수도 있어요. 그러니까 문서의 크기에 관련된 요소들을 다 지정해 줄 수 있겠지요.


자 그럼, 이제 Header, Footer로 넘어가겠습니다!

얘네들은 설명할 부분이 좀 있어요.


코드를 보시죠.

사실 위의 코드는 너무 직관적이라서 설명할 부분이 별로 없어요. 보시면 바로 이해하실 수 있겠죠.

다만 header, footer의 contents 요소는 무조건 phantom.callback object로 설정이 되어야 합니다. 


코드상에서 header는 단순히 문자열을 포함한 div를 return하고 있고, footer는 페이지 번호를 return하는데요, 콜백함수에 pageNum, numPages인자가 넘어와서 페이지 번호를 쉽게 표현할 수 있습니다.


그럼 실제로 pageSize가 적용된 문서와 그렇지 않은 문서를 비교해 볼까요?





왼쪽이 pageSize 적용 안 된 문서, 오른쪽이 적용 된 문서입니다. 차이가 확실하쥬??


일단 문서 모양이 다르죠. 확실히 A4에 맞게 사이즈가 적용된 모습입니다. 또한 양 옆 margin이 설정이 되었고, 위아래 header, footer가 붙었네요.


조금 더 문서처럼 그럴듯하게 보이게 만들어 진 것 같네요.


그렇다면 header나 footer에 스타일을 적용하거나 이미지를 넣을 수는 없을까요?

HTML 태그로 적용되었기 때문에 가능할 것 같습니다. 한번 시도해보죠!




요 webPonent 로고를 Header에 뙇! 그리구 Footer는 색깔을 빨간색으로 바꾼 후 가운데 정렬을 해 보겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
page.paperSize = {
    format: 'A4',
    orientation: 'portrait',
    margin: {
        left: '1cm',
        right: '1cm'
    },
    header: {
        height: '1cm',
        contents: phantom.callback(function () {
            var div = document.createElement('div');
            var img  = document.createElement('img');
            img.src = 'http://www.webponent.com/templets/default/img/default/img_logo.gif';
            img.style.height = '0.5cm';
 
            div.appendChild(img);
 
            return div.outerHTML;
        })
    },
    footer: {
        height: '1cm',
        contents: phantom.callback(function (pageNum, numPages) {
            var div = document.createElement('div');
            div.textContent = pageNum + '/' + numPages;
            div.style.color = 'red';
            div.style.textAlign = 'center';
 
            return div.outerHTML;
        })    
    }
}
cs


코드를 수정했습니다.

이제 이 스크립트를 실행해 봅시다!

.

.

.

ㅇㅓ??? 왜 안나오지??????


스크린샷을 올리진 않겠습니다. 여러분이 실제로 작성해 보시면서 확인해 보시기 바랍니다.

PDF를 추출해 보시면 footer에는 스타일 적용이 잘 되었는데, header가 휑 하니 비어있을 거에요.

분명히 로고이미지가 있어야 하는데!!!! T^T


이미지를 header나 footer에 삽입하기 위해서는 조금 다른 방법을 사용해야합니다. 

일종의 트릭이지요.

다음 3번째 글에서는 그 방법에 대해 설명해 드리도록 할게요.


긴 글 읽느라 수고하셨고 조만간 세 번째 글로 찾아뵙겠습니다~!


아, 혹여 제가 쓴 정보중에 틀린 부분이나 이해가 안 되시는 부분이 있으면 댓글남겨주세요! 환영합니다!!



New Multi-Channel Dynamic CMS

PhantomJS로 GRID&CHART를 PDF 출력하기 (1편 : 시작하기)

웹포넌트 그리드차트는 웹 상에서 표현된 데이터를 Excel, CSV, PDF 등의 파일로 추출하는 기능을 가지고 있습니다.


데모 보러가기 클릭!!


그 중 PDF를 추출하는 기능은 PhantomJS 라는 툴을 이용하여 만들었는데요, PDF추출 기능을 구현하며 처음 사용해  된 PhantomJS!

세상 모든것들이 그렇듯 잘 사용하기만 하면 아주 유용한 녀석입니다.

만들면서 많은 시행착오를 겪게 되었는데요, 앞으로 몇 회에 걸친 글을 통해 구현하면서 얻게 된 Know How와 Tip들을 공유해보도록 하겠습니다. 

그 첫 시간으로 PhantomJS란 과연 무엇인지에 대한 간략한 설명과 함께 기본적인 Screen capture에 대해 설명하도록 하겠습니다.



1. PhantomJS 란?


PhantomJS 공식 홈페이지에 있는 설명입니다. 대강 해석해보면 

"JavaScript, DOM, CSS, JSON, Canvas, SVG와 같은 웹 표준을 Control할 수 있는 Headless Webkit Utility"

정도 될 것 같군요. 쉽게 설명하면 "브라우저 화면없이 웹을 컨트롤 할 수있는 도구" 정도로 이해하시면 큰 무리가 없으실 겁니다.



PhantomJS가 어디어디에 쓰일 수 있는지 설명하고 있습니다. 이 또한 공식 홈페이지에 있는 내용인데요, 웹사이트 테스팅, 페이지 자동화, 네트워크 모니터링 등 여러가지로 사용될 수 있지만 나머지는 다 패스하고 저희는 스크린 캡쳐에 관한 내용만 집중적으로 살펴보겠습니다.



2. 설치

본격적으로 Screen Capture에 대해 이야기하기 전에 PhantomJS 설치방법을 간략해 설명드리겠습다.



Windows나 Mac에서의 설치방법은 비교적 간단합니다. 위 페이지의 다운로드 링크를 통해 zip파일을 다운로드 후 압축만 풀어주시면 실행파일이 생성되서 바로 사용하실 수 있는데요, Linux같은 경우는 아직 Binary package가 없다고 하네요(2015. 06. 24기준). 어쩔수 없이 소드코드를 다운받아서 빌드하셔야 합니다. 빌드방법은 홈페이지에 잘 나와있으니 요기로 가셔서 확인하시면 될 것 같네요.



3. Screen Capture

약간은 지루한 설치과정을 다 마치셨으면, 이제야 드디어 실제로 웹 화면을 캡쳐해보도록 하겠습니다!!!

복잡한 설정과 이미지, 스타일적용은 다음편 포스팅에서 자세히 다루기 위해 조금 미뤄두고, 이번편에서는 간단히 캡쳐결과만 나오는 js파일을 작성해 보도록 할게요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Web Page를 Control 하기 위한 Web Page Module 객체 생성
var page = require('webpage').create();
 
// PhantomJS에서 화면을 어떤 사이즈로 출력할 것인지에 대한 값
// 미디어 쿼리도 동작
page.viewportSize = { width: 1024, height: 768 };
 
// 페이지 오픈
page.open('http://www.naver.com'function(status) {
 
    // status 인자를 통해 성공, 실패여부 확인
    if (status !== 'success') {
        console.log('Cannot open site');
        phantom.exit();
 
    } else {
        // 페이지가 렌더링 되는 시간(2초) 기다린 후
        window.setTimeout(function () {
            page.render('screenshot.pdf');    // 스크린 캡쳐파일 생성
              phantom.exit();
        }, 2000);
    }
});
cs

아주아주 간단한 캡쳐 코드입니다. 실제 웹포넌트 그리드&차트에 사용된 코드의 아주일부분을 차용해서 작성한 것인데요, PhantomJS는 JavaScript코드를 통해 동작하기 때문에 위와같이 우리에게 익숙한 JavaScript코드를 통해 작성하시면 됩니다.

실제로 위의 코드를 capture.js로 저장하신 후에 PhantomJS가 설치된 경로에서

> phantomjs capture.js

명령어를 입력하시면 screenshot.pdf파일이 생성되는것을 확인하실 수 있습니다.

이 시점에 첫번째 고민이 시작됩니다.

18 line에 보시면 페이지렌더링 때문에 setTimeout() 함수를 사용해서 2초를 기다리고 있죠. 그런데 이런 방식으로 사용하다보면 리소스가 많아질 경우 페이지가 완전히 렌더링 되지 않았는데도 스크린샷이 찍히거나, 리소스가 완전히 로딩이 되었는데 timeout을 기다려서 시간이 낭비가 될 경우가 생기더라구요.

이제 이 부분을 해결해 보겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Web Page를 Control 하기 위한 Web Page Module 객체 생성
var page = require('webpage').create();
 
// PhantomJS에서 화면을 어떤 사이즈로 출력할 것인지에 대한 값
// 미디어 쿼리도 동작
page.viewportSize = { width: 1024, height: 768 };
 
page.onLoadFinished = function(status) {
    console.log('onLoadFinished Status: ' + status);
 
    page.render('screenshot.pdf');    // 스크린 캡쳐파일 생성
      phantom.exit();
}
 
// 페이지 오픈
page.open('http://www.google.com'function(status) {
    // status 인자를 통해 성공, 실패여부 확인
    if (status !== 'success') {
        console.log('Cannot open site');
        phantom.exit();
    } 
});
cs

setTimeout() 함수를 없애고 대신에 page.onLoadFinished 이벤트 리스터를 추가했습니다(8 line). 이제 페이지의 요소들의 로딩이 끝나는 시점에 Event listener를 통해서 페이지를 캡쳐 할 것입니다.



이렇게 해서 기본적인 PDF를 출력하는 Script가 완성되었습니다. 하지만 이것만으로는 많이 부족하죠.

실제로 PDF출력 기능을 구현하면서 CSS적용, 폰트, 페이지 설정, PDF Header, Footer 삽입 등 여러가지 문제에 직면했었습니다.


이어지는 글에서 그 직면했던 문제들을 어떻게 해결했는지 계속 포스팅 하겠습니다. 그러면 다음 포스팅을 기다리며 이만~~



capture.js  -> 첨부파일 확인 해 보셔요~
















New Multi-Channel Dynamic CMS