Files
wace_rps/.cursor/plans/리포트_컴포넌트화_Phase3_확장_계획서.md
2026-03-12 18:47:42 +09:00

36 KiB
Raw Permalink Blame History

리포트 컴포넌트화 (Phase 3 확장) — 실행 계획서

작성일: 2026-03-10 | 최종 업데이트: 2026-03-10 (v5) 목표: 리포트 디자이너에서 만든 리포트를 화면관리의 V2 컴포넌트(v2-report-viewer)에서 reportId를 직접 지정하여 배치하고, 인라인 또는 모달로 렌더링하는 것.

참조 문서

순서 문서 경로 반영 내용
1 V2 컴포넌트 분석 가이드 docs/V2_컴포넌트_분석_가이드.md 파일 구조, v2- 접두사, Definition 네이밍
2 V2 컴포넌트 연동 가이드 docs/V2_컴포넌트_연동_가이드.md ScreenContext, V2 이벤트 시스템, formData 공유
3 화면개발 표준 가이드 docs/screen-implementation-guide/화면개발_표준_가이드.md V2 컴포넌트 목록, screen_layouts_v2 저장 구조
4 CLAUDE.md CLAUDE.md 네이밍 규칙, 표준 파일 구조, 코딩 규칙

완성 후 동작 플로우

플로우 A: 관리자가 화면에 리포트를 배치하는 과정 (설정 시점)

[1] 관리자가 화면 디자이너에 접속
    URL: /admin/screenMng/screenMngList
    → 화면 목록에서 "견적 관리" 화면을 더블클릭
    → 화면 디자이너 진입 (URL 변화 없음, ScreenDesigner.tsx 렌더링)

[2] 좌측 컴포넌트 패널에서 "리포트 뷰어" (v2-report-viewer)를 캔버스에 드래그&드롭
    ┌──────────────────────────────────────────────────────────────────┐
    │  [좌측 패널]          [캔버스]                    [우측 패널]     │
    │                                                                  │
    │  ▸ 입력              ┌────────────────────────┐                  │
    │  ▸ 버튼              │  v2-input: 주문번호     │                  │
    │  ▸ 테이블            ├────────────────────────┤                  │
    │  ▸ 표시              │  v2-table-list          │                  │
    │    ├ 리포트 뷰어 ◀   │  (주문 목록 테이블)      │                  │
    │    ├ 텍스트           ├────────────────────────┤                  │
    │    └ ...             │  ┌──────────────────┐  │                  │
    │                      │  │ 📄 리포트 (뷰어)  │  │  ← 방금 배치     │
    │                      │  │                  │  │                  │
    │                      │  └──────────────────┘  │                  │
    │                      └────────────────────────┘                  │
    └──────────────────────────────────────────────────────────────────┘

[3] 배치한 리포트 뷰어 컴포넌트를 클릭 → 우측 설정 패널이 열림
    ┌─────────────────────────────────────────────┐
    │  리포트 뷰어 설정                            │
    │                                             │
    │  컴포넌트 제목                               │
    │  [견적서 미리보기]  ___________________      │
    │                                             │
    │  리포트 선택                                 │
    │  ┌─────────────────────────────────────┐    │
    │  │ 리포트를 선택해주세요        [선택] │    │
    │  └─────────────────────────────────────┘    │
    │                                             │
    │  표시 모드                                   │
    │  [모달 (클릭 시 팝업)                  ▼]    │
    │                                             │
    │  파라미터 매핑                               │
    │  매핑 없음 — 폼 데이터가 자동 주입됩니다     │
    │                                   [+ 추가]  │
    └─────────────────────────────────────────────┘

