# 문서 시스템 통합 계획

> 작성일: 2025-01-21
> 상태: 계획 수립

## 1. 현황 분석

### 1.1 발견된 문서 컴포넌트 (17개)

| 카테고리 | 문서 수 | 파일 위치 |
|---------|--------|----------|
| 결재함 (Approval) | 3개 | `src/components/approval/DocumentDetail/` |
| 견적/발주 (Quotes) | 2개 | `src/components/quotes/` |
| 수주/거래 (Orders) | 3개 | `src/components/orders/documents/` |
| 건축사업 (Construction) | 3개 | `src/components/business/construction/*/modals/` |
| 품질관리 (QMS) | 6개 | `src/app/.../quality/qms/components/documents/` |

### 1.2 문서 상세 목록

#### 결재함 (approval/)
| 문서 | 파일 | 라인 |
|------|------|------|
| 품의서 | ProposalDocument.tsx | 114 |
| 지출결의서 | ExpenseReportDocument.tsx | 135 |
| 지출예상내역서 | ExpenseEstimateDocument.tsx | 127 |

#### 견적/발주 (quotes/)
| 문서 | 파일 | 라인 |
|------|------|------|
| 견적서 | QuoteDocument.tsx | 464 |
| 발주서 | PurchaseOrderDocument.tsx | 425 |

#### 수주/거래 (orders/documents/)
| 문서 | 파일 | 라인 |
|------|------|------|
| 계약서 | ContractDocument.tsx | 236 |
| 거래명세서 | TransactionDocument.tsx | 202 |
| 발주서 | PurchaseOrderDocument.tsx | 202 |

#### 건축사업 (construction/*/modals/)
| 문서 | 파일 | 라인 |
|------|------|------|
| 계약서 | ContractDocumentModal.tsx | 104 |
| 인수인계보고서 | HandoverReportDocumentModal.tsx | 308 |
| 발주서 | OrderDocumentModal.tsx | 354 |

#### 품질관리 (quality/qms/components/documents/)
| 문서 | 파일 | 라인 |
|------|------|------|
| 제품검사성적서 | ProductInspectionDocument.tsx | 289 |
| 스크린중간검사 | ScreenInspectionDocument.tsx | 309 |
| 슬랫중간검사 | SlatInspectionDocument.tsx | 286 |
| 절곡중간검사 | BendingInspectionDocument.tsx | 348 |
| 금속프레임검사 | JointbarInspectionDocument.tsx | 298 |
| 수입검사성적서 | ImportInspectionDocument.tsx | 418 |

### 1.3 기능 현황

| 컴포넌트 | 줌 | 드래그 | 인쇄 | 다운로드 | 수정 | 삭제 | 상신 |
|---------|:--:|:-----:|:----:|:-------:|:----:|:----:|:----:|
| InspectionModal (QMS) | ✅ | ✅ | ✅ | UI만 | - | - | - |
| ContractDocumentModal | - | - | ✅ | - | ✅ | - | ✅ |
| OrderDocumentModal | - | - | ✅ | - | ✅ | ✅ | - |
| HandoverReportModal | - | - | ✅ | - | ✅ | ✅ | - |
| 결재함 문서 3개 | - | - | - | - | - | - | - |
| 견적/발주 문서 | - | - | @media print | - | - | - | - |

### 1.4 문제점

1. **중복 코드**: 모달 래퍼, 버튼, 프린트 로직이 각 파일에 반복
2. **기능 불일치**: 줌 기능이 QMS에만 있음, 다른 문서에는 없음
3. **스타일 불일치**: 버튼 위치, 스타일이 문서마다 다름
4. **유지보수 어려움**: 17개 파일을 개별 관리

---

## 2. 설계 방향

### 2.1 핵심 원칙

