9.5 KiB
9.5 KiB
리포트 페이지 관리 시스템 설계
1. 개요
리포트 디자이너에 다중 페이지 관리 기능을 추가하여 여러 페이지에 걸친 복잡한 문서를 작성할 수 있도록 합니다.
2. 주요 기능
2.1 페이지 관리
- 페이지 추가/삭제
- 페이지 복사
- 페이지 순서 변경 (드래그 앤 드롭)
- 페이지 이름 지정
2.2 페이지 네비게이션
- 좌측 페이지 썸네일 패널
- 페이지 간 전환 (클릭)
- 이전/다음 페이지 이동
- 페이지 번호 표시
2.3 페이지별 설정
- 페이지 크기 (A4, A3, Letter, 사용자 정의)
- 페이지 방향 (세로/가로)
- 여백 설정
- 배경색
2.4 컴포넌트 관리
- 컴포넌트는 특정 페이지에 속함
- 페이지 간 컴포넌트 복사/이동
- 현재 페이지의 컴포넌트만 표시
3. 데이터베이스 스키마
3.1 기존 구조 활용 (변경 없음)
report_layout 테이블의 layout_config (JSONB) 활용
기존:
{
"width": 210,
"height": 297,
"orientation": "portrait",
"components": [...]
}
변경 후:
{
"pages": [
{
"page_id": "page-uuid-1",
"page_name": "표지",
"page_order": 0,
"width": 210,
"height": 297,
"orientation": "portrait",
"margins": {
"top": 20,
"bottom": 20,
"left": 20,
"right": 20
},
"background_color": "#ffffff",
"components": [
{
"id": "comp-1",
"type": "text",
"x": 100,
"y": 50,
...
}
]
},
{
"page_id": "page-uuid-2",
"page_name": "본문",
"page_order": 1,
"width": 210,
"height": 297,
"orientation": "portrait",
"margins": { "top": 20, "bottom": 20, "left": 20, "right": 20 },
"background_color": "#ffffff",
"components": [...]
}
]
}
3.2 마이그레이션 전략
기존 단일 페이지 리포트 자동 변환:
// 기존 구조 감지 시
if (layoutConfig.components && !layoutConfig.pages) {
// 자동으로 pages 구조로 변환
layoutConfig = {
pages: [
{
page_id: uuidv4(),
page_name: "페이지 1",
page_order: 0,
width: layoutConfig.width || 210,
height: layoutConfig.height || 297,
orientation: layoutConfig.orientation || "portrait",
margins: { top: 20, bottom: 20, left: 20, right: 20 },
background_color: "#ffffff",
components: layoutConfig.components,
},
],
};
}
4. 프론트엔드 구조
4.1 타입 정의 (types/report.ts)
export interface ReportPage {
page_id: string;
report_id: string;
page_order: number;
page_name: string;
// 페이지 설정
width: number;
height: number;
orientation: 'portrait' | 'landscape';
// 여백
margin_top: number;
margin_bottom: number;
margin_left: number;
margin_right: number;
// 배경
background_color: string;
created_at?: string;
updated_at?: string;
}
export interface ComponentConfig {
id: string;
// page_id 불필요 (페이지의 components 배열에 포함됨)
type: 'text' | 'label' | 'image' | 'table' | ...;
x: number;
y: number;
width: number;
height: number;
// ... 기타 속성
}
export interface ReportLayoutConfig {
pages: ReportPage[];
}
4.2 Context 구조 변경
interface ReportDesignerContextType {
// 페이지 관리
pages: ReportPage[];
currentPageId: string | null;
currentPage: ReportPage | null;
addPage: () => void;
deletePage: (pageId: string) => void;
duplicatePage: (pageId: string) => void;
reorderPages: (sourceIndex: number, targetIndex: number) => void;
selectPage: (pageId: string) => void;
updatePage: (pageId: string, updates: Partial<ReportPage>) => void;
// 컴포넌트 (현재 페이지만)
currentPageComponents: ComponentConfig[];
// ... 기존 기능들
}
4.3 UI 구조
┌─────────────────────────────────────────────────────────────┐
│ ReportDesignerToolbar (저장, 미리보기, 페이지 추가 등) │
├──────────┬────────────────────────────────────┬─────────────┤
│ │ │ │
│ PageList │ ReportDesignerCanvas │ Right │
│ (좌측) │ (현재 페이지만 표시) │ Panel │
│ │ │ (속성) │
│ - Page 1 │ ┌──────────────────────────┐ │ │
│ - Page 2 │ │ │ │ │
│ * Page 3 │ │ [컴포넌트들] │ │ │
│ (현재) │ │ │ │ │
│ │ └──────────────────────────┘ │ │
│ [+ 추가] │ │ │
│ │ 이전 | 다음 (페이지 네비게이션) │ │
└──────────┴────────────────────────────────────┴─────────────┘
5. 컴포넌트 구조
5.1 새 컴포넌트
PageListPanel.tsx
- 좌측 페이지 목록 패널
- 페이지 썸네일 표시
- 드래그 앤 드롭으로 순서 변경
- 페이지 추가/삭제/복사 버튼
- 현재 페이지 하이라이트
PageNavigator.tsx
- 캔버스 하단의 페이지 네비게이션
- 이전/다음 버튼
- 현재 페이지 번호 표시
- 페이지 점프 (1/5 형식)
PageSettingsPanel.tsx
- 우측 패널 내 페이지 설정 섹션
- 페이지 크기, 방향
- 여백 설정
- 배경색
5.2 수정할 컴포넌트
ReportDesignerContext.tsx
- pages 상태 추가
- currentPageId 상태 추가
- 페이지 관리 함수들 추가
- components를 currentPageComponents로 필터링
ReportDesignerCanvas.tsx
- currentPageComponents만 렌더링
- 캔버스 크기를 currentPage 기준으로 설정
- 컴포넌트 추가 시 page_id 포함
ReportDesignerToolbar.tsx
- "페이지 추가" 버튼 추가
- 저장 시 pages도 함께 저장
ReportPreviewModal.tsx
- 모든 페이지 순서대로 미리보기
- 페이지 구분선 표시
- PDF 저장 시 모든 페이지 포함
6. API 엔드포인트
6.1 페이지 관리
// 페이지 목록 조회
GET /api/report/:reportId/pages
Response: { pages: ReportPage[] }
// 페이지 생성
POST /api/report/:reportId/pages
Body: { page_name, width, height, orientation, margins }
Response: { page: ReportPage }
// 페이지 수정
PUT /api/report/pages/:pageId
Body: Partial<ReportPage>
Response: { page: ReportPage }
// 페이지 삭제
DELETE /api/report/pages/:pageId
Response: { success: boolean }
// 페이지 순서 변경
PUT /api/report/:reportId/pages/reorder
Body: { pageOrders: Array<{ page_id, page_order }> }
Response: { success: boolean }
// 페이지 복사
POST /api/report/pages/:pageId/duplicate
Response: { page: ReportPage }
6.2 레이아웃 (기존 수정)
// 레이아웃 저장 (페이지별)
PUT /api/report/:reportId/layout
Body: {
pages: ReportPage[],
components: ComponentConfig[] // page_id 포함
}
7. 구현 단계
Phase 1: DB 및 백엔드 (0.5일)
- ✅ DB 스키마 생성
- ✅ API 엔드포인트 구현
- ✅ 기존 리포트 마이그레이션 (단일 페이지 생성)
Phase 2: 타입 및 Context (0.5일)
- ✅ 타입 정의 업데이트
- ✅ Context에 페이지 상태/함수 추가
- ✅ API 연동
Phase 3: UI 컴포넌트 (1일)
- ✅ PageListPanel 구현
- ✅ PageNavigator 구현
- ✅ PageSettingsPanel 구현
Phase 4: 통합 및 수정 (1일)
- ✅ Canvas에서 현재 페이지만 표시
- ✅ 컴포넌트 추가/수정 시 page_id 처리
- ✅ 미리보기에서 모든 페이지 표시
- ✅ PDF/WORD 저장에서 모든 페이지 처리
Phase 5: 테스트 및 최적화 (0.5일)
- ✅ 페이지 전환 성능 확인
- ✅ 썸네일 렌더링 최적화
- ✅ 버그 수정
총 예상 기간: 3-4일
8. 주의사항
8.1 성능 최적화
- 페이지 썸네일은 저해상도로 렌더링
- 현재 페이지 컴포넌트만 DOM에 유지
- 페이지 전환 시 애니메이션 최소화
8.2 호환성
- 기존 리포트는 자동으로 단일 페이지로 마이그레이션
- 템플릿도 페이지 구조 포함
8.3 사용자 경험
- 페이지 삭제 시 확인 다이얼로그
- 컴포넌트가 있는 페이지 삭제 시 경고
- 페이지 순서 변경 시 즉시 반영
9. 추후 확장 기능
9.1 페이지 템플릿
- 자주 사용하는 페이지 레이아웃 저장
- 페이지 추가 시 템플릿 선택
9.2 마스터 페이지
- 모든 페이지에 공통으로 적용되는 헤더/푸터
- 페이지 번호 자동 삽입
9.3 페이지 연결
- 테이블 데이터가 여러 페이지에 자동 분할
- 페이지 오버플로우 처리
10. 참고 자료
- 오즈리포트 메뉴얼
- Crystal Reports 페이지 관리
- Adobe InDesign 페이지 시스템