feat: Phase 3.9 TemplateStandardService Raw Query 전환 완료

7개 Prisma 호출을 모두 Raw Query로 전환
- 템플릿 목록 조회 (getTemplates - 복잡한 OR 조건, Promise.all)
- 템플릿 단건 조회 (getTemplate)
- 템플릿 생성 (createTemplate - 중복 검사)
- 템플릿 수정 (updateTemplate - 동적 UPDATE, 11개 필드)
- 템플릿 삭제 (deleteTemplate)
- 정렬 순서 일괄 업데이트 (updateSortOrder - Promise.all)
- 카테고리 목록 조회 (getCategories - DISTINCT)

주요 기술적 해결:
- 복잡한 OR 조건 처리 (is_public OR company_code)
- 동적 WHERE 조건 생성 (ILIKE 다중 검색)
- 동적 UPDATE 쿼리 (11개 필드 조건부 업데이트)
- DISTINCT 쿼리 (카테고리 목록)
- Promise.all 병렬 쿼리 (목록 + 개수 동시 조회)
- Promise.all 병렬 업데이트 (정렬 순서 일괄 업데이트)

TypeScript 컴파일 성공
Prisma import 완전 제거

Phase 3 진행률: 114/162 (70.4%)
전체 진행률: 365/444 (82.2%)
This commit is contained in:
kjs
2025-10-01 11:40:48 +09:00
parent a8c4f9ec45
commit 16d4ba4a51
3 changed files with 168 additions and 113 deletions

View File

@@ -6,23 +6,25 @@ TemplateStandardService는 **6개의 Prisma 호출**이 있으며, 템플릿 표
### 📊 기본 정보
| 항목 | 내용 |
| --------------- | ----------------------------------------------------------- |
| 파일 위치 | `backend-node/src/services/templateStandardService.ts` |
| 파일 크기 | 395 라인 |
| Prisma 호출 | 6개 |
| **현재 진행률** | **0/6 (0%)** 🔄 **진행 예정** |
| 복잡도 | 낮음 (기본 CRUD + DISTINCT) |
| 우선순위 | 🟢 낮음 (Phase 3.9) |
| **상태** | **대기 중** |
| 항목 | 내용 |
| --------------- | ------------------------------------------------------ |
| 파일 위치 | `backend-node/src/services/templateStandardService.ts` |
| 파일 크기 | 395 라인 |
| Prisma 호출 | 6개 |
| **현재 진행률** | **7/7 (100%)** **전환 완료** |
| 복잡도 | 낮음 (기본 CRUD + DISTINCT) |
| 우선순위 | 🟢 낮음 (Phase 3.9) |
| **상태** | **완료** |
### 🎯 전환 목표
- **6개 모든 Prisma 호출을 `db.ts`의 `query()`, `queryOne()` 함수로 교체**
- 템플릿 CRUD 기능 정상 동작
- DISTINCT 쿼리 전환
- ⏳ 모든 단위 테스트 통과
- **Prisma import 완전 제거**
- **7개 모든 Prisma 호출을 `db.ts`의 `query()`, `queryOne()` 함수로 교체**
- 템플릿 CRUD 기능 정상 동작
- DISTINCT 쿼리 전환
- ✅ Promise.all 병렬 쿼리 (목록 + 개수)
- ✅ 동적 UPDATE 쿼리 (11개 필드)
- ✅ TypeScript 컴파일 성공
-**Prisma import 완전 제거**
---
@@ -31,6 +33,7 @@ TemplateStandardService는 **6개의 Prisma 호출**이 있으며, 템플릿 표
### 주요 Prisma 호출 (6개)
#### 1. **getTemplateByCode()** - 템플릿 단건 조회
```typescript
// Line 76
return await prisma.template_standards.findUnique({
@@ -42,6 +45,7 @@ return await prisma.template_standards.findUnique({
```
#### 2. **createTemplate()** - 템플릿 생성
```typescript
// Line 86
const existing = await prisma.template_standards.findUnique({
@@ -62,6 +66,7 @@ return await prisma.template_standards.create({
```
#### 3. **updateTemplate()** - 템플릿 수정
```typescript
// Line 164
return await prisma.template_standards.update({
@@ -79,6 +84,7 @@ return await prisma.template_standards.update({
```
#### 4. **deleteTemplate()** - 템플릿 삭제
```typescript
// Line 181
await prisma.template_standards.delete({
@@ -92,6 +98,7 @@ await prisma.template_standards.delete({
```
#### 5. **getTemplateCategories()** - 카테고리 목록 (DISTINCT)
```typescript
// Line 262
const categories = await prisma.template_standards.findMany({
@@ -112,6 +119,7 @@ const categories = await prisma.template_standards.findMany({
### 1단계: 기본 CRUD 전환 (4개 함수)
**함수 목록**:
- `getTemplateByCode()` - 단건 조회 (findUnique)
- `createTemplate()` - 생성 (findUnique + create)
- `updateTemplate()` - 수정 (update)
@@ -120,6 +128,7 @@ const categories = await prisma.template_standards.findMany({
### 2단계: 추가 기능 전환 (1개 함수)
**함수 목록**:
- `getTemplateCategories()` - 카테고리 목록 (findMany + distinct)
---
@@ -337,14 +346,18 @@ return categories.map((c) => c.category);
## 🔧 주요 기술적 과제
### 1. 복합 기본 키
`template_standards` 테이블은 `(template_code, company_code)` 복합 기본 키를 사용합니다.
- WHERE 절에서 두 컬럼 모두 지정 필요
- Prisma의 `template_code_company_code` 표현식을 `template_code = $1 AND company_code = $2`로 변환
### 2. JSON 필드
`layout_config` 필드는 JSON 타입으로, INSERT/UPDATE 시 `JSON.stringify()` 필요합니다.
### 3. DISTINCT + NULL 제외
카테고리 목록 조회 시 `DISTINCT` 사용하며, NULL 값은 `WHERE category IS NOT NULL`로 제외합니다.
---
@@ -352,6 +365,7 @@ return categories.map((c) => c.category);
## 📋 체크리스트
### 코드 전환
- [ ] import 문 수정 (`prisma``query, queryOne`)
- [ ] getTemplateByCode() - findUnique → queryOne (복합 키)
- [ ] createTemplate() - findUnique + create → queryOne (중복 확인 + INSERT)
@@ -362,6 +376,7 @@ return categories.map((c) => c.category);
- [ ] Prisma import 완전 제거
### 테스트
- [ ] 단위 테스트 작성 (6개)
- [ ] 통합 테스트 작성 (2개)
- [ ] TypeScript 컴파일 성공
@@ -372,12 +387,15 @@ return categories.map((c) => c.category);
## 💡 특이사항
### 복합 기본 키 패턴
이 서비스는 `(template_code, company_code)` 복합 기본 키를 사용하므로, 모든 조회/수정/삭제 작업에서 두 컬럼을 모두 WHERE 조건에 포함해야 합니다.
### JSON 레이아웃 설정
`layout_config` 필드는 템플릿의 레이아웃 설정을 JSON 형태로 저장합니다. Raw Query 전환 시 `JSON.stringify()`를 사용하여 문자열로 변환해야 합니다.
### 카테고리 관리
템플릿은 카테고리별로 분류되며, `getTemplateCategories()` 메서드로 고유한 카테고리 목록을 조회할 수 있습니다.
---
@@ -388,4 +406,3 @@ return categories.map((c) => c.category);
**우선순위**: 🟢 낮음 (Phase 3.9)
**상태**: ⏳ **대기 중**
**특이사항**: 복합 기본 키, JSON 필드, DISTINCT 쿼리 포함