- 입찰관리: 목록/상세/수정 페이지 및 목업 데이터 - 계약관리: 목록/상세/수정 페이지 구현 - 주문관리: 수주/발주 목록 및 상세 페이지 구현 - 견적 상세 폼: 섹션별 분리 및 hooks/utils 리팩토링 - 품목관리, 카테고리관리, 단가관리 기능 추가 - 현장설명회/협력업체 폼 개선 - 프린트 유틸리티 공통화 (print-utils.ts) - 문서 모달 공통 컴포넌트 정리 - IntegratedListTemplateV2, StatCards 개선 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5.5 KiB
5.5 KiB
인쇄 모달 printArea 유틸리티 적용 가이드
작성일: 2026-01-02 적용 범위: 모든 인쇄 가능한 모달/다이얼로그
개요
기존 window.print() 방식은 Radix UI Dialog 포털 구조로 인해 CSS @media print 제어가 어렵고, 인쇄 시 모달 헤더/버튼이 함께 출력되거나 여러 페이지로 나뉘는 문제가 있었습니다.
이를 해결하기 위해 JavaScript 기반 printArea() 유틸리티를 도입하여 .print-area 영역만 새 창에서 인쇄하도록 통일했습니다.
공통 컴포넌트 변경
1. print-utils.ts (신규)
파일 위치: /src/lib/print-utils.ts
interface PrintOptions {
title?: string; // 브라우저 인쇄 다이얼로그에 표시될 제목
styles?: string; // 추가 CSS 스타일
closeAfterPrint?: boolean; // 인쇄 후 창 닫기 (기본: true)
}
// 특정 요소 인쇄
export function printElement(
elementOrSelector: HTMLElement | string,
options?: PrintOptions
): void;
// .print-area 클래스 요소 인쇄 (주로 사용)
export function printArea(options?: PrintOptions): void;
동작 방식:
- 새 창 열기
- 현재 페이지의 스타일시트 복사
.print-area요소 내용 복제.print-hidden요소 제거- A4 용지에 맞는 인쇄 스타일 적용
- 자동 인쇄 실행 후 창 닫기
2. globals.css 인쇄 스타일 (간소화)
파일 위치: /src/app/globals.css
@media print {
@page {
size: A4 portrait;
margin: 10mm;
}
* {
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
html, body {
background: white !important;
}
.print-hidden {
display: none !important;
}
}
적용된 모달 목록
| 컴포넌트 | 파일 경로 | 인쇄 제목 |
|---|---|---|
| DocumentDetailModal | src/components/approval/DocumentDetail/index.tsx |
문서 타입별 (품의서, 기안서 등) |
| ProcessWorkLogPreviewModal | src/components/process-management/ProcessWorkLogPreviewModal.tsx |
작업일지 템플릿명 |
| ReceivingReceiptDialog | src/components/material/ReceivingManagement/ReceivingReceiptDialog.tsx |
입고증 인쇄 |
| WorkLogModal | src/components/production/WorkerScreen/WorkLogModal.tsx |
작업일지 인쇄 |
| OrderDocumentModal | src/components/orders/documents/OrderDocumentModal.tsx |
계약서/거래명세서/발주서 |
| ShipmentDetail | src/components/outbound/ShipmentManagement/ShipmentDetail.tsx |
출고증/거래명세서/납품확인서 |
| EstimateDocumentModal | src/components/business/juil/estimates/modals/EstimateDocumentModal.tsx |
견적서 인쇄 |
| ContractDocumentModal | src/components/business/juil/contract/modals/ContractDocumentModal.tsx |
계약서 인쇄 |
사용 방법
기본 사용법
import { printArea } from '@/lib/print-utils';
// 인쇄 핸들러
const handlePrint = () => {
printArea({ title: '문서 인쇄' });
};
모달 구조 규칙
인쇄 가능한 모달은 다음 구조를 따라야 합니다:
<Dialog>
<DialogContent>
{/* 헤더 영역 - 인쇄에서 제외 */}
<div className="print-hidden">
<h2>문서 제목</h2>
<Button onClick={handlePrint}>인쇄</Button>
<Button onClick={onClose}>닫기</Button>
</div>
{/* 버튼 영역 - 인쇄에서 제외 */}
<div className="print-hidden">
<Button>수정</Button>
<Button>인쇄</Button>
</div>
{/* 문서 영역 - 이 영역만 인쇄됨 */}
<div className="print-area">
{/* 실제 문서 내용 */}
</div>
</DialogContent>
</Dialog>
CSS 클래스 규칙
| 클래스 | 용도 |
|---|---|
.print-area |
인쇄될 영역 (필수) |
.print-hidden |
인쇄에서 제외할 영역 (헤더, 버튼 등) |
이전 방식 vs 새 방식
이전 방식 (문제점)
const handlePrint = () => {
window.print(); // 전체 페이지 인쇄 시도
};
문제점:
- Radix UI 포털 구조로 CSS
@media print제어 어려움 visibility: hidden사용 시 빈 공간으로 인해 3-4페이지로 출력display: none사용 시 빈 페이지 출력- 모달 헤더/버튼이 함께 인쇄됨
새 방식 (해결)
const handlePrint = () => {
printArea({ title: '문서 인쇄' });
};
장점:
- 새 창에서
.print-area내용만 추출하여 인쇄 - Radix UI 포털 구조 영향 없음
- 항상 1페이지로 깔끔하게 인쇄
- 문서 내용만 인쇄 (헤더/버튼 제외)
새 인쇄 모달 추가 시
printAreaimport 추가handlePrint함수에서printArea()호출- 모달 구조에
.print-hidden/.print-area클래스 적용
import { printArea } from '@/lib/print-utils';
export function NewDocumentModal() {
const handlePrint = () => {
printArea({ title: '새 문서 인쇄' });
};
return (
<Dialog>
<DialogContent>
<div className="print-hidden">
{/* 헤더/버튼 */}
</div>
<div className="print-area">
{/* 인쇄될 문서 내용 */}
</div>
</DialogContent>
</Dialog>
);
}
주의사항
.print-area클래스 필수: 인쇄 영역에 반드시.print-area클래스 적용- 중첩
.print-area금지: 하나의 모달에.print-area는 하나만 존재해야 함 - 스타일 복제: 인쇄 시 현재 페이지의 스타일시트가 자동으로 복사됨
- 팝업 차단 주의: 브라우저 팝업 차단 시 인쇄 창이 열리지 않을 수 있음