# ๐Ÿ”— ์กฐ๊ฑด๋ถ€ ์—ฐ๊ฒฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ๊ณ„ํš ## ๐Ÿ“‹ ํ”„๋กœ์ ํŠธ ๊ฐœ์š” ํ˜„์žฌ DataFlow ์‹œ์Šคํ…œ์—์„œ 3๊ฐ€์ง€ ์—ฐ๊ฒฐ ์ข…๋ฅ˜๋ฅผ ์ง€์›ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์ด ์ค‘ **๋ฐ์ดํ„ฐ ์ €์žฅ**๊ณผ **์™ธ๋ถ€ ํ˜ธ์ถœ** ๊ธฐ๋Šฅ์— ์‹คํ–‰ ์กฐ๊ฑด ๋กœ์ง์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ### ํ˜„์žฌ ์—ฐ๊ฒฐ ์ข…๋ฅ˜ 1. **๋‹จ์ˆœ ํ‚ค๊ฐ’ ์—ฐ๊ฒฐ** - ์กฐ๊ฑด ์„ค์ • ๋ถˆํ•„์š” (๊ธฐ์กด ๋ฐฉ์‹ ์œ ์ง€) 2. **๋ฐ์ดํ„ฐ ์ €์žฅ** - ์‹คํ–‰ ์กฐ๊ฑด ์„ค์ • ํ•„์š” โœจ 3. **์™ธ๋ถ€ ํ˜ธ์ถœ** - ์‹คํ–‰ ์กฐ๊ฑด ์„ค์ • ํ•„์š” โœจ ## ๐ŸŽฏ ๊ธฐ๋Šฅ ์š”๊ตฌ์‚ฌํ•ญ ### ๋ฐ์ดํ„ฐ ์ €์žฅ ๊ธฐ๋Šฅ ``` "from ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ์ด ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋ฉด to ํ…Œ์ด๋ธ”์— ํŠน์ • ์•ก์…˜์„ ์ทจํ•  ๊ฒƒ" ``` **์˜ˆ์‹œ ์‹œ๋‚˜๋ฆฌ์˜ค:** - `work_order` ํ…Œ์ด๋ธ”์˜ `status = 'APPROVED'` ์ด๊ณ  `quantity > 0` ์ผ ๋•Œ - `material_requirement` ํ…Œ์ด๋ธ”์— ์ž์žฌ ์†Œ์š”๋Ÿ‰ ๋ฐ์ดํ„ฐ INSERT ### ์™ธ๋ถ€ ํ˜ธ์ถœ ๊ธฐ๋Šฅ ``` "fromํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ์ด ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋ฉด ์™ธ๋ถ€ apiํ˜ธ์ถœ์ด๋‚˜ ์ด๋ฉ”์ผ ๋ฐœ์†ก ๋“ฑ์˜ ๋™์ž‘์„ ์ทจํ•ด์•ผ ํ•จ" ``` **์˜ˆ์‹œ ์‹œ๋‚˜๋ฆฌ์˜ค:** - `employee_master` ํ…Œ์ด๋ธ”์˜ `employment_status = 'APPROVED'` ์ผ ๋•Œ - ์™ธ๋ถ€ ์ด๋ฉ”์ผ API ํ˜ธ์ถœํ•˜์—ฌ ํ™˜์˜ ๋ฉ”์ผ ๋ฐœ์†ก ## ๐Ÿ—„๏ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ ### 1. ์ปฌ๋Ÿผ ์ถ”๊ฐ€ ```sql -- ๊ธฐ์กด ๋ฐ์ดํ„ฐ ์‚ญ์ œ ํ›„ dataflow_diagrams ํ…Œ์ด๋ธ”์— 3๊ฐœ ์ปฌ๋Ÿผ ์ถ”๊ฐ€ DELETE FROM dataflow_diagrams; -- ๊ธฐ์กด ๋ฐ์ดํ„ฐ ์ „์ฒด ์‚ญ์ œ ALTER TABLE dataflow_diagrams ADD COLUMN control JSONB, -- ์กฐ๊ฑด ์„ค์ • ADD COLUMN category JSONB, -- ์—ฐ๊ฒฐ ์ข…๋ฅ˜ ์„ค์ • ADD COLUMN plan JSONB; -- ์‹คํ–‰ ๊ณ„ํš ์„ค์ • -- ์ธ๋ฑ์Šค ์ถ”๊ฐ€ CREATE INDEX idx_dataflow_control_trigger ON dataflow_diagrams USING GIN ((control->'triggerType')); CREATE INDEX idx_dataflow_category_type ON dataflow_diagrams USING GIN ((category->'type')); ``` ### 2. ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์„ค๊ณ„ #### `control` ์ปฌ๋Ÿผ - ์กฐ๊ฑด ์„ค์ • ```json { "triggerType": "insert", "conditionTree": { "type": "group", "operator": "AND", "children": [ { "type": "condition", "field": "status", "operator": "=", "value": "APPROVED" } ] } } ``` #### `category` ์ปฌ๋Ÿผ - ์—ฐ๊ฒฐ ์ข…๋ฅ˜ ```json { "type": "data-save" // "simple-key" | "data-save" | "external-call" } ``` #### `plan` ์ปฌ๋Ÿผ - ์‹คํ–‰ ๊ณ„ํš ```json { "sourceTable": "work_order", "targetActions": [ { "id": "action_1", "actionType": "insert", "targetTable": "material_requirement", "enabled": true, "fieldMappings": [ { "sourceField": "work_order_id", "targetField": "order_id" } ] } ] } ``` ## ๐ŸŽจ ํ”„๋ก ํŠธ์—”๋“œ UI ๊ฐœ์„  ### ConnectionSetupModal.tsx ์žฌ์„ค๊ณ„ #### ํ˜„์žฌ ๊ตฌ์กฐ ๋ฌธ์ œ์  - ๋ชจ๋“  ์—ฐ๊ฒฐ ์ข…๋ฅ˜์— ๋™์ผํ•œ UI ์ ์šฉ - ์กฐ๊ฑด ์„ค์ • ๊ธฐ๋Šฅ ์—†์Œ - ๋‹จ์ˆœ ํ‚ค๊ฐ’ ์—ฐ๊ฒฐ๊ณผ ์กฐ๊ฑด๋ถ€ ์—ฐ๊ฒฐ์˜ ๊ตฌ๋ถ„ ์—†์Œ #### ๊ฐœ์„  ๋ฐฉ์•ˆ ##### 1. ์—ฐ๊ฒฐ ์ข…๋ฅ˜๋ณ„ UI ๋ถ„๊ธฐ ```tsx // ์—ฐ๊ฒฐ ์ข…๋ฅ˜ ์„ ํƒ ํ›„ ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง { config.connectionType === "simple-key" && ; } { (config.connectionType === "data-save" || config.connectionType === "external-call") && ( ); } ``` ##### 2. ์กฐ๊ฑด ์„ค์ • ์„น์…˜ ์ถ”๊ฐ€ ```tsx // control.html์˜ ์ œ์–ด ์กฐ๊ฑด ์„ค์ • ์„น์…˜์„ ์ฐธ์กฐํ•˜์—ฌ ๊ตฌํ˜„