[4] "선택" 버튼 클릭 → 리포트 선택 모달이 열림
    ┌──────────────────────────────────────────────────────┐
    │  리포트 선택                                    [×]  │
    │  ┌──────────────────────────────────────────────┐    │
    │  │ 🔍 견적...                                   │    │
    │  └──────────────────────────────────────────────┘    │
    │                                                      │
    │  ┌──────┬──────────────┬──────────┬─────────────┐    │
    │  │  ID  │ 리포트명      │ 유형     │ 사용여부     │    │
    │  ├──────┼──────────────┼──────────┼─────────────┤    │
    │  │  12  │ ▶ 견적서 ◀   │ 견적     │ Y           │ ← 클릭!
    │  │  15  │ 발주서        │ 발주     │ Y           │    │
    │  │  18  │ 검수 보고서   │ 검사     │ Y           │    │
    │  └──────┴──────────────┴──────────┴─────────────┘    │
    │                                                      │
    │  * 리포트 관리에서 만든 리포트 목록이 표시됩니다       │
    │  * 리포트 관리 URL: /admin/screenMng/reportList       │
    └──────────────────────────────────────────────────────┘

[5] "견적서" 행 클릭 → 모달 닫히고 설정 패널에 선택 결과 표시
    ┌─────────────────────────────────────────────┐
    │  리포트 뷰어 설정                            │
    │                                             │
    │  컴포넌트 제목                               │
    │  [견적서 미리보기]  ___________________      │
    │                                             │
    │  리포트 선택                                 │
    │  ┌─────────────────────────────────────┐    │
    │  │ 📄 견적서              [변경] [×]   │    │
    │  │    ID: 12 | 유형: 견적              │    │
    │  └─────────────────────────────────────┘    │
    │                                             │
    │  표시 모드                                   │
    │  [인라인 (화면 내 직접 표시)            ▼]    │  ← "인라인"으로 변경
    │                                             │
    │  파라미터 매핑                               │
    │  ┌─────────────────────────────────────┐    │
    │  │ $1  ←  order_no               [×]  │    │  ← 매핑 추가
    │  │                        [+ 추가]     │    │
    │  └─────────────────────────────────────┘    │
    │  쿼리의 $1에 폼 데이터의 order_no 값 전달    │
    └─────────────────────────────────────────────┘

[6] 화면 저장 → screen_layouts_v2 테이블에 JSONB로 저장됨
    저장되는 componentConfig:
    {
      "title": "견적서 미리보기",
      "reportId": 12,
      "reportName": "견적서",
      "displayMode": "inline",
      "paramMappings": [{ "param": "$1", "formField": "order_no" }]
    }

플로우 B: 사용자가 화면에서 리포트를 보는 과정 (실행 시점 — 인라인 모드)

[1] 사용자가 "견적 관리" 화면에 접속
    URL: /screens/45?menuObjid=789
    → DynamicComponentRenderer가 screen_layouts_v2에서 레이아웃 로드
    → v2-report-viewer 컴포넌트 렌더링 시작

[2] 화면 초기 상태 (formData에 order_no 없음)
    ┌──────────────────────────────────────────────────────────────┐
    │  견적 관리                                                    │
    │  ┌────────────────────────────────────────────────────────┐  │
    │  │  주문번호: [_______________]  [조회]                    │  │
    │  ├────────────────────────────────────────────────────────┤  │
    │  │  주문 목록 테이블                                       │  │
    │  │  ┌──────┬──────────┬──────────┬──────────┐             │  │
    │  │  │ 번호 │ 주문번호  │ 고객명    │ 금액     │             │  │
    │  │  │      │          │          │          │             │  │
    │  │  │  (데이터 없음)                         │             │  │
    │  │  └──────┴──────────┴──────────┴──────────┘             │  │
    │  ├────────────────────────────────────────────────────────┤  │
    │  │  견적서 미리보기              [↻ 새로고침] [↗ 전체보기]  │  │
    │  │  ┌──────────────────────────────────────────────────┐  │  │
    │  │  │                                                  │  │  │
    │  │  │   파라미터가 없어 리포트를 표시할 수 없습니다      │  │  │
    │  │  │                                                  │  │  │
    │  │  └──────────────────────────────────────────────────┘  │  │
    │  └────────────────────────────────────────────────────────┘  │
    └──────────────────────────────────────────────────────────────┘

[3] 사용자가 주문번호 입력 후 조회 → 테이블에 데이터 표시 → 행 선택
    → formData가 변경됨: { order_no: "ORD-2026-001", ... }
    → v2-report-viewer가 ScreenContext.formData 변경 감지
    → buildContextParams: { "$1": "ORD-2026-001" }
    → useReportExecution 훅이 즉시 쿼리 실행
    → reportApi.executeQuery(12, queryId, { "$1": "ORD-2026-001" })

[4] 리포트가 인라인으로 렌더링됨 (축소 표시)
    ┌──────────────────────────────────────────────────────────────┐
    │  견적 관리                                                    │
    │  ┌────────────────────────────────────────────────────────┐  │
    │  │  주문번호: [ORD-2026-001]  [조회]                       │  │
    │  ├────────────────────────────────────────────────────────┤  │
    │  │  주문 목록 테이블                                       │  │
    │  │  ┌──────┬──────────────┬──────────┬──────────┐         │  │
    │  │  │ 번호 │ 주문번호      │ 고객명    │ 금액     │         │  │
    │  │  │  1   │ ORD-2026-001 │ (주)가나  │ 1,500만  │ ← 선택  │  │
    │  │  │  2   │ ORD-2026-002 │ (주)다라  │ 800만    │         │  │
    │  │  └──────┴──────────────┴──────────┴──────────┘         │  │
    │  ├────────────────────────────────────────────────────────┤  │
    │  │  견적서 미리보기              [↻ 새로고침] [↗ 전체보기]  │  │
    │  │  ┌──────────────────────────────────────────────────┐  │  │
    │  │  │  ╔══════════════════════════════════════════╗     │  │  │
    │  │  │  ║          견   적   서                    ║     │  │  │
    │  │  │  ║──────────────────────────────────────────║     │  │  │
    │  │  │  ║  수신: (주)가나                          ║     │  │  │
    │  │  │  ║  주문번호: ORD-2026-001                  ║     │  │  │
    │  │  │  ║  ┌────┬──────────┬────┬──────────┐      ║     │  │  │
    │  │  │  ║  │ No │ 품목명    │ 수량│ 단가     │      ║     │  │  │
    │  │  │  ║  │ 1  │ 부품A    │ 100│ 50,000   │      ║     │  │  │
    │  │  │  ║  │ 2  │ 부품B    │ 50 │ 100,000  │      ║     │  │  │
    │  │  │  ║  └────┴──────────┴────┴──────────┘      ║     │  │  │
    │  │  │  ║  합계: 15,000,000원                     ║     │  │  │
    │  │  │  ╚══════════════════════════════════════════╝     │  │  │
    │  │  └──────────────────────────────────────────────────┘  │  │
    │  │  * 컴포넌트 크기에 맞게 축소(scale) 렌더링              │  │
    │  │  * 클릭하면 전체 보기 모달 열림                          │  │
    │  └────────────────────────────────────────────────────────┘  │
    └──────────────────────────────────────────────────────────────┘

[5] "전체보기" 버튼 또는 인라인 리포트 클릭 → 모달로 전체 크기 표시
    ┌──────────────────────────────────────────────────────────────┐
    │  견적서 — ORD-2026-001                        [PDF] [×]      │
    │  ┌──────────────────────────────────────────────────────┐    │
    │  │                                                      │    │
    │  │              (A4 크기 리포트 전체 표시)                │    │
    │  │              ReportListPreviewModal 사용              │    │
    │  │              (기존 모달 그대로)                        │    │
    │  │                                                      │    │
    │  └──────────────────────────────────────────────────────┘    │
    │  페이지: [< 1 / 1 >]                                        │
    └──────────────────────────────────────────────────────────────┘

플로우 C: 모달 모드로 설정한 경우 (실행 시점 — 모달 모드)

[1] 관리자가 설정 패널에서 displayMode = "모달" 선택 + reportId = 12 (견적서) 설정

[2] 사용자가 화면 접속 시 → 리포트 이름 + "보기" 버튼만 표시
    ┌────────────────────────────────────────────────────────┐
    │  견적서 미리보기                                        │
    │  ┌──────────────────────────────────────────────────┐  │
    │  │  📄 견적서                            [보기]     │  │
    │  └──────────────────────────────────────────────────┘  │
    └────────────────────────────────────────────────────────┘

[3] "보기" 버튼 클릭 → ReportListPreviewModal 모달 열림 (기존과 동일)
    → formData의 order_no 값이 $1 파라미터로 자동 바인딩
    → 모달 안에서 리포트 렌더링 + PDF 다운로드 가능

플로우 D: reportId 미지정 시 (하위 호환 — 기존 menuObjid 기반)

[1] 관리자가 설정 패널에서 reportId를 선택하지 않음 (또는 선택 해제)

[2] 사용자가 /screens/45?menuObjid=789 로 접속
    → menuObjid=789에 연결된 리포트 목록 자동 조회
    → 기존과 동일하게 리포트 버튼 목록 표시

    ┌────────────────────────────────────────────────────────┐
    │  리포트                                                │
    │  ┌──────────────────────────────────────────────────┐  │
    │  │  📄 견적서                                       │  │
    │  │  📄 발주서                                       │  │
    │  │  📄 거래명세서                                   │  │
    │  └──────────────────────────────────────────────────┘  │
    └────────────────────────────────────────────────────────┘

[3] 버튼 클릭 → 해당 리포트의 ReportListPreviewModal 모달 열림
    (현재 동작과 100% 동일)

데이터 흐름 요약

┌─────────────────┐     ┌──────────────────┐     ┌─────────────────────┐
│  화면 디자이너    │     │  화면 뷰어        │     │  백엔드 API          │
│  (설정 시점)     │     │  (실행 시점)      │     │                     │
├─────────────────┤     ├──────────────────┤     ├─────────────────────┤
│                 │     │                  │     │                     │
│ ConfigPanel     │     │ ReportViewer     │     │ GET /admin/reports  │
│   ↓ reportId    │ 저장 │ Component        │     │   → 리포트 목록     │
│   ↓ displayMode │ ──→ │   ↓              │     │                     │
│   ↓ paramMappings    │   ↓ config 로드    │     │ GET /admin/reports  │
│                 │     │   ↓              │     │     /:reportId      │
│ ReportSelect    │     │ reportId 있음?   │     │   → 리포트 상세     │
│ Modal           │     │   ├─ Yes         │     │                     │
│   ↓             │     │   │  displayMode?│     │ POST /admin/reports │
│ reportApi       │     │   │  ├─ inline   │     │   /:reportId/queries│
│ .getReports()   │     │   │  │  → Inline │     │   /:queryId/execute │
│                 │     │   │  │  Renderer │ ──→ │   → 쿼리 실행       │
│                 │     │   │  └─ modal    │     │   params: { $1: ... }│
│                 │     │   │     → 버튼   │     │                     │
│                 │     │   │     → 클릭시 │     │                     │
│                 │     │   │     모달     │     │                     │
│                 │     │   │              │     │                     │
│                 │     │   └─ No (fallback)     │ GET /admin/reports  │
│                 │     │      → menuObjid │     │   /by-menu/:objid   │
│                 │     │      기반 목록    │     │   → 메뉴별 리포트   │
│                 │     │                  │     │                     │
│                 │     │ formData 변경    │     │                     │
│                 │     │   → 즉시 재실행   │     │                     │
└─────────────────┘     └──────────────────┘     └─────────────────────┘

관련 URL 정리

화면 URL 역할
화면 목록 (관리자) /admin/screenMng/screenMngList 화면 목록 + 더블클릭 시 디자이너 진입
화면 디자이너 (관리자) (URL 변화 없음, 같은 페이지 내 ScreenDesigner 렌더링) 컴포넌트 배치 + 설정
리포트 관리 (관리자) /admin/screenMng/reportList 리포트 CRUD + 디자이너 진입
리포트 디자이너 (관리자) /admin/screenMng/reportList/designer/{reportId} SQL + 레이아웃 + 바인딩 설정
화면 뷰어 (사용자) /screens/{screenId}?menuObjid={menuObjid} 실제 화면 사용
POP 화면 뷰어 (사용자) /pop/screens/{screenId} POP 화면 사용

확정된 결정 사항