1. **Config + 프리셋 패턴**: 프로젝트의 IntegratedDetailTemplate과 일관성 유지
2. **Shell/Content 분리**: 뷰어 기능과 문서 내용 완전 분리
3. **블록 기반 렌더링**: 향후 문서 빌더 대비
4. **점진적 마이그레이션**: 기존 컴포넌트 유지하면서 전환

### 2.2 아키텍처 개요

```
┌─────────────────────────────────────────────────────────┐
│  DocumentViewer (Shell)                                 │
│  - 줌/드래그 기능                                        │
│  - 액션 버튼 (인쇄, 다운로드, 수정, 삭제, 상신)            │
├─────────────────────────────────────────────────────────┤
│  DocumentRenderer (Content)                             │
│  ├── 정적 모드: 기존 컴포넌트 (component prop)           │
│  └── 동적 모드: 블록 배열 렌더링 (blocks prop) - 빌더용   │
└─────────────────────────────────────────────────────────┘
```

---

## 3. 상세 설계

### 3.1 프리셋 시스템

```typescript
// src/components/document-system/presets/index.ts
export const DOCUMENT_PRESETS = {
  // QMS 검사 문서용
  inspection: {
    features: { zoom: true, drag: true, print: true, download: true },
    actions: ['print', 'download'],
  },

  // 건설 프로젝트용 (CRUD)
  construction: {
    features: { zoom: true, drag: true, print: true, download: false },
    actions: ['edit', 'delete', 'print'],
  },

  // 결재 문서용
  approval: {
    features: { zoom: true, drag: true, print: true, download: false },
    actions: ['edit', 'submit', 'print'],
  },

  // 조회 전용
  readonly: {
    features: { zoom: true, drag: true, print: true, download: false },
    actions: ['print'],
  },
};
```

### 3.2 Config 인터페이스

```typescript
// src/components/document-system/types.ts
interface DocumentConfig {
  // 메타 정보
  type: string;
  title: string;
  preset?: keyof typeof DOCUMENT_PRESETS;

  // 뷰어 설정 (Shell) - 프리셋 오버라이드 가능
  features?: {
    zoom?: boolean;
    drag?: boolean;
    print?: boolean;
    download?: boolean;
  };
  actions?: ActionType[];

  // 콘텐츠 설정 (Content) - 둘 중 하나 사용
  component?: React.ComponentType<any>;  // Phase 1: 정적 모드
  blocks?: DocumentBlock[];               // Phase 2: 동적 모드 (빌더)
}

type ActionType = 'print' | 'download' | 'edit' | 'delete' | 'submit';
```

### 3.3 블록 시스템 (문서 빌더 대비)

```typescript
// src/components/document-system/types.ts
type DocumentBlock =
  | HeaderBlock
  | InfoTableBlock
  | ItemTableBlock
  | ApprovalLineBlock
  | SignatureBlock
  | TextSectionBlock
  | ImageGridBlock
  | CustomBlock;

interface HeaderBlock {
  type: 'header';
  title: string;
  logo?: boolean;
  showApprovalLine?: boolean;
  approvalPositions?: string[];  // ['작성', '검토', '승인']
}

interface InfoTableBlock {
  type: 'info-table';
  columns: 2 | 3 | 4;
  fields: {
    label: string;
    key: string;
    colSpan?: number;
  }[];
}

interface ItemTableBlock {
  type: 'item-table';
  columns: {
    key: string;
    label: string;
    width?: string;
    align?: 'left' | 'center' | 'right';
  }[];
  showTotal?: boolean;
  totalFields?: string[];
}

interface ApprovalLineBlock {
  type: 'approval-line';
  positions: string[];  // ['담당', '부서장', '결재']
  layout: 'horizontal' | 'vertical';
}

interface SignatureBlock {
  type: 'signature';
  positions: { label: string; name?: string }[];
}

interface TextSectionBlock {
  type: 'text-section';
  title?: string;
  content: string;
  style?: 'normal' | 'highlight' | 'note';
}

interface ImageGridBlock {
  type: 'image-grid';
  columns: 2 | 3 | 4;
  images: { src: string; caption?: string }[];
}

interface CustomBlock {
  type: 'custom';
  componentKey: string;  // 블록 레지스트리에서 찾음
  props?: Record<string, any>;
}
```

