이미지 출처: .bubble | QZ Tray

📘 QZ Tray 설치 가이드

1. 시작하며

1.1 문제 정의

  • 필자가 맞닥드린 문제는 아래와 같다.
  1. 사용자가 몸을 사용하는 실무를 하는 동시에 웹 사이트(Spring Boot 로 클라우드 서버를 통해 배포)를 통해 반복적인 데이터를 기록하고 처리를 하며, 이에 따라 실제 인쇄물이 바로바로 나와야 한다.
  2. 이 때, 사용자가 전반적인 업무를 보다 효율적이고 반복적인 작업을 최소화 할 수 있게 해주기 위해서는 인쇄를 하는 과정을 대폭 간소화 시켜주면 된다.
이미지 1.1: 실무자의 전산 처리 업무 구조

인쇄하는 과정을 간소화 시켜주지 않는다면...

  • 실무자는 몸을 사용하는 업무를 하고, 전산을 기록하고 처리된 파일을 열어 직접 컴퓨터에 인쇄 명령을 내리는 작업을 업무를 수 없이 반복해야 한다. 이 과정을 좀 더 쉽고 간단하게 할 수 있게 실무자를 도와주자.

1.1.1. 사용자의 실무 중 고충

  • 일반적으로, 문서나 이미지를 특히나 웹에서 인쇄 하고자 할 때는 항상 아래와 같은 유형의 사용자의 상호작용이 필수적으로 필요하다.

    1. 인쇄 버튼 -> 인쇄 설정 페이지 -> 인쇄
    2. Ctrl + P -> 인쇄 설정 페이지 -> 인쇄
    3. 마우스 우클릭 -> 인쇄 클릭 -> 인쇄 설정 페이지 -> 인쇄
  • 하지만, 1)인쇄 설정 페이지에 들어가서 2)설정을 하고 3)인쇄 버튼을 누르는 수작업은 실제로 특정 작업을 반복하는 실무자에 입장에서는 매우 비효율적일 수 있다.

2. 해결 방안과 접근 방식

  • 전산 처리 중, 처리된 문서에 대한 즉각적인 인쇄 작업을 간소화 시켜주는 작업을 QZ Tray 라는 웹 브라우저 인쇄 플러그인 을 통해 진행해 보도록 하겠다.

QZ Tray 란?

  • QZ Tray 는 브라우저 간 혹은 플랫폼 간의 특별한 인쇄 기능을 제공하는 플러그 인 이다.
  • 이 플러그인을 통해 웹 사이트 내에서 사용자가 원하는 파일을 최소한의 상호작용으로 사용자의 로컬 인쇄기를 통해 출력할 수 있게 해주는 기능을 제공한다.
  • 대부분의 인쇄 방식을 지원하지만, 반복적이고, 조금은 특수한 방식이 필요한 열전사 인쇄기 (Thermal Printer) 에 다양한 기능을 지원한다.

* 다음은 QZ Tray 를 이용해 사용자의 전산 처리 과정을 최소화 하는 구도다.

이미지 2.1: QZ Tray 도입 후 사용자 전산 업무 처리 구도
  • 이미지에 적힌 숫자에 대한 설명은 다음과 같다.
    1. 사용자가 개인 컴퓨터에 설치된 인쇄기 정보를 가져온다.
    2. 가져온 인쇄기 정보를 QZ Tray 에 전달하고,
    3. QZ Tray 는 해당 정보들을 전산 처리 서버에 전송한다.
    4. 전송받은 서버는 알맞은 전산 처리 후, 사용자가 인쇄해야 하는 정보를 QZ Tray 에 넘겨준다.
    5. QZ Tray 는 사용자를 지나,
    6. 사용자의 컴퓨터에 설치된 인쇄기에 정보(EPL, ZPL, Base64 등 의 인코딩 방식 혹은 인쇄 언어)를 전달하여 출력한다.

3. 대체 해결 방안

  • QZ Tray 를 원활하게 사용하기 까지의 과정은 그리 짧고 간단하지만은 않기에 위 방법을 사용하지 않아도 요구사항을 충족시켜줄 수 있다면 다음 소개된 대체 해결 방안들 중 적합한 것을 찾아 처리 할 수 있길 바란다.
  • 다만, 필자와 유사한 상황에 놓인 개발자라면, 곧 이어 소개될 과정들을 통해 만족할 수 있는 결과를 얻어가길 바란다.