# 결정 항목 확정 내용
1 리포트 선택 방식 reportId 직접 지정 — 설정 패널에서 "리포트 선택" 버튼 → 리포트 목록 모달 → 선택하면 reportId 저장. menuObjid 기반은 fallback으로 유지
2 표시 모드 모달 + 인라인 선택 가능 — 설정에서 displayMode 선택 (modal / inline)
3 파라미터 바인딩 단순 키만formData['order_no'] 같은 1단계 키만 지원 (현재 방식 유지)
4 자동 갱신 즉시 자동 갱신 — formData 변경 시 즉시 리포트 재실행
5 버그 수정 범위 screens + pop/screens 모두 수정 — menuObjid 미전달 버그

1. 현재 코드 현황

v2-report-viewer 현재 파일 구조

frontend/lib/registry/components/v2-report-viewer/
├── index.ts                        # V2ReportViewerDefinition (28줄)
├── types.ts                        # ReportViewerConfig, ReportParamMapping (18줄)
├── ReportViewerComponent.tsx       # 메인 컴포넌트 (133줄)
├── ReportViewerConfigPanel.tsx     # 설정 패널 (115줄)
└── ReportViewerRenderer.tsx        # ComponentRegistry 등록 (12줄)

현재 문제점

문제 원인
reportId를 직접 지정할 수 없음 설정 패널에 리포트 선택 UI 없음
menuObjid 없으면 아무것도 안 보임 reportId fallback 없음
인라인 렌더링 불가 모달만 지원
formData 변경 시 자동 갱신 없음 감지 로직 없음
/screens/ 페이지에서 menuObjid 전달 안 됨 ScreenContextProvider에 props 미전달

2. 구현 단계 (7 Steps)

Step 1: menuObjid 미전달 버그 수정 [난이도: 낮음]

수정 파일 (2개):

파일 현재 변경
frontend/app/(main)/screens/[screenId]/page.tsx <ScreenContextProvider> (props 없음, 1377행) Wrapper에서 useSearchParamsmenuObjid 파싱 후 전달
frontend/app/(pop)/pop/screens/[screenId]/page.tsx <ScreenContextProvider> (props 없음, 348행) 동일

검증:

  • /screens/{screenId}?menuObjid=123 접속 → screenContext.menuObjid === 123 확인

Step 2: ReportViewerConfig 타입 확장 [난이도: 낮음]

수정 파일: frontend/lib/registry/components/v2-report-viewer/types.ts

export interface ReportViewerConfig extends ComponentConfig {
  title?: string;
  paramMappings?: ReportParamMapping[];

  reportId?: number;                       // 리포트 목록 모달에서 선택한 리포트 ID
  reportName?: string;                     // 선택한 리포트명 (설정 패널 표시용)
  displayMode?: "modal" | "inline";        // 기본: "modal"
}

Step 3: ConfigPanel에 리포트 선택 UI 추가 [난이도: 중간]

수정 파일: frontend/lib/registry/components/v2-report-viewer/ReportViewerConfigPanel.tsx

추가되는 UI 섹션:

  1. 리포트 선택 영역 (선택 버튼 → 리포트 목록 모달 → 선택 결과 표시 + 해제 버튼)
  2. 표시 모드 Select (모달 / 인라인)

리포트 선택 모달: reportApi.getReports({ limit: 100, useYn: 'Y' }) → 검색 + 테이블 → 행 클릭 시 선택 완료.


Step 4: ReportInlineRenderer + useReportExecution 추출 [난이도: 높음]

신규 파일 (2개):

파일 역할 위치 근거
frontend/hooks/useReportExecution.ts 리포트 로드 + 쿼리 실행 공용 훅 (~120줄) CLAUDE.md 네이밍 규칙: 훅은 frontend/hooks/에 배치. ReportListPreviewModalReportInlineRenderer 양쪽에서 공유하므로 특정 컴포넌트 폴더가 아닌 공용 위치가 적합
frontend/components/report/ReportInlineRenderer.tsx 모달 없이 인라인 렌더링 (~200줄) ReportListPreviewModal과 동일 레벨에 배치. v2-report-viewer 전용이 아니라 향후 다른 컨텍스트(예: 대시보드 위젯)에서도 재사용 가능한 범용 렌더러이므로 components/report/가 적합

useReportExecution: ReportListPreviewModal에서 리포트 로드 + 쿼리 실행 로직을 추출한 공용 훅.

ReportInlineRenderer: useReportExecution 훅 사용 + ResizeObserver로 scale 축소 렌더링 + 첫 페이지만 표시.


