291 lines
7.2 KiB
Markdown
291 lines
7.2 KiB
Markdown
|
|
# Phase 4: Controller Layer Raw Query 전환 계획
|
||
|
|
|
||
|
|
## 📋 개요
|
||
|
|
|
||
|
|
컨트롤러 레이어에 남아있는 Prisma 호출을 Raw Query로 전환합니다.
|
||
|
|
대부분의 컨트롤러는 Service 레이어를 호출하지만, 일부 컨트롤러에서 직접 Prisma를 사용하고 있습니다.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 📊 기본 정보
|
||
|
|
|
||
|
|
| 항목 | 내용 |
|
||
|
|
| --------------- | --------------------------------------- |
|
||
|
|
| 대상 파일 | 7개 컨트롤러 |
|
||
|
|
| 파일 위치 | `backend-node/src/controllers/` |
|
||
|
|
| Prisma 호출 | 70개 |
|
||
|
|
| **현재 진행률** | **0/70 (0%)** 🔄 **진행 예정** |
|
||
|
|
| 복잡도 | 중간 (대부분 단순 CRUD) |
|
||
|
|
| 우선순위 | 🟡 중간 (Phase 4) |
|
||
|
|
| **상태** | ⏳ **대기 중** |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 전환 대상 컨트롤러
|
||
|
|
|
||
|
|
### 1. adminController.ts (28개)
|
||
|
|
- **라인 수**: 2,571 라인
|
||
|
|
- **Prisma 호출**: 28개
|
||
|
|
- **주요 기능**:
|
||
|
|
- 사용자 관리 (조회, 생성, 수정, 삭제)
|
||
|
|
- 회사 관리 (조회, 생성, 수정, 삭제)
|
||
|
|
- 부서 관리 (조회)
|
||
|
|
- 메뉴 관리 (생성, 수정, 삭제)
|
||
|
|
- 다국어 키 조회
|
||
|
|
- **우선순위**: 🔴 높음
|
||
|
|
|
||
|
|
### 2. webTypeStandardController.ts (11개)
|
||
|
|
- **Prisma 호출**: 11개
|
||
|
|
- **주요 기능**: 웹타입 표준 관리
|
||
|
|
- **우선순위**: 🟡 중간
|
||
|
|
|
||
|
|
### 3. fileController.ts (11개)
|
||
|
|
- **Prisma 호출**: 11개
|
||
|
|
- **주요 기능**: 파일 업로드/다운로드 관리
|
||
|
|
- **우선순위**: 🟡 중간
|
||
|
|
|
||
|
|
### 4. buttonActionStandardController.ts (11개)
|
||
|
|
- **Prisma 호출**: 11개
|
||
|
|
- **주요 기능**: 버튼 액션 표준 관리
|
||
|
|
- **우선순위**: 🟡 중간
|
||
|
|
|
||
|
|
### 5. entityReferenceController.ts (4개)
|
||
|
|
- **Prisma 호출**: 4개
|
||
|
|
- **주요 기능**: 엔티티 참조 관리
|
||
|
|
- **우선순위**: 🟢 낮음
|
||
|
|
|
||
|
|
### 6. dataflowExecutionController.ts (3개)
|
||
|
|
- **Prisma 호출**: 3개
|
||
|
|
- **주요 기능**: 데이터플로우 실행
|
||
|
|
- **우선순위**: 🟢 낮음
|
||
|
|
|
||
|
|
### 7. screenFileController.ts (2개)
|
||
|
|
- **Prisma 호출**: 2개
|
||
|
|
- **주요 기능**: 화면 파일 관리
|
||
|
|
- **우선순위**: 🟢 낮음
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📝 전환 전략
|
||
|
|
|
||
|
|
### 기본 원칙
|
||
|
|
|
||
|
|
1. **Service Layer 우선**
|
||
|
|
- 가능하면 Service로 로직 이동
|
||
|
|
- Controller는 최소한의 로직만 유지
|
||
|
|
|
||
|
|
2. **단순 전환**
|
||
|
|
- 대부분 단순 CRUD → `query`, `queryOne` 사용
|
||
|
|
- 복잡한 로직은 Service로 이동
|
||
|
|
|
||
|
|
3. **에러 처리 유지**
|
||
|
|
- 기존 try-catch 구조 유지
|
||
|
|
- 에러 메시지 일관성 유지
|
||
|
|
|
||
|
|
### 전환 패턴
|
||
|
|
|
||
|
|
#### 1. findMany → query
|
||
|
|
```typescript
|
||
|
|
// Before
|
||
|
|
const users = await prisma.user_info.findMany({
|
||
|
|
where: { company_code: companyCode }
|
||
|
|
});
|
||
|
|
|
||
|
|
// After
|
||
|
|
const users = await query<UserInfo>(
|
||
|
|
`SELECT * FROM user_info WHERE company_code = $1`,
|
||
|
|
[companyCode]
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 2. findUnique → queryOne
|
||
|
|
```typescript
|
||
|
|
// Before
|
||
|
|
const user = await prisma.user_info.findUnique({
|
||
|
|
where: { user_id: userId }
|
||
|
|
});
|
||
|
|
|
||
|
|
// After
|
||
|
|
const user = await queryOne<UserInfo>(
|
||
|
|
`SELECT * FROM user_info WHERE user_id = $1`,
|
||
|
|
[userId]
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 3. create → queryOne with INSERT
|
||
|
|
```typescript
|
||
|
|
// Before
|
||
|
|
const newUser = await prisma.user_info.create({
|
||
|
|
data: userData
|
||
|
|
});
|
||
|
|
|
||
|
|
// After
|
||
|
|
const newUser = await queryOne<UserInfo>(
|
||
|
|
`INSERT INTO user_info (user_id, user_name, ...)
|
||
|
|
VALUES ($1, $2, ...) RETURNING *`,
|
||
|
|
[userData.user_id, userData.user_name, ...]
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 4. update → queryOne with UPDATE
|
||
|
|
```typescript
|
||
|
|
// Before
|
||
|
|
const updated = await prisma.user_info.update({
|
||
|
|
where: { user_id: userId },
|
||
|
|
data: updateData
|
||
|
|
});
|
||
|
|
|
||
|
|
// After
|
||
|
|
const updated = await queryOne<UserInfo>(
|
||
|
|
`UPDATE user_info SET user_name = $1, ...
|
||
|
|
WHERE user_id = $2 RETURNING *`,
|
||
|
|
[updateData.user_name, ..., userId]
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 5. delete → query with DELETE
|
||
|
|
```typescript
|
||
|
|
// Before
|
||
|
|
await prisma.user_info.delete({
|
||
|
|
where: { user_id: userId }
|
||
|
|
});
|
||
|
|
|
||
|
|
// After
|
||
|
|
await query(
|
||
|
|
`DELETE FROM user_info WHERE user_id = $1`,
|
||
|
|
[userId]
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 6. count → queryOne
|
||
|
|
```typescript
|
||
|
|
// Before
|
||
|
|
const count = await prisma.user_info.count({
|
||
|
|
where: { company_code: companyCode }
|
||
|
|
});
|
||
|
|
|
||
|
|
// After
|
||
|
|
const result = await queryOne<{ count: number }>(
|
||
|
|
`SELECT COUNT(*) as count FROM user_info WHERE company_code = $1`,
|
||
|
|
[companyCode]
|
||
|
|
);
|
||
|
|
const count = parseInt(result?.count?.toString() || '0', 10);
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ✅ 체크리스트
|
||
|
|
|
||
|
|
### Phase 4.1: adminController.ts
|
||
|
|
- [ ] Prisma import 제거
|
||
|
|
- [ ] query, queryOne import 추가
|
||
|
|
- [ ] 사용자 관리 함수 전환 (8개)
|
||
|
|
- [ ] getUserList - count + findMany
|
||
|
|
- [ ] getUserInfo - findFirst
|
||
|
|
- [ ] updateUserStatus - update
|
||
|
|
- [ ] deleteUserByAdmin - update
|
||
|
|
- [ ] getMyProfile - findUnique
|
||
|
|
- [ ] updateMyProfile - update
|
||
|
|
- [ ] createOrUpdateUser - upsert
|
||
|
|
- [ ] count (getUserList)
|
||
|
|
- [ ] 회사 관리 함수 전환 (7개)
|
||
|
|
- [ ] getCompanyList - findMany
|
||
|
|
- [ ] createCompany - findFirst (중복체크) + create
|
||
|
|
- [ ] updateCompany - findFirst (중복체크) + update
|
||
|
|
- [ ] deleteCompany - findUnique + delete
|
||
|
|
- [ ] 부서 관리 함수 전환 (2개)
|
||
|
|
- [ ] getDepartmentList - findMany
|
||
|
|
- [ ] findUnique (부서 조회)
|
||
|
|
- [ ] 메뉴 관리 함수 전환 (3개)
|
||
|
|
- [ ] createMenu - create
|
||
|
|
- [ ] updateMenu - update
|
||
|
|
- [ ] deleteMenu - delete
|
||
|
|
- [ ] 기타 함수 전환 (8개)
|
||
|
|
- [ ] getMultiLangKeys - findMany
|
||
|
|
- [ ] 컴파일 확인
|
||
|
|
- [ ] 린터 확인
|
||
|
|
|
||
|
|
### Phase 4.2: webTypeStandardController.ts
|
||
|
|
- [ ] Prisma import 제거
|
||
|
|
- [ ] query, queryOne import 추가
|
||
|
|
- [ ] 모든 함수 전환 (11개)
|
||
|
|
- [ ] 컴파일 확인
|
||
|
|
- [ ] 린터 확인
|
||
|
|
|
||
|
|
### Phase 4.3: fileController.ts
|
||
|
|
- [ ] Prisma import 제거
|
||
|
|
- [ ] query, queryOne import 추가
|
||
|
|
- [ ] 모든 함수 전환 (11개)
|
||
|
|
- [ ] 컴파일 확인
|
||
|
|
- [ ] 린터 확인
|
||
|
|
|
||
|
|
### Phase 4.4: buttonActionStandardController.ts
|
||
|
|
- [ ] Prisma import 제거
|
||
|
|
- [ ] query, queryOne import 추가
|
||
|
|
- [ ] 모든 함수 전환 (11개)
|
||
|
|
- [ ] 컴파일 확인
|
||
|
|
- [ ] 린터 확인
|
||
|
|
|
||
|
|
### Phase 4.5: entityReferenceController.ts
|
||
|
|
- [ ] Prisma import 제거
|
||
|
|
- [ ] query, queryOne import 추가
|
||
|
|
- [ ] 모든 함수 전환 (4개)
|
||
|
|
- [ ] 컴파일 확인
|
||
|
|
- [ ] 린터 확인
|
||
|
|
|
||
|
|
### Phase 4.6: dataflowExecutionController.ts
|
||
|
|
- [ ] Prisma import 제거
|
||
|
|
- [ ] query, queryOne import 추가
|
||
|
|
- [ ] 모든 함수 전환 (3개)
|
||
|
|
- [ ] 컴파일 확인
|
||
|
|
- [ ] 린터 확인
|
||
|
|
|
||
|
|
### Phase 4.7: screenFileController.ts
|
||
|
|
- [ ] Prisma import 제거
|
||
|
|
- [ ] query, queryOne import 추가
|
||
|
|
- [ ] 모든 함수 전환 (2개)
|
||
|
|
- [ ] 컴파일 확인
|
||
|
|
- [ ] 린터 확인
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 예상 결과
|
||
|
|
|
||
|
|
### 코드 품질
|
||
|
|
- ✅ Prisma 의존성 완전 제거
|
||
|
|
- ✅ 직접적인 SQL 제어
|
||
|
|
- ✅ 타입 안전성 유지
|
||
|
|
|
||
|
|
### 성능
|
||
|
|
- ✅ 불필요한 ORM 오버헤드 제거
|
||
|
|
- ✅ 쿼리 최적화 가능
|
||
|
|
|
||
|
|
### 유지보수성
|
||
|
|
- ✅ 명확한 SQL 쿼리
|
||
|
|
- ✅ 디버깅 용이
|
||
|
|
- ✅ 데이터베이스 마이그레이션 용이
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📌 참고사항
|
||
|
|
|
||
|
|
### Import 변경
|
||
|
|
```typescript
|
||
|
|
// Before
|
||
|
|
import { PrismaClient } from "@prisma/client";
|
||
|
|
const prisma = new PrismaClient();
|
||
|
|
|
||
|
|
// After
|
||
|
|
import { query, queryOne } from "../database/db";
|
||
|
|
```
|
||
|
|
|
||
|
|
### 타입 정의
|
||
|
|
- 각 테이블의 타입은 `types/` 디렉토리에서 import
|
||
|
|
- 필요시 새로운 타입 정의 추가
|
||
|
|
|
||
|
|
### 에러 처리
|
||
|
|
- 기존 try-catch 구조 유지
|
||
|
|
- 적절한 HTTP 상태 코드 반환
|
||
|
|
- 사용자 친화적 에러 메시지
|
||
|
|
|