# 인쇄 모달 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`

```typescript
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;
```

**동작 방식**:
1. 새 창 열기
2. 현재 페이지의 스타일시트 복사
3. `.print-area` 요소 내용 복제
4. `.print-hidden` 요소 제거
5. A4 용지에 맞는 인쇄 스타일 적용
6. 자동 인쇄 실행 후 창 닫기

### 2. globals.css 인쇄 스타일 (간소화)

**파일 위치**: `/src/app/globals.css`

```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` | 계약서 인쇄 |

## 사용 방법

### 기본 사용법

```tsx
import { printArea } from '@/lib/print-utils';

// 인쇄 핸들러
const handlePrint = () => {
  printArea({ title: '문서 인쇄' });
};
```

### 모달 구조 규칙

인쇄 가능한 모달은 다음 구조를 따라야 합니다:

```tsx
<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 새 방식

### 이전 방식 (문제점)

```tsx
const handlePrint = () => {
  window.print(); // 전체 페이지 인쇄 시도
};
```

**문제점**:
- Radix UI 포털 구조로 CSS `@media print` 제어 어려움
- `visibility: hidden` 사용 시 빈 공간으로 인해 3-4페이지로 출력
- `display: none` 사용 시 빈 페이지 출력
- 모달 헤더/버튼이 함께 인쇄됨

### 새 방식 (해결)

```tsx
const handlePrint = () => {
  printArea({ title: '문서 인쇄' });
};
```

**장점**:
- 새 창에서 `.print-area` 내용만 추출하여 인쇄
- Radix UI 포털 구조 영향 없음
- 항상 1페이지로 깔끔하게 인쇄
- 문서 내용만 인쇄 (헤더/버튼 제외)

## 새 인쇄 모달 추가 시

1. `printArea` import 추가
2. `handlePrint` 함수에서 `printArea()` 호출
3. 모달 구조에 `.print-hidden` / `.print-area` 클래스 적용

```tsx
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>
  );
}
```

## 주의사항

1. **`.print-area` 클래스 필수**: 인쇄 영역에 반드시 `.print-area` 클래스 적용
2. **중첩 `.print-area` 금지**: 하나의 모달에 `.print-area`는 하나만 존재해야 함
3. **스타일 복제**: 인쇄 시 현재 페이지의 스타일시트가 자동으로 복사됨
4. **팝업 차단 주의**: 브라우저 팝업 차단 시 인쇄 창이 열리지 않을 수 있음
