# 리포트 관리 시스템 설계 ## 1. 프로젝트 개요 ### 1.1 목적 ERP 시스템에서 다양한 업무 문서(발주서, 청구서, 거래명세서 등)를 동적으로 디자인하고 관리할 수 있는 리포트 관리 시스템을 구축합니다. ### 1.2 주요 기능 - 리포트 목록 조회 및 관리 - 드래그 앤 드롭 기반 리포트 디자이너 - 템플릿 관리 (기본 템플릿 + 사용자 정의 템플릿) - 쿼리 관리 (마스터/디테일) - 외부 DB 연동 - 인쇄 및 내보내기 (PDF, WORD) - 미리보기 기능 ## 2. 화면 구성 ### 2.1 리포트 목록 화면 (`/admin/report`) ``` ┌──────────────────────────────────────────────────────────────────┐ │ 리포트 관리 [+ 새 리포트] │ ├──────────────────────────────────────────────────────────────────┤ │ 검색: [____________________] [검색] [초기화] │ ├──────────────────────────────────────────────────────────────────┤ │ No │ 리포트명 │ 작성자 │ 수정일 │ 액션 │ ├────┼──────────────┼────────┼───────────┼────────────────────────┤ │ 1 │ 발주서 양식 │ 홍길동 │ 2025-10-01 │ 수정 │ 복사 │ 삭제 │ │ 2 │ 청구서 기본 │ 김철수 │ 2025-09-28 │ 수정 │ 복사 │ 삭제 │ │ 3 │ 거래명세서 │ 이영희 │ 2025-09-25 │ 수정 │ 복사 │ 삭제 │ └──────────────────────────────────────────────────────────────────┘ ``` **기능** - 리포트 목록 조회 (페이징, 정렬, 검색) - 새 리포트 생성 - 기존 리포트 수정 - 리포트 복사 - 리포트 삭제 - 리포트 미리보기 ### 2.2 리포트 디자이너 화면 ``` ┌──────────────────────────────────────────────────────────────────┐ │ 리포트 디자이너 [저장] [미리보기] [초기화] [목록으로] │ ├──────┬────────────────────────────────────────────────┬──────────┤ │ │ │ │ │ 템플릿│ 작업 영역 (캔버스) │ 속성 패널 │ │ │ │ │ │ 컴포넌트│ [드래그 앤 드롭] │ 쿼리 관리 │ │ │ │ │ │ │ │ DB 연동 │ └──────┴────────────────────────────────────────────────┴──────────┘ ``` ### 2.3 미리보기 모달 ``` ┌──────────────────────────────────────────────────────────────────┐ │ 미리보기 [닫기] │ ├──────────────────────────────────────────────────────────────────┤ │ │ │ [리포트 내용 미리보기] │ │ │ ├──────────────────────────────────────────────────────────────────┤ │ [인쇄] [PDF] [WORD] │ └──────────────────────────────────────────────────────────────────┘ ``` ## 3. 데이터베이스 설계 ### 3.1 테이블 구조 #### REPORT_TEMPLATE (리포트 템플릿) ```sql CREATE TABLE report_template ( template_id VARCHAR(50) PRIMARY KEY, -- 템플릿 ID template_name_kor VARCHAR(100) NOT NULL, -- 템플릿명 (한국어) template_name_eng VARCHAR(100), -- 템플릿명 (영어) template_type VARCHAR(30) NOT NULL, -- 템플릿 타입 (ORDER, INVOICE, STATEMENT, etc) is_system CHAR(1) DEFAULT 'N', -- 시스템 기본 템플릿 여부 (Y/N) thumbnail_url VARCHAR(500), -- 썸네일 이미지 경로 description TEXT, -- 템플릿 설명 layout_config TEXT, -- 레이아웃 설정 (JSON) default_queries TEXT, -- 기본 쿼리 (JSON) use_yn CHAR(1) DEFAULT 'Y', -- 사용 여부 sort_order INTEGER DEFAULT 0, -- 정렬 순서 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by VARCHAR(50), updated_at TIMESTAMP, updated_by VARCHAR(50) ); ``` #### REPORT_MASTER (리포트 마스터) ```sql CREATE TABLE report_master ( report_id VARCHAR(50) PRIMARY KEY, -- 리포트 ID report_name_kor VARCHAR(100) NOT NULL, -- 리포트명 (한국어) report_name_eng VARCHAR(100), -- 리포트명 (영어) template_id VARCHAR(50), -- 템플릿 ID (FK) report_type VARCHAR(30) NOT NULL, -- 리포트 타입 company_code VARCHAR(20), -- 회사 코드 description TEXT, -- 설명 use_yn CHAR(1) DEFAULT 'Y', -- 사용 여부 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by VARCHAR(50), updated_at TIMESTAMP, updated_by VARCHAR(50), FOREIGN KEY (template_id) REFERENCES report_template(template_id) ); ``` #### REPORT_LAYOUT (리포트 레이아웃) ```sql CREATE TABLE report_layout ( layout_id VARCHAR(50) PRIMARY KEY, -- 레이아웃 ID report_id VARCHAR(50) NOT NULL, -- 리포트 ID (FK) canvas_width INTEGER DEFAULT 210, -- 캔버스 너비 (mm) canvas_height INTEGER DEFAULT 297, -- 캔버스 높이 (mm) page_orientation VARCHAR(10) DEFAULT 'portrait', -- 페이지 방향 (portrait/landscape) margin_top INTEGER DEFAULT 20, -- 상단 여백 (mm) margin_bottom INTEGER DEFAULT 20, -- 하단 여백 (mm) margin_left INTEGER DEFAULT 20, -- 좌측 여백 (mm) margin_right INTEGER DEFAULT 20, -- 우측 여백 (mm) components TEXT, -- 컴포넌트 배치 정보 (JSON) created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by VARCHAR(50), updated_at TIMESTAMP, updated_by VARCHAR(50), FOREIGN KEY (report_id) REFERENCES report_master(report_id) ); ``` ## 4. 컴포넌트 목록 ### 4.1 기본 컴포넌트 #### 텍스트 관련 - **Text Field**: 단일 라인 텍스트 입력/표시 - **Text Area**: 여러 줄 텍스트 입력/표시 - **Label**: 고정 라벨 텍스트 - **Rich Text**: 서식이 있는 텍스트 (굵게, 기울임, 색상) #### 숫자/날짜 관련 - **Number**: 숫자 표시 (통화 형식 지원) - **Date**: 날짜 표시 (형식 지정 가능) - **Date Time**: 날짜 + 시간 표시 - **Calculate Field**: 계산 필드 (합계, 평균 등) #### 테이블/그리드 - **Data Table**: 데이터 테이블 (디테일 쿼리 바인딩) - **Summary Table**: 요약 테이블 - **Group Table**: 그룹핑 테이블 #### 이미지/그래픽 - **Image**: 이미지 표시 (로고, 서명 등) - **Line**: 구분선 - **Rectangle**: 사각형 (테두리) #### 특수 컴포넌트 - **Page Number**: 페이지 번호 - **Current Date**: 현재 날짜/시간 - **Company Info**: 회사 정보 (자동) - **Signature**: 서명란 - **Stamp**: 도장란 ### 4.2 컴포넌트 속성 각 컴포넌트는 다음 공통 속성을 가집니다: ```typescript interface ComponentBase { id: string; // 컴포넌트 ID type: string; // 컴포넌트 타입 x: number; // X 좌표 y: number; // Y 좌표 width: number; // 너비 height: number; // 높이 zIndex: number; // Z-인덱스 // 스타일 fontSize?: number; // 글자 크기 fontFamily?: string; // 폰트 fontWeight?: string; // 글자 굵기 fontColor?: string; // 글자 색상 backgroundColor?: string; // 배경색 borderWidth?: number; // 테두리 두께 borderColor?: string; // 테두리 색상 borderRadius?: number; // 모서리 둥글기 textAlign?: string; // 텍스트 정렬 padding?: number; // 내부 여백 // 데이터 바인딩 queryId?: string; // 연결된 쿼리 ID fieldName?: string; // 필드명 defaultValue?: string; // 기본값 format?: string; // 표시 형식 // 기타 visible?: boolean; // 표시 여부 printable?: boolean; // 인쇄 여부 conditional?: string; // 조건부 표시 (수식) } ``` ## 5. 템플릿 목록 ### 5.1 기본 템플릿 (시스템) #### 구매/발주 관련 - **발주서 (Purchase Order)**: 거래처에 발주하는 문서 - **구매요청서 (Purchase Request)**: 내부 구매 요청 문서 - **발주 확인서 (PO Confirmation)**: 발주 확인 문서 #### 판매/청구 관련 - **청구서 (Invoice)**: 고객에게 청구하는 문서 - **견적서 (Quotation)**: 견적 제공 문서 - **거래명세서 (Transaction Statement)**: 거래 내역 명세 - **세금계산서 (Tax Invoice)**: 세금 계산서 - **영수증 (Receipt)**: 영수 증빙 문서 #### 재고/입출고 관련 - **입고증 (Goods Receipt)**: 입고 증빙 문서 - **출고증 (Delivery Note)**: 출고 증빙 문서 - **재고 현황표 (Inventory Report)**: 재고 현황 - **이동 전표 (Transfer Note)**: 재고 이동 문서 #### 생산 관련 - **작업지시서 (Work Order)**: 생산 작업 지시 - **생산 일보 (Production Daily Report)**: 생산 일일 보고 - **품질 검사표 (Quality Inspection)**: 품질 검사 기록 - **불량 보고서 (Defect Report)**: 불량 보고 #### 회계/경영 관련 - **손익 계산서 (Income Statement)**: 손익 현황 - **대차대조표 (Balance Sheet)**: 재무 상태 - **현금 흐름표 (Cash Flow Statement)**: 현금 흐름 - **급여 명세서 (Payroll Slip)**: 급여 내역 #### 일반 문서 - **기본 양식 (Basic Template)**: 빈 캔버스 - **일반 보고서 (General Report)**: 일반 보고 양식 - **목록 양식 (List Template)**: 목록형 양식 ### 5.2 사용자 정의 템플릿 - 사용자가 직접 생성한 템플릿 - 기본 템플릿을 복사하여 수정 가능 - 회사별로 관리 가능 ## 6. API 설계 ### 6.1 리포트 목록 API #### GET `/api/admin/reports` 리포트 목록 조회 ```typescript // Request interface GetReportsRequest { page?: number; limit?: number; searchText?: string; reportType?: string; useYn?: string; sortBy?: string; sortOrder?: "ASC" | "DESC"; } // Response interface GetReportsResponse { items: ReportMaster[]; total: number; page: number; limit: number; } ``` #### GET `/api/admin/reports/:reportId` 리포트 상세 조회 ```typescript // Response interface ReportDetail { report: ReportMaster; layout: ReportLayout; queries: ReportQuery[]; components: Component[]; } ``` #### POST `/api/admin/reports` 리포트 생성 ```typescript // Request interface CreateReportRequest { reportNameKor: string; reportNameEng?: string; templateId?: string; reportType: string; description?: string; } // Response interface CreateReportResponse { reportId: string; message: string; } ``` #### PUT `/api/admin/reports/:reportId` 리포트 수정 ```typescript // Request interface UpdateReportRequest { reportNameKor?: string; reportNameEng?: string; reportType?: string; description?: string; useYn?: string; } ``` #### DELETE `/api/admin/reports/:reportId` 리포트 삭제 #### POST `/api/admin/reports/:reportId/copy` 리포트 복사 ### 6.2 템플릿 API #### GET `/api/admin/reports/templates` 템플릿 목록 조회 ```typescript // Response interface GetTemplatesResponse { system: ReportTemplate[]; // 시스템 템플릿 custom: ReportTemplate[]; // 사용자 정의 템플릿 } ``` #### POST `/api/admin/reports/templates` 템플릿 생성 (사용자 정의) ```typescript // Request interface CreateTemplateRequest { templateNameKor: string; templateNameEng?: string; templateType: string; description?: string; layoutConfig: any; defaultQueries?: any; } ``` #### PUT `/api/admin/reports/templates/:templateId` 템플릿 수정 #### DELETE `/api/admin/reports/templates/:templateId` 템플릿 삭제 ### 6.3 레이아웃 API #### GET `/api/admin/reports/:reportId/layout` 레이아웃 조회 #### PUT `/api/admin/reports/:reportId/layout` 레이아웃 저장 ```typescript // Request interface SaveLayoutRequest { canvasWidth: number; canvasHeight: number; pageOrientation: string; margins: { top: number; bottom: number; left: number; right: number; }; components: Component[]; } ``` ### 6.4 인쇄/내보내기 API #### POST `/api/admin/reports/:reportId/preview` 미리보기 생성 ```typescript // Request interface PreviewRequest { parameters?: { [key: string]: any }; format?: "HTML" | "PDF"; } // Response interface PreviewResponse { html?: string; // HTML 미리보기 pdfUrl?: string; // PDF URL } ``` #### POST `/api/admin/reports/:reportId/print` 인쇄 (PDF 생성) ```typescript // Request interface PrintRequest { parameters?: { [key: string]: any }; format: "PDF" | "WORD" | "EXCEL"; } // Response interface PrintResponse { fileUrl: string; fileName: string; fileSize: number; } ``` ## 7. 프론트엔드 구조 ### 7.1 페이지 구조 ``` /admin/report ├── ReportListPage.tsx # 리포트 목록 페이지 ├── ReportDesignerPage.tsx # 리포트 디자이너 페이지 └── components/ ├── ReportList.tsx # 리포트 목록 테이블 ├── ReportSearchForm.tsx # 검색 폼 ├── TemplateSelector.tsx # 템플릿 선택기 ├── ComponentPalette.tsx # 컴포넌트 팔레트 ├── Canvas.tsx # 캔버스 영역 ├── ComponentRenderer.tsx # 컴포넌트 렌더러 ├── PropertyPanel.tsx # 속성 패널 ├── QueryManager.tsx # 쿼리 관리 ├── QueryCard.tsx # 쿼리 카드 ├── ConnectionManager.tsx # 외부 DB 연결 관리 ├── PreviewModal.tsx # 미리보기 모달 └── PrintOptionsModal.tsx # 인쇄 옵션 모달 ``` ### 7.2 상태 관리 ```typescript interface ReportDesignerState { // 리포트 기본 정보 report: ReportMaster | null; // 레이아웃 layout: ReportLayout | null; components: Component[]; selectedComponentId: string | null; // 쿼리 queries: ReportQuery[]; queryResults: { [queryId: string]: any[] }; // 외부 연결 connections: ReportExternalConnection[]; // UI 상태 isDragging: boolean; isResizing: boolean; showPreview: boolean; showPrintOptions: boolean; // 히스토리 (Undo/Redo) history: { past: Component[][]; present: Component[]; future: Component[][]; }; } ``` ## 8. 구현 우선순위 ### Phase 1: 기본 기능 (2주) - [ ] 데이터베이스 테이블 생성 - [ ] 리포트 목록 화면 - [ ] 리포트 CRUD API - [ ] 템플릿 목록 조회 - [ ] 기본 템플릿 데이터 생성 ### Phase 2: 디자이너 기본 (2주) - [ ] 캔버스 구현 - [ ] 컴포넌트 드래그 앤 드롭 - [ ] 컴포넌트 선택/이동/크기 조절 - [ ] 속성 패널 (기본) - [ ] 저장/불러오기 ### Phase 3: 쿼리 관리 (1주) - [ ] 쿼리 추가/수정/삭제 - [ ] 파라미터 감지 및 입력 - [ ] 쿼리 실행 (내부 DB) - [ ] 쿼리 결과를 컴포넌트에 바인딩 ### Phase 4: 쿼리 관리 고급 (1주) - [ ] 쿼리 필드 매핑 - [ ] 컴포넌트와 데이터 바인딩 - [ ] 파라미터 전달 및 처리 ### Phase 5: 미리보기/인쇄 (1주) - [ ] HTML 미리보기 - [ ] PDF 생성 - [ ] WORD 생성 - [ ] 브라우저 인쇄 ### Phase 6: 고급 기능 (2주) - [ ] 템플릿 생성 기능 - [ ] 컴포넌트 추가 (이미지, 서명, 도장) - [ ] 계산 필드 - [ ] 조건부 표시 - [ ] Undo/Redo - [ ] 다국어 지원 ## 9. 기술 스택 ### Backend - **Node.js + TypeScript**: 백엔드 서버 - **PostgreSQL**: 데이터베이스 - **Prisma**: ORM - **Puppeteer**: PDF 생성 - **docx**: WORD 생성 ### Frontend - **Next.js + React**: 프론트엔드 프레임워크 - **TypeScript**: 타입 안정성 - **TailwindCSS**: 스타일링 - **react-dnd**: 드래그 앤 드롭 - **react-grid-layout**: 레이아웃 관리 - **react-to-print**: 인쇄 기능 - **react-pdf**: PDF 미리보기 ## 10. 보안 고려사항 ### 10.1 쿼리 실행 보안 - SELECT 쿼리만 허용 (INSERT, UPDATE, DELETE 금지) - 쿼리 결과 크기 제한 (최대 1000 rows) - 실행 시간 제한 (30초) - SQL 인젝션 방지 (파라미터 바인딩 강제) - 위험한 함수 차단 (DROP, TRUNCATE 등) ### 10.2 파일 보안 - 생성된 PDF/WORD 파일은 임시 디렉토리에 저장 - 파일은 24시간 후 자동 삭제 - 파일 다운로드 시 토큰 검증 ### 10.3 접근 권한 - 리포트 생성/수정/삭제 권한 체크 - 관리자만 템플릿 생성 가능 - 사용자별 리포트 접근 제어 ## 11. 성능 최적화 ### 11.1 PDF 생성 최적화 - 백그라운드 작업으로 처리 - 생성된 PDF는 CDN에 캐싱 ### 11.2 프론트엔드 최적화 - 컴포넌트 가상화 (많은 컴포넌트 처리) - 디바운싱/쓰로틀링 (드래그 앤 드롭) - 이미지 레이지 로딩 ### 11.3 데이터베이스 최적화 - 레이아웃 데이터는 JSON 형태로 저장 - 리포트 목록 조회 시 인덱스 활용 - 자주 사용하는 템플릿 캐싱 ## 12. 테스트 계획 ### 12.1 단위 테스트 - API 엔드포인트 테스트 - 쿼리 파싱 테스트 - PDF 생성 테스트 ### 12.2 통합 테스트 - 리포트 생성 → 쿼리 실행 → PDF 생성 전체 플로우 - 템플릿 적용 → 데이터 바인딩 테스트 ### 12.3 UI 테스트 - 드래그 앤 드롭 동작 테스트 - 컴포넌트 속성 변경 테스트 ## 13. 향후 확장 계획 ### 13.1 고급 기능 - 차트/그래프 컴포넌트 - 조건부 서식 (색상 변경 등) - 그룹핑 및 집계 함수 - 마스터-디테일 관계 자동 설정 ### 13.2 협업 기능 - 리포트 공유 - 버전 관리 - 댓글 기능 ### 13.3 자동화 - 스케줄링 (정기적 리포트 생성) - 이메일 자동 발송 - 알림 설정 ## 14. 참고 자료 ### 14.1 유사 솔루션 - Crystal Reports - JasperReports - BIRT (Business Intelligence and Reporting Tools) - FastReport ### 14.2 라이브러리 - [react-grid-layout](https://github.com/react-grid-layout/react-grid-layout) - [react-dnd](https://react-dnd.github.io/react-dnd/) - [puppeteer](https://pptr.dev/) - [docx](https://docx.js.org/)