# ๐Ÿ“ Phase 2.4: DynamicFormService Raw Query ์ „ํ™˜ ๊ณ„ํš ## ๐Ÿ“‹ ๊ฐœ์š” DynamicFormService๋Š” **13๊ฐœ์˜ Prisma ํ˜ธ์ถœ**์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„(์•ฝ 11๊ฐœ)์€ `$queryRaw`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด SQL์€ ์ด๋ฏธ ์ž‘์„ฑ๋˜์–ด ์žˆ์ง€๋งŒ, **Prisma ํด๋ผ์ด์–ธํŠธ๋ฅผ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜๋ ค๋ฉด 13๊ฐœ ๋ชจ๋‘๋ฅผ `db.ts`์˜ `query` ํ•จ์ˆ˜๋กœ ๊ต์ฒด**ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ### ๐Ÿ“Š ๊ธฐ๋ณธ ์ •๋ณด | ํ•ญ๋ชฉ | ๋‚ด์šฉ | | --------------- | ------------------------------------------------- | | ํŒŒ์ผ ์œ„์น˜ | `backend-node/src/services/dynamicFormService.ts` | | ํŒŒ์ผ ํฌ๊ธฐ | 1,213 ๋ผ์ธ | | Prisma ํ˜ธ์ถœ | 0๊ฐœ (์ „ํ™˜ ์™„๋ฃŒ) | | **ํ˜„์žฌ ์ง„ํ–‰๋ฅ ** | **13/13 (100%)** โœ… **์™„๋ฃŒ** | | **์ „ํ™˜ ์ƒํƒœ** | **Raw Query๋กœ ์ „ํ™˜ ์™„๋ฃŒ** | | ๋ณต์žก๋„ | ๋‚ฎ์Œ (SQL ์ž‘์„ฑ ์™„๋ฃŒ โ†’ `query()` ํ•จ์ˆ˜๋กœ ๊ต์ฒด ์™„๋ฃŒ) | | ์šฐ์„ ์ˆœ์œ„ | ๐ŸŸข ๋‚ฎ์Œ (Phase 2.4) | | **์ƒํƒœ** | โœ… **์ „ํ™˜ ์™„๋ฃŒ ๋ฐ ์ปดํŒŒ์ผ ์„ฑ๊ณต** | ### ๐ŸŽฏ ์ „ํ™˜ ๋ชฉํ‘œ - โœ… **13๊ฐœ ๋ชจ๋“  Prisma ํ˜ธ์ถœ์„ `db.ts`์˜ `query()` ํ•จ์ˆ˜๋กœ ๊ต์ฒด** - 11๊ฐœ `$queryRaw` โ†’ `query()` ํ•จ์ˆ˜๋กœ ๊ต์ฒด - 2๊ฐœ ORM ๋ฉ”์„œ๋“œ โ†’ `query()` (SQL ์ƒˆ๋กœ ์ž‘์„ฑ) - โœ… ๋ชจ๋“  ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ - โœ… **Prisma import ์™„์ „ ์ œ๊ฑฐ** --- ## ๐Ÿ” Prisma ์‚ฌ์šฉ ํ˜„ํ™ฉ ๋ถ„์„ ### 1. `$queryRaw` / `$queryRawUnsafe` ์‚ฌ์šฉ (11๊ฐœ) **ํ˜„์žฌ ์ƒํƒœ**: SQL์€ ์ด๋ฏธ ์ž‘์„ฑ๋˜์–ด ์žˆ์Œ โœ… **์ „ํ™˜ ์ž‘์—…**: `prisma.$queryRaw` โ†’ `query()` ํ•จ์ˆ˜๋กœ ๊ต์ฒด๋งŒ ํ•˜๋ฉด ๋จ ```typescript // ๊ธฐ์กด await prisma.$queryRaw>`...`; await prisma.$queryRawUnsafe(upsertQuery, ...values); // ์ „ํ™˜ ํ›„ import { query } from "../database/db"; await query>(`...`); await query(upsertQuery, values); ``` ### 2. ORM ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ (2๊ฐœ) **ํ˜„์žฌ ์ƒํƒœ**: Prisma ORM ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ **์ „ํ™˜ ์ž‘์—…**: SQL ์ž‘์„ฑ ํ•„์š” #### 1. dynamic_form_data ์กฐํšŒ (1๊ฐœ) ```typescript // Line 867: ํผ ๋ฐ์ดํ„ฐ ์กฐํšŒ const result = await prisma.dynamic_form_data.findUnique({ where: { id }, select: { data: true }, }); ``` #### 2. screen_layouts ์กฐํšŒ (1๊ฐœ) ```typescript // Line 1101: ํ™”๋ฉด ๋ ˆ์ด์•„์›ƒ ์กฐํšŒ const screenLayouts = await prisma.screen_layouts.findMany({ where: { screen_id: screenId, component_type: "widget", }, select: { component_id: true, properties: true, }, }); ``` --- ## ๐Ÿ“ ์ „ํ™˜ ์˜ˆ์‹œ ### ์˜ˆ์‹œ 1: dynamic_form_data ์กฐํšŒ ์ „ํ™˜ **๊ธฐ์กด Prisma ์ฝ”๋“œ:** ```typescript const result = await prisma.dynamic_form_data.findUnique({ where: { id }, select: { data: true }, }); ``` **์ƒˆ๋กœ์šด Raw Query ์ฝ”๋“œ:** ```typescript import { queryOne } from "../database/db"; const result = await queryOne<{ data: any }>( `SELECT data FROM dynamic_form_data WHERE id = $1`, [id] ); ``` ### ์˜ˆ์‹œ 2: screen_layouts ์กฐํšŒ ์ „ํ™˜ **๊ธฐ์กด Prisma ์ฝ”๋“œ:** ```typescript const screenLayouts = await prisma.screen_layouts.findMany({ where: { screen_id: screenId, component_type: "widget", }, select: { component_id: true, properties: true, }, }); ``` **์ƒˆ๋กœ์šด Raw Query ์ฝ”๋“œ:** ```typescript import { query } from "../database/db"; const screenLayouts = await query<{ component_id: string; properties: any; }>( `SELECT component_id, properties FROM screen_layouts WHERE screen_id = $1 AND component_type = $2`, [screenId, "widget"] ); ``` --- ## ๐Ÿงช ํ…Œ์ŠคํŠธ ๊ณ„ํš ### ๋‹จ์œ„ ํ…Œ์ŠคํŠธ (5๊ฐœ) ```typescript describe("DynamicFormService Raw Query ์ „ํ™˜ ํ…Œ์ŠคํŠธ", () => { describe("getFormDataById", () => { test("ํผ ๋ฐ์ดํ„ฐ ์กฐํšŒ ์„ฑ๊ณต", async () => { ... }); test("์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ", async () => { ... }); }); describe("getScreenLayoutsForControl", () => { test("ํ™”๋ฉด ๋ ˆ์ด์•„์›ƒ ์กฐํšŒ ์„ฑ๊ณต", async () => { ... }); test("widget ํƒ€์ž…๋งŒ ํ•„ํ„ฐ๋ง", async () => { ... }); test("๋นˆ ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ", async () => { ... }); }); }); ``` ### ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ (3๊ฐœ ์‹œ๋‚˜๋ฆฌ์˜ค) ```typescript describe("๋™์  ํผ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ", () => { test("ํผ ๋ฐ์ดํ„ฐ UPSERT โ†’ ์กฐํšŒ", async () => { ... }); test("ํผ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ โ†’ ์กฐํšŒ", async () => { ... }); test("ํ™”๋ฉด ๋ ˆ์ด์•„์›ƒ ์กฐํšŒ โ†’ ์ œ์–ด ์„ค์ • ํ™•์ธ", async () => { ... }); }); ``` --- ## ๐Ÿ“‹ ์ „ํ™˜ ์™„๋ฃŒ ๋‚ด์—ญ ### โœ… ์ „ํ™˜๋œ ํ•จ์ˆ˜๋“ค (13๊ฐœ Raw Query ํ˜ธ์ถœ) 1. **getTableColumnInfo()** - ์ปฌ๋Ÿผ ์ •๋ณด ์กฐํšŒ 2. **getPrimaryKeyColumns()** - ๊ธฐ๋ณธ ํ‚ค ์กฐํšŒ 3. **getNotNullColumns()** - NOT NULL ์ปฌ๋Ÿผ ์กฐํšŒ 4. **upsertFormData()** - UPSERT ์‹คํ–‰ 5. **partialUpdateFormData()** - ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ 6. **updateFormData()** - ์ „์ฒด ์—…๋ฐ์ดํŠธ 7. **deleteFormData()** - ๋ฐ์ดํ„ฐ ์‚ญ์ œ 8. **getFormDataById()** - ํผ ๋ฐ์ดํ„ฐ ์กฐํšŒ 9. **getTableColumns()** - ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ ์กฐํšŒ 10. **getTablePrimaryKeys()** - ๊ธฐ๋ณธ ํ‚ค ์กฐํšŒ 11. **getScreenLayoutsForControl()** - ํ™”๋ฉด ๋ ˆ์ด์•„์›ƒ ์กฐํšŒ ### ๐Ÿ”ง ์ฃผ์š” ๊ธฐ์ˆ ์  ํ•ด๊ฒฐ ์‚ฌํ•ญ 1. **Prisma import ์™„์ „ ์ œ๊ฑฐ**: `import { query, queryOne } from "../database/db"` 2. **๋™์  UPSERT ์ฟผ๋ฆฌ**: PostgreSQL ON CONFLICT ๊ตฌ๋ฌธ ์‚ฌ์šฉ 3. **๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ**: ๋™์  SET ์ ˆ ์ƒ์„ฑ 4. **ํƒ€์ž… ๋ณ€ํ™˜**: PostgreSQL ํƒ€์ž… ์ž๋™ ๋ณ€ํ™˜ ๋กœ์ง ์œ ์ง€ ## ๐Ÿ“‹ ์ฒดํฌ๋ฆฌ์ŠคํŠธ ### 1๋‹จ๊ณ„: ORM ํ˜ธ์ถœ ์ „ํ™˜ โœ… **์™„๋ฃŒ** - [x] `getFormDataById()` - queryOne ์ „ํ™˜ - [x] `getScreenLayoutsForControl()` - query ์ „ํ™˜ - [x] ๋ชจ๋“  Raw Query ํ•จ์ˆ˜ ์ „ํ™˜ ### 2๋‹จ๊ณ„: ํ…Œ์ŠคํŠธ & ๊ฒ€์ฆ โณ **์ง„ํ–‰ ์˜ˆ์ •** - [ ] ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ (5๊ฐœ) - [ ] ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ (3๊ฐœ ์‹œ๋‚˜๋ฆฌ์˜ค) - [x] Prisma import ์™„์ „ ์ œ๊ฑฐ ํ™•์ธ โœ… - [ ] ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ --- ## ๐ŸŽฏ ์™„๋ฃŒ ๊ธฐ์ค€ - [x] **13๊ฐœ ๋ชจ๋“  Prisma ํ˜ธ์ถœ์„ Raw Query๋กœ ์ „ํ™˜ ์™„๋ฃŒ** โœ… - [x] 11๊ฐœ `$queryRaw` โ†’ `query()` ํ•จ์ˆ˜๋กœ ๊ต์ฒด โœ… - [x] 2๊ฐœ ORM ๋ฉ”์„œ๋“œ โ†’ `query()` ํ•จ์ˆ˜๋กœ ์ „ํ™˜ โœ… - [x] **๋ชจ๋“  TypeScript ์ปดํŒŒ์ผ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ** โœ… - [x] **`import prisma` ์™„์ „ ์ œ๊ฑฐ** โœ… - [ ] **๋ชจ๋“  ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ (5๊ฐœ)** โณ - [ ] **๋ชจ๋“  ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ์™„๋ฃŒ (3๊ฐœ ์‹œ๋‚˜๋ฆฌ์˜ค)** โณ - [ ] **์„ฑ๋Šฅ ์ €ํ•˜ ์—†์Œ** โณ --- **์ž‘์„ฑ์ผ**: 2025-09-30 **์™„๋ฃŒ์ผ**: 2025-10-01 **์†Œ์š” ์‹œ๊ฐ„**: ์™„๋ฃŒ๋จ (์ด์ „์— ์ „ํ™˜) **๋‹ด๋‹น์ž**: ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœํŒ€ **์šฐ์„ ์ˆœ์œ„**: ๐ŸŸข ๋‚ฎ์Œ (Phase 2.4) **์ƒํƒœ**: โœ… **์ „ํ™˜ ์™„๋ฃŒ** (ํ…Œ์ŠคํŠธ ํ•„์š”) **ํŠน์ด์‚ฌํ•ญ**: SQL์€ ์ด๋ฏธ ์ž‘์„ฑ๋˜์–ด ์žˆ์—ˆ๊ณ , `query()` ํ•จ์ˆ˜๋กœ ๊ต์ฒด ์™„๋ฃŒ