### 3.4 DocumentViewer Props

```typescript
interface DocumentViewerProps {
  // Config 기반 (권장)
  config?: DocumentConfig;

  // 또는 개별 props (하위 호환)
  title?: string;
  preset?: keyof typeof DOCUMENT_PRESETS;

  // 데이터
  data?: any;

  // 액션 핸들러
  onPrint?: () => void;
  onDownload?: () => void;
  onEdit?: () => void;
  onDelete?: () => void;
  onSubmit?: () => void;

  // 모달 제어
  open?: boolean;
  onOpenChange?: (open: boolean) => void;

  // 정적 모드용
  children?: React.ReactNode;
}
```

---

## 4. 폴더 구조

```
src/components/document-system/
├── index.ts                       # 공개 API
├── types.ts                       # 타입 정의
│
├── viewer/                        # 뷰어 (Shell)
│   ├── DocumentViewer.tsx         # 메인 컴포넌트
│   ├── DocumentToolbar.tsx        # 툴바 (줌 + 액션 버튼)
│   ├── DocumentContent.tsx        # 콘텐츠 영역 (줌/드래그)
│   └── hooks/
│       ├── useZoom.ts             # 줌 로직
│       ├── useDrag.ts             # 드래그 로직
│       └── usePrint.ts            # 인쇄 로직
│
├── renderer/                      # 렌더러 (Content)
│   ├── DocumentRenderer.tsx       # 정적/동적 분기
│   ├── StaticRenderer.tsx         # 정적 모드 (컴포넌트 렌더링)
│   └── BlockRenderer.tsx          # 동적 모드 (블록 렌더링)
│
├── blocks/                        # 블록 컴포넌트들
│   ├── index.ts                   # 블록 레지스트리
│   ├── HeaderBlock.tsx
│   ├── InfoTableBlock.tsx
│   ├── ItemTableBlock.tsx
│   ├── ApprovalLineBlock.tsx
│   ├── SignatureBlock.tsx
│   ├── TextSectionBlock.tsx
│   └── ImageGridBlock.tsx
│
├── presets/                       # 프리셋 정의
│   └── index.ts
│
└── configs/                       # 문서별 Config (정적)
    ├── index.ts                   # Config 레지스트리
    ├── qms/
    │   ├── importInspection.config.ts
    │   ├── productInspection.config.ts
    │   └── ...
    ├── construction/
    │   ├── contract.config.ts
    │   ├── handoverReport.config.ts
    │   └── order.config.ts
    ├── approval/
    │   ├── proposal.config.ts
    │   ├── expenseReport.config.ts
    │   └── expenseEstimate.config.ts
    └── orders/
        ├── contract.config.ts
        ├── transaction.config.ts
        └── purchaseOrder.config.ts
```

---

## 5. 사용 예시

### 5.1 Phase 1: 기존 컴포넌트 사용 (정적 모드)

```typescript
// configs/qms/importInspection.config.ts
import { ImportInspectionDocument } from '@/app/.../quality/qms/components/documents';

export const importInspectionConfig: DocumentConfig = {
  type: 'import-inspection',
  title: '수입검사 성적서',
  preset: 'inspection',
  component: ImportInspectionDocument,
};

// 페이지에서 사용
import { DocumentViewer } from '@/components/document-system';
import { importInspectionConfig } from '@/components/document-system/configs';

<DocumentViewer
  config={importInspectionConfig}
  data={inspectionData}
  open={isOpen}
  onOpenChange={setIsOpen}
/>
```

### 5.2 Phase 2: 블록 기반 (동적 모드 - 빌더용)

