# 테이블 간 데이터 관계 설정 시스템 설계 ## 📋 목차 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 table_relationships ( relationship_id SERIAL PRIMARY KEY, relationship_name VARCHAR(200) NOT NULL, from_table_name VARCHAR(100) NOT NULL, from_column_name VARCHAR(100) NOT NULL, to_table_name VARCHAR(100) NOT NULL, to_column_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) ); -- 회사 코드 인덱스 CREATE INDEX idx_table_relationships_company_code ON table_relationships(company_code); -- 테이블명 인덱스 CREATE INDEX idx_table_relationships_from_table ON table_relationships(from_table_name); CREATE INDEX idx_table_relationships_to_table ON table_relationships(to_table_name); ``` ### 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 table_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 table_relationships(relationship_id) ); ``` ### 4. 테이블 간 연계 관계 ``` table_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: TableRelationship[]) => 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 // TableNode.tsx import { Handle, Position } from "reactflow"; interface TableNodeData { table: TableDefinition; onColumnClick: (tableName: string, columnName: string) => void; } export const TableNode: React.FC<{ data: TableNodeData }> = ({ data }) => { const { table, onColumnClick } = data; return (
{/* 노드 헤더 */}
{table.tableName}
테이블
컬럼: {table.columns.length}개
{/* 컬럼 목록 */}
컬럼 목록 ({table.columns.length}개)
{table.columns.map((column) => (
onColumnClick(table.tableName, column.name)} >
{column.name}
{column.description}
{column.type}
))}
{/* React Flow 핸들 */}
); }; // 노드 타입 정의 export const nodeTypes = { tableNode: TableNode, }; ``` ### 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/table-relationships Body: { relationshipName: string; fromTableName: string; fromColumnName: string; toTableName: string; toColumnName: 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/table-relationships?companyCode=COMP001 // 테이블 관계 수정 PUT /api/table-relationships/:id // 테이블 관계 삭제 DELETE /api/table-relationships/:id // 관계 시뮬레이션 POST /api/table-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주) ✅ **완료** - [x] React Flow 라이브러리 설치 및 설정 (@xyflow/react 12.8.4) - [x] 기본 노드와 엣지 컴포넌트 구현 - [x] 테이블 노드 컴포넌트 구현 (TableNode.tsx) - [x] 기본 연결선 그리기 (CustomEdge.tsx) - [x] 메인 데이터 흐름 관리 컴포넌트 구현 (DataFlowDesigner.tsx) - [x] /admin/dataflow 페이지 생성 - [x] 메뉴 시스템 연동 (SQL 스크립트 제공) - [x] 샘플 노드 추가/삭제 기능 - [x] 노드 간 드래그앤드롭 연결 기능 - [x] 줌, 팬, 미니맵 등 React Flow 기본 기능 ### Phase 2: 관계 설정 기능 (2주) - 🚧 **진행 중 (85% 완료)** - [x] 연결 설정 모달 UI 구현 - [x] 1:1, 1:N, N:1, N:N 관계 타입 선택 UI - [x] 단순 키값, 데이터 저장, 외부 호출 연결 종류 UI - [x] 컬럼-to-컬럼 연결 시스템 (클릭 기반) - [x] 선택된 컬럼 정보 표시 및 순서 보장 - [x] 드래그 다중 선택 기능 (부분 터치 선택 지원) - [x] 테이블 기반 시스템으로 전환 (화면 → 테이블) - [x] 코드 정리 및 최적화 (불필요한 props 제거) - [ ] 연결 생성 로직 구현 (모달에서 실제 엣지 생성) - [ ] 생성된 연결의 시각적 표시 (React Flow 엣지) - [ ] 연결 데이터 백엔드 저장 API 연동 - [ ] 기존 연결 수정/삭제 기능 ### Phase 3: 고급 연결 타입 (2-3주) - [ ] 데이터 저장 연결 - [ ] 외부 호출 연결 - [ ] 중계 테이블 자동 생성 - [ ] 커스텀 엣지 스타일링 ### Phase 4: React Flow 고급 기능 (1-2주) - [ ] 줌, 팬, 미니맵 기능 - [ ] 노드 선택 및 다중 선택 - [ ] 키보드 단축키 지원 - [ ] 레이아웃 자동 정렬 ### Phase 5: 시각화 및 관리 (1-2주) - [ ] 관계 시뮬레이션 - [ ] 연결 통계 및 관리 - [ ] 관계 검증 - [ ] 데이터 흐름 애니메이션 ### Phase 6: 고급 기능 (2-3주) - [ ] N:N 관계 지원 - [ ] 복합 데이터 흐름 - [ ] 외부 시스템 연동 - [ ] 성능 최적화 ## 🎯 결론 **테이블 간 데이터 관계 설정 시스템**을 통해 ERP 시스템의 테이블들 간 데이터 관계를 시각적으로 설계하고 관리할 수 있습니다. React Flow 라이브러리를 활용한 직관적인 노드 기반 인터페이스와 회사별 권한 관리, 기존 테이블관리 시스템과의 완벽한 연동을 통해 체계적인 데이터 관계 관리가 가능합니다. ## 📊 구현 현황 ### ✅ Phase 1 완료 (2024-12-19) **구현된 기능:** - React Flow 12.8.4 기반 시각적 캔버스 - 테이블 노드 컴포넌트 (컬럼 정보, 타입별 색상 구분, 노드 리사이징) - 커스텀 엣지 컴포넌트 (관계 타입별 스타일링) - 드래그앤드롭 노드 배치 및 연결 - 줌, 팬, 미니맵 등 고급 시각화 기능 (스크롤 충돌 해결) - 실제 테이블 데이터 연동 (테이블 관리 API 연결) - 컬럼-to-컬럼 연결 시스템 (클릭 기반, 2개 테이블 제한) - 연결 설정 모달 (관계 타입, 연결 종류 선택 UI) - /admin/dataflow 경로 설정 - 메뉴 시스템 연동 완료 - 사용자 경험 개선 (토스트 알림, 선택 순서 보장) **구현된 파일:** - `frontend/components/dataflow/DataFlowDesigner.tsx` - 메인 캔버스 컴포넌트 - `frontend/components/dataflow/TableNode.tsx` - 테이블 노드 컴포넌트 (NodeResizer 포함) - `frontend/components/dataflow/CustomEdge.tsx` - 커스텀 엣지 컴포넌트 - `frontend/components/dataflow/ConnectionSetupModal.tsx` - 연결 설정 모달 - `frontend/app/(main)/admin/dataflow/page.tsx` - 데이터 흐름 관리 페이지 - `frontend/lib/api/dataflow.ts` - 데이터 흐름 API 클라이언트 - `docs/add_dataflow_menu.sql` - 메뉴 추가 스크립트 **주요 개선사항:** 1. **스크롤 충돌 해결**: 노드 내부 스크롤과 React Flow 줌/팬 기능 분리 2. **테이블 기반 시스템**: 화면 기반에서 테이블 기반으로 완전 전환 3. **컬럼-to-컬럼 연결**: 드래그앤드롭 대신 클릭 기반 컬럼 선택 방식 4. **2개 테이블 제한**: 최대 2개 테이블에서만 컬럼 선택 가능 5. **선택 순서 보장**: 사이드바와 모달에서 컬럼 선택 순서 정확히 반영 6. **실제 데이터 연동**: 테이블 관리 시스템의 실제 테이블/컬럼 데이터 사용 7. **사용자 경험**: react-hot-toast를 통한 친화적인 알림 시스템 8. **React 안정성**: 렌더링 중 상태 변경 문제 해결 9. **드래그 다중 선택**: 부분 터치로도 노드 선택 가능한 고급 선택 기능 10. **코드 최적화**: 불필요한 props 및 컴포넌트 제거로 성능 향상 **다음 단계:** Phase 2 - 실제 연결 생성 및 시각적 표시 기능 구현 ### 주요 가치 - **React Flow 기반 시각적 설계**: 복잡한 테이블 관계를 직관적인 노드와 엣지로 설계 - **인터랙티브 캔버스**: 줌, 팬, 미니맵 등 고급 시각화 기능 제공 - **회사별 관리**: 각 회사별로 독립적인 테이블 관계 관리 - **다양한 연결 타입**: 업무 요구사항에 맞는 다양한 연결 방식 - **자동화**: 중계 테이블 자동 생성 및 외부 시스템 연동 - **확장성**: 새로운 연결 타입과 관계 유형 쉽게 추가 - **사용자 친화적**: 드래그앤드롭 기반의 직관적인 사용자 인터페이스