3.1. Chrome 브라우저와 JS 의 Print() 함수를 활용

  • 본 대체 해결 방안은, 앞서 이야기한 전형적인 사용자 상호작용 인쇄 방식을 그대로 유지하면서 자동화 하는 방법이다.

    이해가 필요한 사항

    • 기본 JS 에서는 print() 라는 함수를 지원하고, 이 함수를 실행할 경우 대부분의 메이저 웹 프라우저에서는 사용자가 인쇄를 하기 앞서 추가적인 확인(상호작용)을 할 수 있는 다이어로그를 자동('마우스 우 클릭 + "인쇄" ' 혹은 ctrl + p 가 필요 없는)으로 띄워준다.
    • Chrome 에서는 인쇄하기를 눌렀을 때 나오는 사용자 다이어로그 창이 생성되었을 때, 자동으로 인쇄하기를 수행(인쇄 버튼을 눌러주는 것) 해 준다.
      (다른 브라우저는 본 기능을 지원하는지 확인이 필요.)
  • 이렇게 위 두가지 방법을 합치게 되면, 사용자는 인쇄하는 작업을 위해 따로 손을 댈 필요가 없어진다.
  • 다만, 이 방법을 사용하게 되었을 때의 단점은 다음과 같이 파악될 수 있다.
    1. 한개 이상의 문서를 두개 이상의 파일을 통해 인쇄를 진행하게 된다면, 순차적인 작업이 될 수 있게 설정하는 것이 결코 효율적으로 되기 어렵다.

      이유는...

      • 첫 번째 파일의 인쇄가 끝이 나고 두번째 파일의 인쇄를 하고자 할 때, 첫 번째 파일의 인쇄가 언제 시작하고 언제 끝이 나는지에 대한 소요시간(인터넷 속도와 사용자 컴퓨터의 상태에 따라 상이)에 따른 처리 논리를 코드에 작성할 수 없다.
      • 그로인해 특정한 고정 대기 시간 (ex 5초)을 잡고 순차적인 처리를 하면 사람의 손이 닿지 않고 처리가 되게 할 수 있지만, 속도는 사람이 처리하는 것 보다 느려지게 된다.

3.1.1. Chrome 브라우저 자동 인쇄 처리 설정 및 사용 방법

3.1.2. JS 의 print() 함수 사용 예제

  • Backend(Controller)-Spring Boot 에서 연산과 전산 처리를 하고, 인쇄하고자 하는 데이터를 Frontend(View)-JS 에 'Base64' 로 변환된 String 데이터 타입을 전달한다.
  • 전달받은 데이터를 'response' 의 변수에 담아 처리하도록 하겠다.
  • Spring Boot Java Controller Code:
@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;
    }
  • JS Code:
$.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초 후 인쇄할 문서를 끄는 명령어.
        }
    })

3.2. Restful API 와 Java 의 로컬 인쇄 라이브러리 활용

  • 자바의 내장 라이브러리 javax.print(문서 참고) 라는 인쇄 기능이 있다. 이 기능을 활용하면 본인 컴퓨터의 프린터 정보를 읽고 원하는 정보를 출력할 수 있다.
  • 다만, 인쇄하고자 하는 값이 본인 컴퓨터에 있는 것이 아닌, 원격 서버에서 정보를 처리하고 받아올 수 있는 경우에는 본인 컴퓨터만으로 원하는 정보의 문서를 인쇄할 수 없다.
  • 이를 해결하기 위해서는 원격 서버와 안전하게 데이터 통신을 할 수 있는 Rest API 환경을 서버에 구축하고, 해당 API 를 호출해서 통신할 수 있는 사용자 컴퓨터에서의 어플리케이션이 필요하다.
    • 본문에서 사용자 어플리케이션은, 사용자 컴퓨터에서 실행되는 runnable exe 프로그램 혹은 local web application 을 지칭한다.
  • 이를 간단하게 시각화 한 이미지는 다음과 같다.

    이미지 3.2_1: REST API 와 사용자 어플리케이션 사용 구도

4. 준비 사항

Qz Tray 2.0.10 을 선택한 이유? (버전 정보 참고)

포스트를 작성하는 2021-10-26 기준,

  • 버전 2.2.0 은 아직 안정성 문제가 확보되지 않음.
  • 2.1.x 는 차후에 'Self Sign Certificate' 을 진행하는 과정에서 인증 요소가 약간 변경 되었음.

    21.10.23 기준) 2.1.x 버전도 이것이 정상 작동하는 것을 확인.

  • 2.0.10 부터 Open JDK 11 버전을 지원하기 시작
  • 자세한 버전별 정리는 여기를 참고 바란다.

권장 버전(Open JDK 11 사용자 기준):

QZ Tray Version >= 2.0.10 & < 2.1.0


5. 설치 과정

* 설치 과정은 두가지로 나뉜다.

1. 설치하고 인증 여부 상관 없이 테스트 용 설치

  • 이 경우에는 여기 에서 일반적인 '다운로드' 로 설치 프로그램을 다운받아 설치하고, 설치 폴더 ../demo 폴더에서 테스트를 진행한다.

2. 설치하고 인증 후 원활한 사용 용 설치

  • QZ Tray 를 프로젝트에 추가해서 좀 더 기능적인 기능을 구현하고 싶은 경우 이 방법을 권장한다.
  • 여기를 참고하기 바란다.

6. 오류 대처

6.1. 설치 후 sample.html 로 테스트를 해 보았는데, 'untrustred website' 오류가 뜨면서 접근 허용 다이어로그가 계속 떠요.

  • 이 문제는 여기 에서 다뤄 보겠습니다.

7. 마치며

오늘은 새로운 Qz Tray 라는 툴에 대해 알아 보았습니다.

다음 시간에는 실무에서도 사용할 수 있게, 제한되어 있는 인증 이슈 관련해서 다뤄보도록 하겠습니다.

궁금하신 점이나, 오류 사항은 댓글에 남겨 주시면 성심 성의 껏 답변 드리겠습니다.

// 작성자 본인으로서, 무단으로 글을 퍼가거나 복제하는 것을 금합니다.

profile
Seeking to learn new things at all times.

0개의 댓글