이미지 출처: .bubble | QZ Tray
- 사용자가 몸을 사용하는 실무를 하는 동시에 웹 사이트(Spring Boot 로 클라우드 서버를 통해 배포)를 통해 반복적인 데이터를 기록하고 처리를 하며, 이에 따라 실제 인쇄물이 바로바로 나와야 한다.
- 이 때, 사용자가 전반적인 업무를 보다 효율적이고 반복적인 작업을 최소화 할 수 있게 해주기 위해서는 인쇄를 하는 과정을 대폭 간소화 시켜주면 된다.
이미지 1.1: 실무자의 전산 처리 업무 구조
인쇄하는 과정을 간소화 시켜주지 않는다면...
- 실무자는 몸을 사용하는 업무를 하고, 전산을 기록하고 처리된 파일을 열어 직접 컴퓨터에 인쇄 명령을 내리는 작업을 업무를 수 없이 반복해야 한다. 이 과정을 좀 더 쉽고 간단하게 할 수 있게 실무자를 도와주자.
일반적으로, 문서나 이미지를 특히나 웹에서 인쇄 하고자 할 때는 항상 아래와 같은 유형의 사용자의 상호작용이 필수적으로 필요하다.
- 인쇄 버튼 -> 인쇄 설정 페이지 -> 인쇄
- Ctrl + P -> 인쇄 설정 페이지 -> 인쇄
- 마우스 우클릭 -> 인쇄 클릭 -> 인쇄 설정 페이지 -> 인쇄
하지만, 1)인쇄 설정 페이지에 들어가서 2)설정을 하고 3)인쇄 버튼을 누르는 수작업은 실제로 특정 작업을 반복하는 실무자에 입장에서는 매우 비효율적일 수 있다.
QZ Tray 란?
- QZ Tray 는 브라우저 간 혹은 플랫폼 간의 특별한 인쇄 기능을 제공하는 플러그 인 이다.
- 이 플러그인을 통해 웹 사이트 내에서 사용자가 원하는 파일을 최소한의 상호작용으로 사용자의 로컬 인쇄기를 통해 출력할 수 있게 해주는 기능을 제공한다.
- 대부분의 인쇄 방식을 지원하지만, 반복적이고, 조금은 특수한 방식이 필요한 열전사 인쇄기 (Thermal Printer) 에 다양한 기능을 지원한다.
이미지 2.1: QZ Tray 도입 후 사용자 전산 업무 처리 구도
- 이미지에 적힌 숫자에 대한 설명은 다음과 같다.
- 사용자가 개인 컴퓨터에 설치된 인쇄기 정보를 가져온다.
- 가져온 인쇄기 정보를 QZ Tray 에 전달하고,
- QZ Tray 는 해당 정보들을 전산 처리 서버에 전송한다.
- 전송받은 서버는 알맞은 전산 처리 후, 사용자가 인쇄해야 하는 정보를 QZ Tray 에 넘겨준다.
- QZ Tray 는 사용자를 지나,
- 사용자의 컴퓨터에 설치된 인쇄기에 정보(EPL, ZPL, Base64 등 의 인코딩 방식 혹은 인쇄 언어)를 전달하여 출력한다.
이해가 필요한 사항
- 기본 JS 에서는 print() 라는 함수를 지원하고, 이 함수를 실행할 경우 대부분의 메이저 웹 프라우저에서는 사용자가 인쇄를 하기 앞서 추가적인 확인(상호작용)을 할 수 있는 다이어로그를 자동('마우스 우 클릭 + "인쇄" ' 혹은 ctrl + p 가 필요 없는)으로 띄워준다.
- Chrome 에서는 인쇄하기를 눌렀을 때 나오는 사용자 다이어로그 창이 생성되었을 때, 자동으로 인쇄하기를 수행(인쇄 버튼을 눌러주는 것) 해 준다.
(다른 브라우저는 본 기능을 지원하는지 확인이 필요.)
- 한개 이상의 문서를 두개 이상의 파일을 통해 인쇄를 진행하게 된다면, 순차적인 작업이 될 수 있게 설정하는 것이 결코 효율적으로 되기 어렵다.
이유는...
- 첫 번째 파일의 인쇄가 끝이 나고 두번째 파일의 인쇄를 하고자 할 때, 첫 번째 파일의 인쇄가 언제 시작하고 언제 끝이 나는지에 대한 소요시간(인터넷 속도와 사용자 컴퓨터의 상태에 따라 상이)에 따른 처리 논리를 코드에 작성할 수 없다.
- 그로인해 특정한 고정 대기 시간 (ex 5초)을 잡고 순차적인 처리를 하면 사람의 손이 닿지 않고 처리가 되게 할 수 있지만, 속도는 사람이 처리하는 것 보다 느려지게 된다.
@ResponseBody
@PostMapping(value = "/printLabel")
public String printLabel (HttpSession session,
@RequestParam(value = "label_url", required = false) String labelURL)
throws Exception {
packingService.setPdf_base64_str(labelURL);
HttpHeaders headers = new HttpHeaders();
String fileName = "label.pdf";
headers.setContentType(MediaType.parseMediaType("application/pdf"));
headers.add("content-disposition", "inline;filename=" + fileName);
headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
String encodedString = packingService.getPdf_base64_str();
return encodedString;
}
$.ajax({
type: 'POST',
url: '/printLabel?label_url=' + url,
responseType: 'blob',
success: function (response) {
var byteCharacters = atob(response);
console.log(byteCharacters.length)
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var file = new Blob([byteArray], {type: 'application/pdf;base64'});
var fileURL = URL.createObjectURL(file);
var wnd = window.open(fileURL);
wnd.print();
setTimeout(function() {
wnd.close();
}, 5000);
// setTimeout... 5000 은 5초 후 인쇄할 문서를 끄는 명령어.
}
})
- 본문에서 사용자 어플리케이션은, 사용자 컴퓨터에서 실행되는 runnable exe 프로그램 혹은 local web application 을 지칭한다.
이미지 3.2_1: REST API 와 사용자 어플리케이션 사용 구도
- Open JDK (Zulu) 11.0.12
- Spring Boot 2.1.4
- maven 3.8.2
- freemarker
포스트를 작성하는 2021-10-26 기준,
QZ Tray Version >= 2.0.10 & < 2.1.0
- 이 경우에는 여기 에서 일반적인 '다운로드' 로 설치 프로그램을 다운받아 설치하고, 설치 폴더 ../demo 폴더에서 테스트를 진행한다.
2. 설치하고 인증 후 원활한 사용 용 설치
- QZ Tray 를 프로젝트에 추가해서 좀 더 기능적인 기능을 구현하고 싶은 경우 이 방법을 권장한다.
- 여기를 참고하기 바란다.
- 이 문제는 여기 에서 다뤄 보겠습니다.
오늘은 새로운 Qz Tray 라는 툴에 대해 알아 보았습니다.
다음 시간에는 실무에서도 사용할 수 있게, 제한되어 있는 인증 이슈 관련해서 다뤄보도록 하겠습니다.
궁금하신 점이나, 오류 사항은 댓글에 남겨 주시면 성심 성의 껏 답변 드리겠습니다.
// 작성자 본인으로서, 무단으로 글을 퍼가거나 복제하는 것을 금합니다.