```typescript
// DB에서 가져온 템플릿
const customTemplate: DocumentConfig = {
  type: 'custom-report',
  title: '커스텀 검사 보고서',
  preset: 'inspection',
  blocks: [
    {
      type: 'header',
      title: '커스텀 검사 보고서',
      logo: true,
      showApprovalLine: true,
      approvalPositions: ['작성', '검토', '승인']
    },
    {
      type: 'info-table',
      columns: 2,
      fields: [
        { label: '품명', key: 'productName' },
        { label: '규격', key: 'specification' },
        { label: '검사일', key: 'inspectionDate' },
        { label: '검사자', key: 'inspector' },
      ]
    },
    {
      type: 'item-table',
      columns: [
        { key: 'no', label: 'No', width: '50px', align: 'center' },
        { key: 'item', label: '검사항목', align: 'left' },
        { key: 'standard', label: '기준', align: 'center' },
        { key: 'result', label: '결과', align: 'center' },
        { key: 'judgment', label: '판정', width: '80px', align: 'center' },
      ],
      showTotal: false
    },
    {
      type: 'text-section',
      title: '특기사항',
      content: '',
      style: 'note'
    },
    {
      type: 'signature',
      positions: [
        { label: '검사자', name: '' },
        { label: '확인자', name: '' },
      ]
    },
  ],
};

<DocumentViewer config={customTemplate} data={reportData} />
```

---

## 6. 마이그레이션 전략

### Phase 1: 공통 시스템 구축 (1주)
- [ ] document-system 폴더 구조 생성
- [ ] types.ts 작성
- [ ] DocumentViewer (Shell) 구현 - InspectionModal 기반
- [ ] useZoom, useDrag 훅 추출
- [ ] 프리셋 정의

### Phase 2: QMS 문서 마이그레이션 (3일)
- [ ] QMS 문서 6개 Config 작성
- [ ] InspectionModal → DocumentViewer 전환
- [ ] 기존 문서 컴포넌트는 그대로 유지 (component prop)

### Phase 3: 건설/결재함 문서 마이그레이션 (3일)
- [ ] 건설사업 문서 3개 Config 작성
- [ ] 결재함 문서 3개 Config 작성
- [ ] 견적/발주 문서 5개 Config 작성

### Phase 4: 블록 시스템 구축 (1주)
- [ ] 기본 블록 컴포넌트 구현 (Header, InfoTable, ItemTable 등)
- [ ] BlockRenderer 구현
- [ ] 블록 레지스트리 구축

### Phase 5: 문서 빌더 준비 (향후)
- [ ] 블록 편집 UI
- [ ] 템플릿 저장/불러오기 API
- [ ] 미리보기 기능

---

## 7. 예상 효과

| 항목 | Before | After |
|------|--------|-------|
| 총 코드량 | ~4,100줄 (17개 파일) | ~2,500줄 + 공통 시스템 |
| 새 문서 추가 | 200~400줄 | Config만 작성 (20~50줄) |
| 줌 기능 | QMS만 | **모든 문서** |
| UI 일관성 | 불일치 | **통일** |
| 빌더 확장성 | 불가능 | **블록 기반 지원** |

---

## 8. 참고: 기존 InspectionModal 구조

현재 줌/드래그 기능이 구현된 `InspectionModal.tsx` (587줄) 참고:

```typescript
// 줌 레벨
const ZOOM_LEVELS = [50, 75, 100, 125, 150, 200];
const MIN_ZOOM = 50;
const MAX_ZOOM = 200;

// 상태
const [zoom, setZoom] = useState(100);
const [isDragging, setIsDragging] = useState(false);
const [position, setPosition] = useState({ x: 0, y: 0 });

// 핵심 함수
handleZoomIn()    // 확대
handleZoomOut()   // 축소
handleZoomReset() // 맞춤 (100%)
handleMouseDown/Move/Up()  // 드래그
handleTouchStart/Move/End() // 터치 드래그
```

이 로직을 `useZoom`, `useDrag` 훅으로 추출하여 재사용.