diff --git a/docs/화면간_데이터_관계_설정_시스템_설계.md b/docs/화면간_데이터_관계_설정_시스템_설계.md new file mode 100644 index 00000000..5806867a --- /dev/null +++ b/docs/화면간_데이터_관계_설정_시스템_설계.md @@ -0,0 +1,670 @@ +# 데이터 흐름 관리 시스템 설계 + +## 📋 목차 + +1. [시스템 개요](#시스템-개요) +2. [핵심 기능](#핵심-기능) +3. [데이터베이스 설계](#데이터베이스-설계) +4. [프론트엔드 설계](#프론트엔드-설계) +5. [API 설계](#api-설계) +6. [사용 시나리오](#사용-시나리오) +7. [구현 계획](#구현-계획) + +## 🎯 시스템 개요 + +### 데이터 흐름 관리 시스템이란? + +데이터 흐름 관리 시스템은 회사별로 화면들 간의 데이터 흐름과 관계를 시각적으로 설계하고 관리할 수 있는 시스템입니다. React Flow 라이브러리를 활용하여 직관적인 노드 기반 인터페이스로 1:1, 1:N, N:1, N:N 관계를 지원하며, 다양한 연결 방식과 종류로 복합적인 데이터 흐름을 설계할 수 있습니다. + +### 주요 특징 + +- **React Flow 기반 인터페이스**: 직관적인 노드와 엣지 기반 시각적 설계 +- **회사별 관계 관리**: 사용자 회사 코드에 따른 화면 관계 접근 제어 +- **시각적 관계 설계**: 드래그앤드롭으로 화면 노드 배치 및 필드 간 연결 +- **다양한 관계 타입**: 1:1, 1:N, N:1, N:N 관계 지원 +- **연결 종류별 세부 설정**: 단순 키값, 데이터 저장, 외부 호출 +- **실시간 시뮬레이션**: 설계한 관계의 데이터 흐름 시뮬레이션 +- **중계 테이블 자동 생성**: N:N 관계에서 중계 테이블 자동 생성 +- **인터랙티브 캔버스**: 줌, 팬, 미니맵 등 React Flow의 고급 기능 활용 + +### 지원하는 관계 타입 + +- **1:1 (One to One)**: 한 화면의 필드와 다른 화면의 필드가 1:1로 연결 +- **1:N (One to Many)**: 한 화면의 필드가 여러 화면의 필드와 연결 +- **N:1 (Many to One)**: 여러 화면의 필드가 한 화면의 필드와 연결 +- **N:N (Many to Many)**: 여러 화면의 필드가 여러 화면의 필드와 연결 + +### 지원하는 연결 종류 + +- **단순 키값 연결**: 중계 테이블을 통한 참조 관계 +- **데이터 저장**: 필드 매핑을 통한 데이터 저장 +- **외부 호출**: API, 이메일, 웹훅 등을 통한 외부 시스템 연동 + +## 🚀 핵심 기능 + +### 1. React Flow 기반 화면 노드 관리 + +- **화면 추가**: 회사별 화면 목록에서 관계를 설정할 화면들을 React Flow 캔버스에 추가 +- **화면 배치**: 드래그앤드롭으로 화면 노드를 원하는 위치에 배치 +- **화면 이동**: React Flow의 내장 기능으로 화면 노드 자유롭게 이동 +- **노드 선택**: 단일 또는 다중 노드 선택 지원 +- **자동 정렬**: React Flow의 레이아웃 알고리즘을 활용한 자동 정렬 + +### 2. React Flow 기반 필드 간 연결 설정 + +- **필드 선택**: 첫 번째 화면의 필드를 클릭하여 연결 시작 +- **대상 필드 선택**: 두 번째 화면의 필드를 클릭하여 연결 대상 지정 +- **드래그 연결**: React Flow의 핸들(Handle)을 드래그하여 시각적 연결 +- **관계 타입 선택**: 1:1, 1:N, N:1, N:N 중 선택 +- **연결 종류 선택**: 단순 키값, 데이터 저장, 외부 호출 중 선택 +- **엣지 커스터마이징**: 연결 타입별 색상, 스타일, 라벨 설정 + +### 3. 연결 종류별 세부 설정 + +#### 단순 키값 연결 + +- **중계 테이블명**: 자동 생성 또는 사용자 정의 +- **연결 규칙**: 중계 테이블 생성 및 관리 규칙 +- **참조 무결성**: 외래키 제약조건 설정 + +#### 데이터 저장 + +- **필드 매핑**: 소스 필드와 대상 필드 매핑 설정 +- **저장 조건**: 데이터 저장 조건 정의 +- **데이터 변환**: 필드 값 변환 규칙 + +#### 외부 호출 + +- **REST API**: API URL, HTTP Method, Headers, Body Template +- **이메일**: SMTP 서버, 발신자, 수신자, 제목/본문 템플릿 +- **웹훅**: 웹훅 URL, Payload 형식, Payload 템플릿 +- **FTP**: FTP 서버, 업로드 경로, 파일명 템플릿 +- **메시지 큐**: 큐 시스템, 큐 이름, 메시지 형식 + +### 4. React Flow 기반 시각적 관계 관리 + +- **엣지 렌더링**: React Flow의 커스텀 엣지로 화면 간 관계를 시각적으로 표현 +- **관계 타입별 스타일링**: 연결 종류에 따른 색상, 선 스타일, 라벨 구분 +- **인터랙티브 캔버스**: 줌, 팬, 미니맵을 통한 대규모 다이어그램 탐색 +- **실시간 시뮬레이션**: 데이터 흐름 애니메이션 및 시뮬레이션 +- **관계 검증**: 연결 가능성 및 무결성 검증 +- **엣지 편집**: 연결선 클릭으로 관계 설정 수정 + +### 5. 관계 통계 및 관리 + +- **연결 통계**: 관계 타입별 연결 수 표시 +- **중계 테이블 관리**: 생성된 중계 테이블 목록 및 관리 +- **관계 목록**: 생성된 모든 관계 목록 조회 +- **관계 삭제**: 불필요한 관계 삭제 + +## 🗄️ 데이터베이스 설계 + +### 1. 화면 관계 테이블 + +```sql +-- 화면 간 관계 정의 +CREATE TABLE screen_relationships ( + relationship_id SERIAL PRIMARY KEY, + relationship_name VARCHAR(200) NOT NULL, + from_screen_id INTEGER NOT NULL, + from_field_name VARCHAR(100) NOT NULL, + to_screen_id INTEGER NOT NULL, + to_field_name VARCHAR(100) NOT NULL, + relationship_type VARCHAR(20) NOT NULL, -- 'one-to-one', 'one-to-many', 'many-to-one', 'many-to-many' + connection_type VARCHAR(20) NOT NULL, -- 'simple-key', 'data-save', 'external-call' + company_code VARCHAR(50) NOT NULL, + settings JSONB, -- 연결 종류별 세부 설정 + is_active CHAR(1) DEFAULT 'Y', + created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + created_by VARCHAR(50), + updated_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_by VARCHAR(50), + + -- 외래키 제약조건 + CONSTRAINT fk_screen_relationships_from_screen + FOREIGN KEY (from_screen_id) REFERENCES screen_definitions(screen_id), + CONSTRAINT fk_screen_relationships_to_screen + FOREIGN KEY (to_screen_id) REFERENCES screen_definitions(screen_id) +); + +-- 회사 코드 인덱스 +CREATE INDEX idx_screen_relationships_company_code ON screen_relationships(company_code); +``` + +### 2. 중계 테이블 관리 + +```sql +-- 중계 테이블 정의 +CREATE TABLE bridge_tables ( + bridge_id SERIAL PRIMARY KEY, + bridge_name VARCHAR(200) NOT NULL, + table_name VARCHAR(100) NOT NULL, + relationship_id INTEGER NOT NULL, + company_code VARCHAR(50) NOT NULL, + description TEXT, + is_active CHAR(1) DEFAULT 'Y', + created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + created_by VARCHAR(50), + + -- 외래키 제약조건 + CONSTRAINT fk_bridge_tables_relationship + FOREIGN KEY (relationship_id) REFERENCES screen_relationships(relationship_id) +); + +-- 회사 코드 인덱스 +CREATE INDEX idx_bridge_tables_company_code ON bridge_tables(company_code); +``` + +### 3. 외부 호출 설정 + +```sql +-- 외부 호출 설정 +CREATE TABLE external_call_configs ( + config_id SERIAL PRIMARY KEY, + relationship_id INTEGER NOT NULL, + call_type VARCHAR(50) NOT NULL, -- 'rest-api', 'email', 'webhook', 'ftp', 'queue' + parameters JSONB NOT NULL, -- 호출 유형별 파라미터 + is_active CHAR(1) DEFAULT 'Y', + created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + created_by VARCHAR(50), + + -- 외래키 제약조건 + CONSTRAINT fk_external_call_configs_relationship + FOREIGN KEY (relationship_id) REFERENCES screen_relationships(relationship_id) +); +``` + +### 4. 테이블 간 연계 관계 + +``` +screen_definitions (화면 정의) + ↓ (1:N) +screen_relationships (화면 관계) + ↓ (1:N) +bridge_tables (중계 테이블) + ↓ (1:N) +external_call_configs (외부 호출 설정) +``` + +## 🎨 프론트엔드 설계 + +### 1. React Flow 기반 메인 컴포넌트 + +```typescript +// DataFlowDesigner.tsx +import ReactFlow, { + Node, + Edge, + Controls, + Background, + MiniMap, + useNodesState, + useEdgesState, + addEdge, + Connection, + EdgeChange, + NodeChange, +} from "reactflow"; +import "reactflow/dist/style.css"; + +interface DataFlowDesignerProps { + companyCode: string; + onSave?: (relationships: ScreenRelationship[]) => void; +} + +export const DataFlowDesigner: React.FC = ({ + companyCode, + onSave, +}) => { + const [nodes, setNodes, onNodesChange] = useNodesState([]); + const [edges, setEdges, onEdgesChange] = useEdgesState([]); + const [selectedField, setSelectedField] = useState( + null + ); + const [pendingConnection, setPendingConnection] = + useState(null); + + const onConnect = useCallback( + (params: Connection) => { + setEdges((eds) => addEdge(params, eds)); + }, + [setEdges] + ); + + return ( +
+
+ {/* 사이드바 */} +
+ + + +
+ + {/* React Flow 캔버스 */} +
+ + + + + +
+
+ + +
+ ); +}; +``` + +### 2. React Flow 화면 노드 컴포넌트 + +```typescript +// ScreenNode.tsx +import { Handle, Position } from "reactflow"; + +interface ScreenNodeData { + screen: ScreenDefinition; + onFieldClick: (screenId: string, fieldName: string) => void; +} + +export const ScreenNode: React.FC<{ data: ScreenNodeData }> = ({ data }) => { + const { screen, onFieldClick } = data; + + return ( +
+ {/* 노드 헤더 */} +
+
{screen.screenName}
+
{screen.screenCode}
+
테이블: {screen.tableName}
+
+ + {/* 필드 목록 */} +
+
+ 필드 목록 ({screen.fields.length}개) +
+
+ {screen.fields.map((field) => ( +
onFieldClick(screen.screenId, field.name)} + > +
+
{field.name}
+
{field.description}
+
+
+ {field.type} +
+
+ ))} +
+
+ + {/* React Flow 핸들 */} + + +
+ ); +}; + +// 노드 타입 정의 +export const nodeTypes = { + screenNode: ScreenNode, +}; +``` + +### 3. 연결 설정 모달 + +```typescript +// ConnectionSetupModal.tsx +interface ConnectionSetupModalProps { + isOpen: boolean; + connection: PendingConnection | null; + onConfirm: (config: ConnectionConfig) => void; + onCancel: () => void; +} + +export const ConnectionSetupModal: React.FC = ({ + isOpen, + connection, + onConfirm, + onCancel, +}) => { + const [connectionType, setConnectionType] = + useState("simple-key"); + const [relationshipType, setRelationshipType] = + useState("one-to-one"); + const [settings, setSettings] = useState({}); + + return ( + + + + 필드 연결 설정 + + +
+ {/* 연결 정보 표시 */} + + + {/* 관계 타입 선택 */} + + + {/* 연결 종류 선택 */} + + + {/* 연결 종류별 세부 설정 */} + +
+ + + + + +
+
+ ); +}; +``` + +### 4. React Flow 엣지 컴포넌트 + +```typescript +// CustomEdge.tsx +import { + EdgeProps, + getBezierPath, + EdgeLabelRenderer, + BaseEdge, +} from "reactflow"; + +interface CustomEdgeData { + relationshipType: string; + connectionType: string; + label?: string; +} + +export const CustomEdge: React.FC> = ({ + id, + sourceX, + sourceY, + targetX, + targetY, + sourcePosition, + targetPosition, + data, + markerEnd, +}) => { + const [edgePath, labelX, labelY] = getBezierPath({ + sourceX, + sourceY, + sourcePosition, + targetX, + targetY, + targetPosition, + }); + + const getEdgeColor = (connectionType: string) => { + switch (connectionType) { + case "simple-key": + return "#3B82F6"; // 파란색 + case "data-save": + return "#10B981"; // 초록색 + case "external-call": + return "#F59E0B"; // 주황색 + default: + return "#6B7280"; // 회색 + } + }; + + const getEdgeStyle = (connectionType: string) => { + switch (connectionType) { + case "simple-key": + return { strokeWidth: 2, strokeDasharray: "5,5" }; + case "data-save": + return { strokeWidth: 3 }; + case "external-call": + return { strokeWidth: 2, strokeDasharray: "10,5" }; + default: + return { strokeWidth: 2 }; + } + }; + + return ( + <> + + +
+ {data?.label || data?.relationshipType} +
+
+ + ); +}; + +// 엣지 타입 정의 +export const edgeTypes = { + customEdge: CustomEdge, +}; +``` + +## 🌐 API 설계 + +### 1. 화면 관계 관리 API + +```typescript +// 화면 관계 생성 +POST /api/screen-relationships +Body: { + relationshipName: string; + fromScreenId: number; + fromFieldName: string; + toScreenId: number; + toFieldName: string; + relationshipType: 'one-to-one' | 'one-to-many' | 'many-to-one' | 'many-to-many'; + connectionType: 'simple-key' | 'data-save' | 'external-call'; + settings: ConnectionSettings; +} + +// 화면 관계 목록 조회 (회사별) +GET /api/screen-relationships?companyCode=COMP001 + +// 화면 관계 수정 +PUT /api/screen-relationships/:id + +// 화면 관계 삭제 +DELETE /api/screen-relationships/:id + +// 관계 시뮬레이션 +POST /api/screen-relationships/:id/simulate +``` + +### 2. 중계 테이블 관리 API + +```typescript +// 중계 테이블 생성 +POST /api/bridge-tables +Body: { + bridgeName: string; + tableName: string; + relationshipId: number; + description?: string; +} + +// 중계 테이블 목록 조회 +GET /api/bridge-tables?companyCode=COMP001 + +// 중계 테이블 삭제 +DELETE /api/bridge-tables/:id +``` + +### 3. 외부 호출 설정 API + +```typescript +// 외부 호출 설정 생성 +POST /api/external-call-configs +Body: { + relationshipId: number; + callType: 'rest-api' | 'email' | 'webhook' | 'ftp' | 'queue'; + parameters: Record; +} + +// 외부 호출 설정 조회 +GET /api/external-call-configs?relationshipId=123 + +// 외부 호출 설정 수정 +PUT /api/external-call-configs/:id +``` + +## 🎬 사용 시나리오 + +### 1. 기본 관계 설정 + +1. **화면 추가**: 회사별 화면 목록에서 관계를 설정할 화면들을 캔버스에 추가 +2. **필드 선택**: 첫 번째 화면의 필드를 클릭하여 연결 시작 +3. **대상 필드 선택**: 두 번째 화면의 필드를 클릭하여 연결 대상 지정 +4. **관계 설정**: 관계 타입과 연결 종류를 선택하고 세부 설정 구성 +5. **연결 생성**: 설정 완료 후 연결 생성 + +### 2. 복합 데이터 흐름 설계 + +1. **다중 화면 배치**: 관련된 여러 화면을 캔버스에 배치 +2. **다양한 연결 타입**: 단순 키값, 데이터 저장, 외부 호출을 조합 +3. **중계 테이블 활용**: N:N 관계에서 중계 테이블 자동 생성 +4. **시각적 검증**: 연결선과 색상으로 관계 유형 구분 + +### 3. 외부 시스템 연동 + +1. **API 연결**: REST API 호출을 통한 외부 시스템 연동 +2. **이메일 알림**: 데이터 변경 시 이메일 자동 전송 +3. **웹훅 설정**: 실시간 데이터 동기화 +4. **메시지 큐**: 비동기 데이터 처리 + +## 📅 구현 계획 + +### Phase 1: React Flow 기본 설정 (1주) + +- [ ] React Flow 라이브러리 설치 및 설정 +- [ ] 기본 노드와 엣지 컴포넌트 구현 +- [ ] 화면 노드 컴포넌트 구현 +- [ ] 기본 연결선 그리기 + +### Phase 2: 관계 설정 기능 (2주) + +- [ ] 1:1, 1:N 관계 설정 +- [ ] 단순 키값 연결 +- [ ] 연결 설정 모달 +- [ ] 노드 간 드래그앤드롭 연결 + +### Phase 3: 고급 연결 타입 (2-3주) + +- [ ] 데이터 저장 연결 +- [ ] 외부 호출 연결 +- [ ] 중계 테이블 자동 생성 +- [ ] 커스텀 엣지 스타일링 + +### Phase 4: React Flow 고급 기능 (1-2주) + +- [ ] 줌, 팬, 미니맵 기능 +- [ ] 노드 선택 및 다중 선택 +- [ ] 키보드 단축키 지원 +- [ ] 레이아웃 자동 정렬 + +### Phase 5: 시각화 및 관리 (1-2주) + +- [ ] 관계 시뮬레이션 +- [ ] 연결 통계 및 관리 +- [ ] 관계 검증 +- [ ] 데이터 흐름 애니메이션 + +### Phase 6: 고급 기능 (2-3주) + +- [ ] N:N 관계 지원 +- [ ] 복합 데이터 흐름 +- [ ] 외부 시스템 연동 +- [ ] 성능 최적화 + +## 🎯 결론 + +**데이터 흐름 관리 시스템**을 통해 ERP 시스템의 화면들 간 데이터 흐름을 시각적으로 설계하고 관리할 수 있습니다. React Flow 라이브러리를 활용한 직관적인 노드 기반 인터페이스와 회사별 권한 관리, 기존 화면관리 시스템과의 완벽한 연동을 통해 체계적인 데이터 관계 관리가 가능합니다. + +### 주요 가치 + +- **React Flow 기반 시각적 설계**: 복잡한 데이터 관계를 직관적인 노드와 엣지로 설계 +- **인터랙티브 캔버스**: 줌, 팬, 미니맵 등 고급 시각화 기능 제공 +- **회사별 관리**: 각 회사별로 독립적인 관계 관리 +- **다양한 연결 타입**: 업무 요구사항에 맞는 다양한 연결 방식 +- **자동화**: 중계 테이블 자동 생성 및 외부 시스템 연동 +- **확장성**: 새로운 연결 타입과 관계 유형 쉽게 추가 +- **사용자 친화적**: 드래그앤드롭 기반의 직관적인 사용자 인터페이스