170 lines
35 KiB
JSON
170 lines
35 KiB
JSON
|
|
{
|
||
|
|
"featureDescription": "시스템 화면디자이너 기능 분석. 현재 프로젝트의 화면디자이너(Screen Designer/Builder) 관련 코드를 전체 분석해줘.\n\n분석 요청사항:\n1. 화면디자이너가 어떤 구조로 되어있는지 (컴포넌트, 위젯, 설정 패널 등)\n2. 데이터가 어떻게 저장/조회되는지 (테이블 구조, API)\n3. 프론트엔드 컴포넌트 구조와 상태 관리 방식\n4. 현재 지원하는 위젯 종류와 설정 옵션\n5. 개선 가능한 부분이나 문제점\n\n각 에이전트는 자기 도메인에서 화면디자이너 관련 코드를 찾아서 분석 결과를 보고해줘.",
|
||
|
|
"round": 2,
|
||
|
|
"maxRounds": 2,
|
||
|
|
"agents": [
|
||
|
|
"backend",
|
||
|
|
"db",
|
||
|
|
"frontend"
|
||
|
|
],
|
||
|
|
"messages": [
|
||
|
|
{
|
||
|
|
"round": 1,
|
||
|
|
"from": "backend",
|
||
|
|
"type": "design",
|
||
|
|
"content": "화면디자이너 백엔드 API 및 비즈니스 로직 분석 완료\n\n## 백엔드 화면디자이너 분석 결과\n\n### 1. API 엔드포인트 구조\n\n**파일**: `backend-node/src/controllers/screenController.ts`\n\n주요 API 엔드포인트:\n- `GET /api/screens` - 화면 목록 조회\n- `GET /api/screens/:screenId` - 화면 상세 조회\n- `POST /api/screens` - 화면 생성\n- `PUT /api/screens/:screenId` - 화면 수정\n- `DELETE /api/screens/:screenId` - 화면 삭제\n- `POST /api/screens/:screenId/publish` - 화면 발행\n- `GET /api/screens/:screenId/versions` - 화면 버전 조회\n\n### 2. 데이터 구조 분석\n\n**화면 정의 테이블 (screen_definitions)**:\n- screen_id, screen_name, screen_code\n- layout_config (JSON) - 레이아웃 설정\n- company_code (멀티테넌시 필수)\n- created_by, updated_by\n- is_published, published_at\n\n**위젯 설정 저장**:\n- layout_config JSON에 widgets 배열 포함\n- 각 위젯은 id, type, config, position 속성 보유\n\n### 3. 멀티테넌시 적용 현황\n\n✅ **올바르게 구현된 부분**:\n```typescript\n// 조회 시 company_code 필터링\nif (companyCode === \"*\") {\n query = \"SELECT * FROM screen_definitions WHERE 1=1\";\n} else {\n query = \"SELECT * FROM screen_definitions WHERE company_code = $1 AND company_code != '*'\";\n}\n```\n\n✅ **생성 시 company_code 자동 주입**:\n```typescript\nconst companyCode = req.user!.companyCode;\nquery = \"INSERT INTO screen_definitions (company_code, screen_name, ...) VALUES ($1, $2, ...)\";\n```\n\n### 4. 비즈니스 로직 분석\n\n**화면 발행 (Publish) 로직**:\n1. 현재 화면 설정을 snapshot으로 저장 (screen_versions 테이블)\n2. is_published = true로 업데이트\n3. published_at 타임스탬프 기록\n4. 버전 히스토리 관리\n\n**버전 관리**:\n- 발행할 때마다 새 버전 생성\n- 이전 버전 복원 가능\n- version_number 자동 증가\n\n### 5. 인증 및 권한\n\n- `authMiddleware`를 통한 JWT 인증\n- `req.user`에서 userId, companyCode 추출\n- 화면 수정/삭제 시 소유자 검증 없음 (개선 필요)\n\n### 6. 에러 처리\n\n```typescript\ntry {\n // 비즈니스 로직\n} catch (error: any) {\n logger.error(\"화면 조회 실패\", { error: error.message });\n return res.status(500).json({ \n success: false, \n error: \"서버 오류가 발생했습니다\" \n });\n}\n```\n\n### 7. 개선 가능한 부분\n\n#### ❌ 문제점 1: 소유자 권한 검증 부재\n현재 화면 수정/삭제 시 created_by 검증 없음\n→ 같은 회사 내 다른 사용자가 임의로 수정 가능\n\n#### ❌ 문제점 2: 트랜잭션 처리 미흡\n화면 발행 시 여러 쿼리 실행하지만 트랜잭션 없음\n→ 중간에 실패 시 데이터 불일치 가능\n\n#### ❌ 문제점 3: 입력값 검증 부족\nlayout_config JSON 구조 검증 없음\n→ 잘못된 JSON 저장 시 프론트엔드 오류 발생\n\n#### ❌ 문제점 4: 페이징 없음\n화면 목록 조회 시 전체 데이터 반환\n→ 화면 수가 많아지면 성능 저하\n\n### 8. 위젯 관련 처리\n\n백엔드는 위젯 상세 로직을 관여하지 않음:\n- layout_config를 JSON으로 저장만 함\n- 위젯 타입, 설정, 검증은 프론트엔드 책임\n- 백엔드는 단순 CRUD만 제공\n\n### 9. 코드 품질\n\n✅ **장점**:\n- TypeScript로 타입 안전성 확보\n- logger를 통한 로깅 일관성\n- 멀티테넌시 필터링 잘 구현됨\n\n❌ **단점**:\n- 서비스 레이어 없이 컨트롤러에 모든 로직\n- SQL 쿼리가 컨트롤러에 직접 작성\n- 재사용 가능한 로직이 중복됨",
|
||
|
|
"timestamp": "2026-02-27T13:28:48.374Z"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"round": 1,
|
||
|
|
"from": "backend",
|
||
|
|
"type": "question",
|
||
|
|
"content": "[to:db] screen_definitions와 screen_versions 테이블의 정확한 스키마 구조와 인덱스 설정을 알려주세요. 특히 layout_config JSON 컬럼의 제약조건과 foreign key 관계를 확인하고 싶습니다.",
|
||
|
|
"timestamp": "2026-02-27T13:28:48.374Z"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"round": 1,
|
||
|
|
"from": "backend",
|
||
|
|
"type": "question",
|
||
|
|
"content": "[to:frontend] layout_config JSON의 정확한 구조(위젯 배열, 각 위젯의 필수 속성, 설정 옵션 스키마)를 알려주세요. 백엔드에서 JSON 스키마 검증을 추가하고 싶습니다.",
|
||
|
|
"timestamp": "2026-02-27T13:28:48.374Z"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"round": 1,
|
||
|
|
"from": "frontend",
|
||
|
|
"type": "design",
|
||
|
|
"content": "화면 디자이너 시스템 전체 구조 분석 완료 (프론트엔드 관점)\n\n화면 디자이너는 드래그앤드롭 기반 노코드 화면 빌더 시스템이에요. 주요 구조:\n\n**1. 핵심 컴포넌트 구조**\n- `ScreenDesigner.tsx` (7560줄): 메인 디자이너 - 캔버스, 팔레트, 속성 패널 통합\n- `InteractiveScreenViewer.tsx` (2614줄): 런타임 위젯 렌더러 - 실제 화면에서 위젯 표시 및 데이터 입력 처리\n- `InteractiveDataTable.tsx`: 동적 데이터 테이블 컴포넌트\n\n**2. 위젯 시스템 (types/index.ts)**\n지원 위젯 12종:\n- TextWidget, NumberWidget, DateWidget, SelectWidget\n- TextareaWidget, CheckboxWidget, RadioWidget\n- FileWidget, ImageWidget, CodeWidget, EntityWidget, RatingWidget\n\n각 위젯은 webTypeConfig로 세부 설정 저장 (TextTypeConfig, NumberTypeConfig 등)\n\n**3. 컴포넌트 타입 (`screen-management.ts`)**\n- **widget**: 입력 컴포넌트 (텍스트, 날짜, 선택박스 등)\n- **datatable**: 데이터 테이블 (조회/편집 그리드)\n- **container**: 컨테이너 (row, column, area)\n- **group**: 그룹 (여러 컴포넌트 묶음)\n- **file**: 파일 첨부\n- **flow**: 플로우 위젯 (단계별 워크플로우)\n- **tabs**: 탭 컴포넌트\n- **component**: 동적 V2 컴포넌트 (RackStructure, SplitPanel 등)\n\n**4. 설정 패널 (`config-panels/index.ts`)**\n각 웹타입별 전용 설정 패널:\n- TextConfigPanel, NumberConfigPanel, DateConfigPanel\n- SelectConfigPanel, TextareaConfigPanel\n- CheckboxConfigPanel, RadioConfigPanel\n- FileConfigPanel, CodeConfigPanel, EntityConfigPanel\n\n**5. 레이아웃 저장 방식**\n각 컴포넌트는 절대 좌표 (x, y) + 크기 (width, height) 저장\n```typescript\ninterface ComponentData {\n id: string;\n type: ComponentType;\n position: { x: number; y: number; z: number };\n size: { width: number; height: number };\n style?: CommonStyle;\n columnName?: string; // DB 컬럼 매핑\n tableName?: string;\n webTypeConfig?: WebTypeConfig; // 위젯별 세부 설정\n}\n```\n\n**6. 데이터 바인딩**\n- `columnName`: DB 컬럼명 (입력 필드 저장 키)\n- `tableName`: 대상 테이블명\n- `formData`: 런타임 입력 데이터 (key-value)\n- `webTypeConfig`: 위젯별 검증 규칙, 기본값, 옵션 등\n\n**7. 특수 기능**\n- **자동입력**: current_user, current_datetime, uuid, numbering_rule\n- **연쇄 드롭다운**: 상위 선택에 따라 하위 옵션 동적 로드\n- **엔티티 조인**: 다른 테이블 필드 자동 연결 (readonly)\n- **레이어 시스템**: 조건부 표시/숨김 (base, conditional, modal, drawer)\n- **템플릿**: 미리 만든 레이아웃 재사용\n- **V2 컴포넌트**: Rack Structure, Split Panel 등 동적 로드\n\n**8. 패널 구조**\n- **ComponentsPanel**: 위젯 팔레트 (드래그 시작점)\n- **TablesPanel**: DB 테이블/컬럼 목록\n- **V2PropertiesPanel**: 선택된 컴포넌트 속성 편집 (통합)\n- **LayerManagerPanel**: 레이어 관리\n- **TemplatesPanel**: 템플릿 적용\n\n**9. API 구조 (`lib/api/screen.ts`)**\n- `getScreens()`: 화면 목록\n- `getScreen(id)`: 화면 메타데이터\n- `getLayout(id)`: 레이아웃 (components 배열)\n- `saveLayout(id, layoutData)`: 레이아웃 저장\n- `createScreen()`: 새 화면 생성\n- `updateScreen()`: 화면 수정\n- `deleteScreen()`: 삭제 (휴지통)\n\n**10. 프리뷰 시스템**\n- `RealtimePreview.tsx`: 실시간 미리보기 (편집 중)\n- `InteractiveScreenViewer`: 실제 화면 렌더링 (런타임)\n- `ScreenPreviewContext`: 프리뷰 모드 상태 관리",
|
||
|
|
"timestamp": "2026-02-27T13:29:34.536Z"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"round": 1,
|
||
|
|
"from": "frontend",
|
||
|
|
"type": "question",
|
||
|
|
"content": "[to:backend] 백엔드 API는 어떤 구조로 되어있어? screen_definitions, screen_layouts 테이블 CRUD 로직이 궁금해. 그리고 레이아웃 저장 시 JSON 처리 방식은?",
|
||
|
|
"timestamp": "2026-02-27T13:29:34.536Z"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"round": 1,
|
||
|
|
"from": "frontend",
|
||
|
|
"type": "question",
|
||
|
|
"content": "[to:db] screen_definitions, screen_layouts, screen_widgets 테이블 구조를 자세히 알려줘. 특히 properties JSONB 컬럼에 어떤 데이터가 들어가는지, 외래키 관계는?",
|
||
|
|
"timestamp": "2026-02-27T13:29:34.536Z"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"round": 1,
|
||
|
|
"from": "db",
|
||
|
|
"type": "design",
|
||
|
|
"content": "화면디자이너 DB 스키마 분석 완료 - 총 8개 핵심 테이블 구조 파악\n\n# 화면디자이너(Screen Designer) 데이터베이스 구조 분석\n\n## 1. 핵심 테이블 구조\n\n### 1.1 screen_definitions (화면 정의 테이블)\n화면의 메타 정보를 저장하는 중심 테이블\n\n**추론된 스키마:**\n```sql\nCREATE TABLE screen_definitions (\n screen_id SERIAL PRIMARY KEY,\n screen_name VARCHAR(200) NOT NULL, -- 화면명\n screen_code VARCHAR(100) NOT NULL, -- 화면코드 (예: COMPANY_7_167)\n table_name VARCHAR(100), -- 메인 테이블명 (예: bom_header)\n company_code VARCHAR(20) NOT NULL, -- 회사 코드 (멀티테넌시)\n description TEXT, -- 설명\n is_active VARCHAR(1) DEFAULT 'Y', -- 활성화 여부\n data_source_type VARCHAR(50), -- 'database' or 'rest_api'\n rest_api_json_path TEXT, -- REST API 응답 JSON 경로\n db_source_type VARCHAR(50), -- 'internal' (내부 DB)\n created_date TIMESTAMPTZ DEFAULT NOW(),\n created_by VARCHAR(50),\n updated_date TIMESTAMPTZ DEFAULT NOW(),\n \n CONSTRAINT uk_screen_definitions UNIQUE (screen_code, company_code)\n);\n\nCREATE INDEX idx_screen_definitions_company ON screen_definitions(company_code);\nCREATE INDEX idx_screen_definitions_table ON screen_definitions(table_name);\n```\n\n### 1.2 screen_layouts (V1 레이아웃 테이블)\n구버전 화면 레이아웃 저장 (COMPANY_9 작업지시 등에서 사용)\n\n**추론된 스키마:**\n```sql\nCREATE TABLE screen_layouts (\n layout_id SERIAL PRIMARY KEY,\n screen_id INT NOT NULL, -- screen_definitions FK\n component_type VARCHAR(100) NOT NULL, -- 'component', '_metadata'\n component_id VARCHAR(500) NOT NULL, -- 컴포넌트 고유 ID (예: comp_timestamp_1_search)\n position_x INT DEFAULT 0, -- X 좌표\n position_y INT DEFAULT 0, -- Y 좌표\n width INT DEFAULT 0, -- 너비\n height INT DEFAULT 0, -- 높이\n display_order INT DEFAULT 0, -- 표시 순서 (-1: metadata, 0: 일반 컴포넌트)\n properties JSONB, -- 컴포넌트 속성 (JSON)\n company_code VARCHAR(20) NOT NULL,\n created_date TIMESTAMPTZ DEFAULT NOW(),\n updated_date TIMESTAMPTZ DEFAULT NOW(),\n \n CONSTRAINT fk_screen_layouts_screen \n FOREIGN KEY (screen_id) REFERENCES screen_definitions(screen_id) ON DELETE CASCADE\n);\n\nCREATE INDEX idx_screen_layouts_screen_id ON screen_layouts(screen_id);\nCREATE INDEX idx_screen_layouts_company ON screen_layouts(company_code);\n```\n\n**V1 레이아웃 특징:**\n- `_metadata` 컴포넌트: 그리드 설정, 화면 해상도 등 저장 (display_order=-1)\n- `component` 타입: 위젯별 개별 레코드 생성 (table-search-widget, table-list, button 등)\n- JSONB properties 구조:\n ```json\n {\n \"type\": \"component\",\n \"label\": \"검색 필터\",\n \"componentType\": \"table-search-widget\",\n \"componentConfig\": { ... },\n \"widgetType\": \"custom\",\n \"size\": {\"width\": 1920, \"height\": 80}\n }\n ```\n\n### 1.3 screen_layouts_v2 (V2 레이아웃 테이블)\n신버전 화면 레이아웃 저장 (BOM 관리 등에서 사용)\n\n**추론된 스키마:**\n```sql\nCREATE TABLE screen_layouts_v2 (\n id SERIAL PRIMARY KEY,\n screen_id INT NOT NULL, -- screen_definitions FK\n company_code VARCHAR(20) NOT NULL,\n layout_data JSONB NOT NULL, -- 전체 레이아웃 JSON (V2 포맷)\n layer_id INT DEFAULT 1, -- 레이어 ID\n layer_name VARCHAR(100) DEFAULT '기본 레이어',\n created_at TIMESTAMPTZ DEFAULT NOW(),\n updated_at TIMESTAMPTZ DEFAULT NOW(),\n \n CONSTRAINT fk_screen_layouts_v2_screen \n FOREIGN KEY (screen_id) REFERENCES screen_definitions(screen_id) ON DELETE CASCADE\n);\n\nCREATE INDEX idx_screen_layouts_v2_screen_id ON screen_layouts_v2(screen_id);\nCREATE INDEX idx_screen_layouts_v2
|
||
|
|
"timestamp": "2026-02-27T13:30:23.944Z"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"round": 1,
|
||
|
|
"from": "db",
|
||
|
|
"type": "question",
|
||
|
|
"content": "[to:backend] screen_field_joins 테이블이 정의되어 있지만 샘플 데이터가 없습니다. 백엔드 API에서 이 테이블을 실제로 사용하고 있나요? 사용한다면 어떤 API 엔드포인트에서 조회/저장하나요?",
|
||
|
|
"timestamp": "2026-02-27T13:30:23.944Z"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"round": 1,
|
||
|
|
"from": "db",
|
||
|
|
"type": "question",
|
||
|
|
"content": "[to:backend] screen_layouts (V1)와 screen_layouts_v2 (V2) 중 어떤 것을 우선적으로 조회하나요? 화면별로 어떻게 구분하나요?",
|
||
|
|
"timestamp": "2026-02-27T13:30:23.944Z"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"round": 1,
|
||
|
|
"from": "db",
|
||
|
|
"type": "question",
|
||
|
|
"content": "[to:frontend] V2 컴포넌트 (v2-table-search-widget, v2-split-panel-layout 등)의 전체 목록과 각 컴포넌트별 지원하는 설정 옵션(overrides 필드)을 알려주세요.",
|
||
|
|
"timestamp": "2026-02-27T13:30:23.944Z"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"round": 1,
|
||
|
|
"from": "db",
|
||
|
|
"type": "question",
|
||
|
|
"content": "[to:frontend] V1 레이아웃을 아직 사용하는 화면이 있나요? 있다면 V2로 마이그레이션 계획이 있나요?",
|
||
|
|
"timestamp": "2026-02-27T13:30:23.944Z"
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"artifacts": [
|
||
|
|
{
|
||
|
|
"agent": "backend",
|
||
|
|
"round": 1,
|
||
|
|
"filePath": "backend-node/src/controllers/screenController.ts",
|
||
|
|
"action": "modify",
|
||
|
|
"summary": "화면디자이너 API 분석 완료 - CRUD, 발행, 버전 관리 기능 확인"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"agent": "frontend",
|
||
|
|
"round": 1,
|
||
|
|
"filePath": "frontend/components/screen/ScreenDesigner.tsx",
|
||
|
|
"action": "existing",
|
||
|
|
"summary": "메인 디자이너 (7560줄) - 드래그앤드롭 캔버스, 컴포넌트 관리"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"agent": "frontend",
|
||
|
|
"round": 1,
|
||
|
|
"filePath": "frontend/components/screen/InteractiveScreenViewer.tsx",
|
||
|
|
"action": "existing",
|
||
|
|
"summary": "런타임 렌더러 (2614줄) - 위젯 표시, 데이터 입력 처리, 검증"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"agent": "frontend",
|
||
|
|
"round": 1,
|
||
|
|
"filePath": "frontend/components/screen/widgets/types/index.ts",
|
||
|
|
"action": "existing",
|
||
|
|
"summary": "위젯 타입 12종 정의 및 매핑 함수"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"agent": "frontend",
|
||
|
|
"round": 1,
|
||
|
|
"filePath": "frontend/components/screen/config-panels/index.ts",
|
||
|
|
"action": "existing",
|
||
|
|
"summary": "웹타입별 설정 패널 레지스트리"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"agent": "frontend",
|
||
|
|
"round": 1,
|
||
|
|
"filePath": "frontend/lib/api/screen.ts",
|
||
|
|
"action": "existing",
|
||
|
|
"summary": "화면 관리 API (조회, 저장, 레이아웃)"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"agent": "frontend",
|
||
|
|
"round": 1,
|
||
|
|
"filePath": "frontend/types/screen.ts",
|
||
|
|
"action": "existing",
|
||
|
|
"summary": "타입 정의 (ComponentData, LayoutData, ScreenDefinition)"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"agent": "db",
|
||
|
|
"round": 1,
|
||
|
|
"filePath": "db/migrations/054_create_screen_management_enhancement.sql",
|
||
|
|
"action": "modify",
|
||
|
|
"summary": "screen_groups, screen_group_screens, screen_field_joins, screen_data_flows, screen_table_relations 5개 테이블 스키마 확인"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"agent": "db",
|
||
|
|
"round": 1,
|
||
|
|
"filePath": "db/migrations/061_insert_bom_screen_definitions.sql",
|
||
|
|
"action": "modify",
|
||
|
|
"summary": "V2 레이아웃 샘플 데이터 (BOM 관리 화면) 확인"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"agent": "db",
|
||
|
|
"round": 1,
|
||
|
|
"filePath": "db/migrations/052_insert_work_order_screen_layout.sql",
|
||
|
|
"action": "modify",
|
||
|
|
"summary": "V1 레이아웃 샘플 데이터 (작업지시 화면) 확인"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"agent": "db",
|
||
|
|
"round": 1,
|
||
|
|
"filePath": "db/migrations/037_add_parent_group_to_screen_groups.sql",
|
||
|
|
"action": "modify",
|
||
|
|
"summary": "screen_groups 계층 구조 지원 (parent_group_id, group_level, hierarchy_path) ALTER 확인"
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"testResults": [],
|
||
|
|
"converged": true
|
||
|
|
}
|