자바스크립트로 특정 영역 프린트 (인쇄) 기능 구현하기 feat. 리액트
업무 중에 특정 영역에 대한 프린트 기능이 필요하게 되었다.
한번도 해본적은 없었지만 일이니 어떻게든 구현해야 했는데
다행히 구글 선생님께서 어떻게 해야할 지 알려주었다.

지금부터 프린트 기능 함수를 자바스크립트로 구현하여
이를 리액트(Hook) 에 녹이는 방법을 정리하고자 한다.
우선 내가 구현한 프린트 기능 함수는 다음과 같다.
// 인쇄 기능 Handler
const onPrintHandler = () => {
let printContents = ReactDOM.findDOMNode(a4Notice.current).innerHTML;
let windowObject = window.open('', "PrintWindow", "width=1000, height=800, top=100, left=300, toolbars=no, scrollbars=no, status=no, resizale=no");
windowObject.document.writeln(printContents);
windowObject.document.close();
windowObject.focus();
windowObject.print();
windowObject.close();
}
- printContents는 프린트할 영역이라고 생각하면 될 듯 하다.
- windowObject는 프린트될 영역이 주입될 window라고 보면 된다.
프린트할 영역을 기존의 window에 덮어 씌우고 프린트를 한 다음에 다시 원래대로 되돌리는 방법도 있는데,
해보니 기능이 온전하게 되돌아오지 않는 문제가 발생하여
새로운 window를 열고 거기에 프린트할 영역을 넣는 방식을 선택했다.
- windowObject.document.writeln(printContents); 은 새로 열린 window에 프린트될 영역을 주입한다.
- windowObject.document.close(); 로 window 객체의 document를 close.
- windowObject.focus() 로 새로 열린 window 창에 포커스를 준다.
- windowObject.print() 로 인해 새로 열린 window 창에서 프린트 기능을 동작할 수 있다.
- windowObject.close() 로 열린 window를 닫아주며 기능이 마무리된다.
생각보다 어렵지 않아 다행이었다.
window.open에 들어가는 각종 parameter들은...
window.open(url, windowName, [windowFeatures]);
라고 생각하면 되고 자세한 설명은
https://developer.mozilla.org/ko/docs/Web/API/Window/open 를 참고하면 될 듯 하다.
자, 그런데 저걸 복사해서 가져다 쓰면 당연히 안된다는 사실을 알 것이다.
프린트할 영역을 아직 참조하지 않았기 때문이다.
리액트훅의 useRef를 통해 특정 영역을 참조하여 프린트 기능을 적용하는 방법을 적어보겠다.
우선은...
import React, { useRef } from "react";
import ReactDOM from "react-dom";
useRef와 ReactDOM을 import 시켜주고
const a4Notice = useRef();
변수 선언을 해준 다음에,
<MC.Paper
ref={a4Notice}
style={{
width: "21cm",
minHeight: "29.7cm",
padding: "2cm",
margin: "1cm auto",
borderRadius: "5px",
background: "white",
boxShadow: "0 0 5px rgba(0, 0, 0, 0.1)"
}}
>
프린트할 영역에 ref attribute로 적용시켜주면 된다.
참고로 MC.Paper는 material-ui 컴포넌트인데 일반적인 다른 태그로 바꿔도 무방할 듯 하다.
밑에 스타일은 나름 A4 용지 규격으로 맞추게끔 되어있다.
이로써 프린트 기능 구현에 대한 정리를 마치고자 한다.
앞으로 업무할때나 개인적으로 공부할때 구현한 기능을 블로그에 정리해두고자 하는데,
꾸준한 나의 모습을 기대하고 싶다..

참고 블로그: https://hyunalee.tistory.com/56
이미지 출처: https://www.flaticon.com/kr/premium-icon/print_4722903?erm=%EC%9D%B8%EC%87%84&page=1&position=25&page=1&position=25&related_id=4722903&origin=tag