Step 5: ReportViewerComponent에 reportId 직접 지정 + displayMode 분기 [난이도: 중간]

수정 파일: frontend/lib/registry/components/v2-report-viewer/ReportViewerComponent.tsx

렌더링 분기:

config.reportId 있음:
  ├─ displayMode === "inline" → ReportInlineRenderer + 헤더(제목, 새로고침, 전체보기)
  └─ displayMode === "modal"  → 리포트명 + "보기" 버튼 → 클릭 시 모달

config.reportId 없음 (fallback):
  → menuObjid 기반 리포트 목록 (기존 동작 100% 유지)

Step 6: formData 변경 시 즉시 자동 갱신 [난이도: 중간]

수정 파일: ReportViewerComponent.tsx

ScreenContext.formData 변경 감지 → contextParams 재계산 → refreshKey 증가 → ReportInlineRenderer에 전달하여 즉시 재실행.


Step 7: 통합 테스트 + 가이드 문서 업데이트 [난이도: 낮음]

검증 시나리오: 플로우 A~D 전체 검증 + npx tsc --noEmit 오류 없음.

가이드 문서 업데이트:

  • docs/V2_컴포넌트_분석_가이드.md — V2 컴포넌트 목록에 v2-report-viewer 추가 (18개 → 19개)
  • docs/V2_컴포넌트_연동_가이드.md — 6.1 연동 능력 매트릭스에 v2-report-viewer 행 추가
  • docs/screen-implementation-guide/화면개발_표준_가이드.md — V2 컴포넌트 목록에 v2-report-viewer 추가 (23개 → 24개)

3. 파일 변경 요약

수정 파일 (5개)

파일 Step 핵심 변경
frontend/app/(main)/screens/[screenId]/page.tsx 1 ScreenContextProvider에 menuObjid 전달
frontend/app/(pop)/pop/screens/[screenId]/page.tsx 1 동일
frontend/lib/registry/components/v2-report-viewer/types.ts 2 reportId, reportName, displayMode 필드 추가
frontend/lib/registry/components/v2-report-viewer/ReportViewerConfigPanel.tsx 3 리포트 선택 모달 + displayMode Select
frontend/lib/registry/components/v2-report-viewer/ReportViewerComponent.tsx 5,6 reportId 분기 + displayMode 분기 + 자동 갱신

신규 파일 (2개)

파일 Step 역할
frontend/hooks/useReportExecution.ts 4 리포트 로드 + 쿼리 실행 공용 훅
frontend/components/report/ReportInlineRenderer.tsx 4 모달 없이 인라인 리포트 렌더링

수정 대상 (리팩토링, 선택적)

파일 Step 변경
frontend/components/report/ReportListPreviewModal.tsx 4 내부 로드/실행 로직을 useReportExecution으로 교체 (기능 변경 없음)

가이드 문서 업데이트 (3개)

파일 Step 변경
docs/V2_컴포넌트_분석_가이드.md 7 V2 컴포넌트 목록에 v2-report-viewer 추가
docs/V2_컴포넌트_연동_가이드.md 7 연동 능력 매트릭스에 v2-report-viewer 행 추가
docs/screen-implementation-guide/화면개발_표준_가이드.md 7 V2 컴포넌트 목록에 v2-report-viewer 추가

4. 구현 순서 및 의존성

Step 1  menuObjid 버그 수정 ─────────────────── (독립)
  ↓
Step 2  types.ts 확장 ───────────────────────── (Step 3, 5의 기반)
  ↓
Step 3  ConfigPanel 리포트 선택 UI ──────────── (Step 2 의존)
  ↓
Step 4  useReportExecution + ReportInlineRenderer (가장 큰 작업)
  ↓
Step 5  ReportViewerComponent 분기 렌더링 ───── (Step 2, 4 의존)
  ↓
Step 6  즉시 자동 갱신 ──────────────────────── (Step 5 의존)
  ↓
Step 7  통합 테스트 + 가이드 문서 업데이트

병렬 가능:

  • Step 1 + Step 2: 동시 진행 가능
  • Step 3 + Step 4: Step 2 완료 후 동시 진행 가능

5. V2 이벤트 시스템과의 관계

V2_컴포넌트_연동_가이드.md에서 정의한 V2 표준 이벤트 시스템(V2_EVENTS, dispatchV2Event, subscribeV2Event)과의 관계를 정리합니다.

현재 v2-report-viewer가 사용하지 않는 이유

V2 이벤트 사용 여부 이유
tableListDataChange 구독 안 함 리포트 뷰어는 테이블 데이터 변경이 아닌 ScreenContext.formData를 통해 파라미터를 받음
beforeFormSave / afterFormSave 구독 안 함 리포트 뷰어는 데이터를 저장하지 않음 (읽기 전용 표시 컴포넌트)
refreshTable 구독 안 함 리포트 갱신은 refreshKey prop으로 처리. 테이블 갱신 이벤트와는 무관
componentDataTransfer 구독 안 함 리포트 뷰어는 DataReceivable이 아님 (데이터를 수신하여 편집하는 컴포넌트가 아님)

formData 공유 방식

v2-report-viewerScreenContextformData를 통해 다른 컴포넌트와 통신합니다:

v2-input (order_no 입력)
  → ScreenContext.formData 업데이트
    → v2-report-viewer가 formData 변경 감지
      → buildContextParams로 쿼리 파라미터 생성
        → useReportExecution으로 쿼리 실행

이 방식은 V2_컴포넌트_연동_가이드.md 4.3절 ScreenContext의 formData 공유 패턴과 일치합니다.

향후 확장 시 이벤트 도입 가능성

리포트 실행 완료 후 다른 컴포넌트에 알림이 필요한 경우(예: 리포트 로드 완료 시 집계 위젯 갱신), V2 이벤트를 추가할 수 있습니다. 현재 Phase에서는 불필요합니다.


6. 충돌 사전 검사 대상

구현 시작 전 아래 이름들이 현재 코드베이스에 0건인지 Grep 확인 필수:

ReportInlineRenderer, useReportExecution,
ReportSelectModal, displayMode (v2-report-viewer 내),
reportName (v2-report-viewer/types.ts 내)

7. 주의사항

  1. 하위 호환 필수: 모든 신규 필드는 optional. reportId 없으면 기존 menuObjid 기반 동작 그대로 유지.
  2. reportId 타입: ReportMaster.report_idstring이지만 실제 값은 숫자 문자열. API 호출 시 String(reportId)로 변환.
  3. 멀티테넌시: reportApi.getReports() 호출 시 백엔드에서 자동으로 company_code 필터링됨.
  4. 디자인 모드 보호: isDesignMode일 때 API 호출, 자동 갱신 모두 스킵.
  5. ReportListPreviewModal 수정 최소화: 기존 모달은 그대로 유지. 공통 로직만 훅으로 추출.
  6. 인라인 렌더링 스케일: ResizeObserver로 컨테이너 크기 감지 → transform: scale(containerWidth / canvasWidth).
  7. V2 컴포넌트 규칙 준수: v2- 접두사, V2ReportViewerDefinition 네이밍, screen_layouts_v2 JSONB 저장.
  8. 각 Step 완료 시 필수: cd frontend && npx tsc --noEmit

8. 핵심 원칙

역할 담당
SQL 작성, 컴포넌트 레이아웃, queryId+field 연결, 숫자 포맷/합계 리포트 디자이너 (기존, 수정 없음)
어떤 리포트를 보여줄지 (reportId), 언제 실행할지 (자동 갱신), 어디에 표시할지 (displayMode) 화면관리 v2-report-viewer (이번 구현)

리포트 디자이너의 코드는 이번 작업에서 수정하지 않는다.


9. 연동 능력 매트릭스 (Step 7에서 가이드 문서에 추가할 내용)

컴포넌트 이벤트 발행 이벤트 구독 DataProvider DataReceiver Context 사용
v2-report-viewer - - - - Screen (formData, menuObjid)
소스 컴포넌트 타겟 컴포넌트 연동 방식 용도
v2-input / v2-table-list v2-report-viewer ScreenContext.formData 파라미터 바인딩
v2-report-viewer ReportListPreviewModal props (report, contextParams) 전체 보기 모달