๐Ÿ“‹ ์‹คํ–‰ ์กฐ๊ฑด ์„ค์ •

``` ##### 3. ์•ก์…˜ ์„ค์ • ์„น์…˜ ```tsx

โšก ์‹คํ–‰ ์•ก์…˜

{config.connectionType === "data-save" && } {config.connectionType === "external-call" && }
``` ### ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ ``` ConnectionSetupModal.tsx โ”œโ”€โ”€ BasicConnectionInfo (๊ณตํ†ต) โ”œโ”€โ”€ ConnectionTypeSelector (๊ณตํ†ต) โ”œโ”€โ”€ SimpleKeyConnectionSettings (๋‹จ์ˆœ ํ‚ค๊ฐ’ ์ „์šฉ) โ””โ”€โ”€ ConditionalConnectionSettings (์กฐ๊ฑด๋ถ€ ์—ฐ๊ฒฐ ์ „์šฉ) โ”œโ”€โ”€ ConditionBuilder (์กฐ๊ฑด ์„ค์ •) โ”œโ”€โ”€ DataSaveActionSettings (๋ฐ์ดํ„ฐ ์ €์žฅ ์•ก์…˜) โ””โ”€โ”€ ExternalCallActionSettings (์™ธ๋ถ€ ํ˜ธ์ถœ ์•ก์…˜) ``` ## โš™๏ธ ๋ฐฑ์—”๋“œ ์„œ๋น„์Šค ๊ตฌํ˜„ ### 1. EventTriggerService ์ƒ์„ฑ ```typescript // backend-node/src/services/eventTriggerService.ts export class EventTriggerService { static async executeEventTriggers( triggerType: "insert" | "update" | "delete", tableName: string, data: Record, companyCode: string ): Promise; static async executeDataSaveAction( action: TargetAction, sourceData: Record ): Promise; static async executeExternalCallAction( action: ExternalCallAction, sourceData: Record ): Promise; } ``` ### 2. DynamicFormService ์—ฐ๋™ ```typescript // ๊ธฐ์กด saveFormData ๋ฉ”์„œ๋“œ์— ํŠธ๋ฆฌ๊ฑฐ ์‹คํ–‰ ์ถ”๊ฐ€ async saveFormData(screenId: number, tableName: string, data: Record) { // ๊ธฐ์กด ์ €์žฅ ๋กœ์ง const result = await this.saveToDatabase(data); // ๐Ÿ”ฅ ์กฐ๊ฑด๋ถ€ ์—ฐ๊ฒฐ ์‹คํ–‰ await EventTriggerService.executeEventTriggers("insert", tableName, data, companyCode); return result; } ``` ### 3. API ์—”๋“œํฌ์ธํŠธ ์ถ”๊ฐ€ ```typescript // backend-node/src/routes/dataflowRoutes.ts router.post("/diagrams/:id/test-conditions", async (req, res) => { // ์กฐ๊ฑด ํ…Œ์ŠคํŠธ ์‹คํ–‰ }); router.post("/diagrams/:id/execute-actions", async (req, res) => { // ์•ก์…˜ ์ˆ˜๋™ ์‹คํ–‰ }); ``` ## ๐Ÿ“ ๊ตฌํ˜„ ๋‹จ๊ณ„๋ณ„ ๊ณ„ํš ### Phase 1: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ค€๋น„ - [ ] dataflow_diagrams ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ ์ถ”๊ฐ€ (๊ธฐ์กด ๋ฐ์ดํ„ฐ ์‚ญ์ œ ํ›„ ์ง„ํ–‰) - [ ] Prisma ์Šคํ‚ค๋งˆ ์—…๋ฐ์ดํŠธ ### Phase 2: ํ”„๋ก ํŠธ์—”๋“œ UI ๊ฐœ์„  - [ ] ConnectionSetupModal.tsx ์žฌ๊ตฌ์กฐํ™” - [ ] ConditionBuilder ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋ฐœ - [ ] ์—ฐ๊ฒฐ ์ข…๋ฅ˜๋ณ„ ์„ค์ • ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ - [ ] control.html ์ฐธ์กฐํ•˜์—ฌ ์กฐ๊ฑด ์„ค์ • UI ๊ตฌํ˜„ ### Phase 3: ๋ฐฑ์—”๋“œ ์„œ๋น„์Šค ๊ฐœ๋ฐœ - [ ] EventTriggerService ๊ธฐ๋ณธ ๊ตฌ์กฐ ์ƒ์„ฑ - [ ] ์กฐ๊ฑด ํ‰๊ฐ€ ์—”์ง„ ๊ตฌํ˜„ - [ ] ๋ฐ์ดํ„ฐ ์ €์žฅ ์•ก์…˜ ์‹คํ–‰ ๋กœ์ง - [ ] DynamicFormService ์—ฐ๋™ ### Phase 4: ์™ธ๋ถ€ ํ˜ธ์ถœ ๊ธฐ๋Šฅ - [ ] ์™ธ๋ถ€ API ํ˜ธ์ถœ ์„œ๋น„์Šค - [ ] ์ด๋ฉ”์ผ ๋ฐœ์†ก ๊ธฐ๋Šฅ - [ ] ์›นํ›… ์ง€์› - [ ] ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๋ฐ ์žฌ์‹œ๋„ ๋กœ์ง ## ๐Ÿ”ง ๊ธฐ์ˆ ์  ๊ณ ๋ ค์‚ฌํ•ญ ### 1. ์„ฑ๋Šฅ ์ตœ์ ํ™” - ์กฐ๊ฑด ํ‰๊ฐ€ ์‹œ ์ธ๋ฑ์Šค ํ™œ์šฉ - ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์‹œ ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ - ๋น„๋™๊ธฐ ์‹คํ–‰์œผ๋กœ ๋ฉ”์ธ ๋กœ์ง ๋ธ”๋กœํ‚น ๋ฐฉ์ง€ ### 2. ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ - ํŠธ๋žœ์žญ์…˜ ๋กค๋ฐฑ ์ง€์› - ๋ถ€๋ถ„ ์‹คํŒจ ์‹œ ๋ณต๊ตฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ### 3. ๋ณด์•ˆ - SQL ์ธ์ ์…˜ ๋ฐฉ์ง€ - ์™ธ๋ถ€ API ํ˜ธ์ถœ ์‹œ ์ธ์ฆ ์ฒ˜๋ฆฌ - ๋ฏผ๊ฐ ๋ฐ์ดํ„ฐ ๋งˆ์Šคํ‚น ### 4. ํ™•์žฅ์„ฑ - ์ƒˆ๋กœ์šด ์•ก์…˜ ํƒ€์ž… ์ถ”๊ฐ€ ์šฉ์ด์„ฑ - ๋ณต์žกํ•œ ์กฐ๊ฑด๋ฌธ ์ง€์› - ๋‹ค์–‘ํ•œ ์™ธ๋ถ€ ์„œ๋น„์Šค ์—ฐ๋™ ## ๐Ÿ“š ์ฐธ๊ณ  ์ž๋ฃŒ - [control.html](../control.html) - ์ œ์–ด ์กฐ๊ฑด ์„ค์ • UI ์ฐธ์กฐ - [ConnectionSetupModal.tsx](../frontend/components/dataflow/ConnectionSetupModal.tsx) - ํ˜„์žฌ ๊ตฌํ˜„ - [ํ™”๋ฉด๊ฐ„*๋ฐ์ดํ„ฐ*๊ด€๊ณ„*์„ค์ •*์‹œ์Šคํ…œ\_์„ค๊ณ„.md](./ํ™”๋ฉด๊ฐ„_๋ฐ์ดํ„ฐ_๊ด€๊ณ„_์„ค์ •_์‹œ์Šคํ…œ_์„ค๊ณ„.md) - ์ „์ฒด ์‹œ์Šคํ…œ ์„ค๊ณ„ ## ๐Ÿš€ ๋‹ค์Œ ๋‹จ๊ณ„ 1. **๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ์—…๋ฐ์ดํŠธ** ๋ถ€ํ„ฐ ์‹œ์ž‘ 2. **UI ์žฌ์„ค๊ณ„** - control.html ์ฐธ์กฐํ•˜์—ฌ ์กฐ๊ฑด ์„ค์ • UI ๊ตฌํ˜„ 3. **๋ฐฑ์—”๋“œ ์„œ๋น„์Šค** ๋‹จ๊ณ„๋ณ„ ๊ตฌํ˜„ 4. **์™ธ๋ถ€ ํ˜ธ์ถœ ๊ธฐ๋Šฅ** ๊ตฌํ˜„ --- _์ด ๋ฌธ์„œ๋Š” ์กฐ๊ฑด๋ถ€ ์—ฐ๊ฒฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„์„ ์œ„ํ•œ ์ „์ฒด์ ์ธ ๋กœ๋“œ๋งต์„ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ๋‹จ๊ณ„๋ณ„๋กœ ์ƒ์„ธํ•œ ๊ตฌํ˜„ ๊ณ„ํš์„ ์ˆ˜๋ฆฝํ•˜์—ฌ ์ง„ํ–‰ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค._