feat: Phase 2.1 - Start ScreenManagementService Raw Query migration (2/46)

1단계 기본 CRUD 전환 시작 (2/6 완료)

 전환 완료 (2개):
1. createScreen() - 화면 생성
   - 중복 확인: findFirst → Raw Query SELECT
   - 생성: create → Raw Query INSERT RETURNING
   - 파라미터 바인딩 적용

2. getScreensByCompany() - 화면 목록 조회 (페이징)
   - 동적 WHERE 절 생성
   - Promise.all로 병렬 조회 (목록 + 총개수)
   - table_labels IN 쿼리 전환

🔧 주요 변경사항:
- Prisma import 제거 → query, transaction import
- 파라미터 바인딩으로 SQL Injection 방지
- COUNT 결과 문자열 → 숫자 변환

📊 진행률:
- 전환 완료: 2/46 (4.3%)
- 남은 작업: 44개 Prisma 호출

🎯 다음 작업:
- getScreenByCode()
- getScreenById()
- updateScreen()
- deleteScreen()

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
kjs 2025-09-30 16:20:09 +09:00
parent ba10e7a12b
commit 95c9811c3b
1 changed files with 62 additions and 39 deletions

View File

@ -1,4 +1,5 @@
import prisma from "../config/database";
// ✅ Prisma → Raw Query 전환 (Phase 2.1)
import { query, transaction } from "../database/db";
import {
ScreenDefinition,
CreateScreenRequest,
@ -39,7 +40,7 @@ export class ScreenManagementService {
// ========================================
/**
*
* ( Raw Query )
*/
async createScreen(
screenData: CreateScreenRequest,
@ -49,75 +50,97 @@ export class ScreenManagementService {
console.log(`요청 데이터:`, screenData);
console.log(`사용자 회사 코드:`, userCompanyCode);
// 화면 코드 중복 확인
const existingScreen = await prisma.screen_definitions.findFirst({
where: {
screen_code: screenData.screenCode,
is_active: { not: "D" }, // 삭제되지 않은 화면만 중복 검사
},
});
// 화면 코드 중복 확인 (Raw Query)
const existingResult = await query<{ screen_id: number }>(
`SELECT screen_id FROM screen_definitions
WHERE screen_code = $1 AND is_active != 'D'
LIMIT 1`,
[screenData.screenCode]
);
console.log(
`화면 코드 '${screenData.screenCode}' 중복 검사 결과:`,
existingScreen ? "중복됨" : "사용 가능"
existingResult.length > 0 ? "중복됨" : "사용 가능"
);
if (existingScreen) {
console.log(`기존 화면 정보:`, existingScreen);
if (existingResult.length > 0) {
console.log(`기존 화면 정보:`, existingResult[0]);
throw new Error("이미 존재하는 화면 코드입니다.");
}
const screen = await prisma.screen_definitions.create({
data: {
screen_name: screenData.screenName,
screen_code: screenData.screenCode,
table_name: screenData.tableName,
company_code: screenData.companyCode,
description: screenData.description,
created_by: screenData.createdBy,
},
});
// 화면 생성 (Raw Query)
const [screen] = await query<any>(
`INSERT INTO screen_definitions (
screen_name, screen_code, table_name, company_code, description, created_by
) VALUES ($1, $2, $3, $4, $5, $6)
RETURNING *`,
[
screenData.screenName,
screenData.screenCode,
screenData.tableName,
screenData.companyCode,
screenData.description || null,
screenData.createdBy,
]
);
return this.mapToScreenDefinition(screen);
}
/**
* ( ) -
* ( ) - ( Raw Query )
*/
async getScreensByCompany(
companyCode: string,
page: number = 1,
size: number = 20
): Promise<PaginatedResponse<ScreenDefinition>> {
const whereClause: any = { is_active: { not: "D" } }; // 삭제된 화면 제외
const offset = (page - 1) * size;
// WHERE 절 동적 생성
const whereConditions: string[] = ["is_active != 'D'"];
const params: any[] = [];
if (companyCode !== "*") {
whereClause.company_code = companyCode;
whereConditions.push(`company_code = $${params.length + 1}`);
params.push(companyCode);
}
const [screens, total] = await Promise.all([
prisma.screen_definitions.findMany({
where: whereClause,
skip: (page - 1) * size,
take: size,
orderBy: { created_date: "desc" },
}),
prisma.screen_definitions.count({ where: whereClause }),
const whereSQL = whereConditions.join(" AND ");
// 페이징 쿼리 (Raw Query)
const [screens, totalResult] = await Promise.all([
query<any>(
`SELECT * FROM screen_definitions
WHERE ${whereSQL}
ORDER BY created_date DESC
LIMIT $${params.length + 1} OFFSET $${params.length + 2}`,
[...params, size, offset]
),
query<{ count: string }>(
`SELECT COUNT(*)::text as count FROM screen_definitions
WHERE ${whereSQL}`,
params
),
]);
// 테이블 라벨 정보를 한 번에 조회
const total = parseInt(totalResult[0]?.count || "0", 10);
// 테이블 라벨 정보를 한 번에 조회 (Raw Query)
const tableNames = [
...new Set(screens.map((s) => s.table_name).filter(Boolean)),
...new Set(screens.map((s: any) => s.table_name).filter(Boolean)),
];
let tableLabelMap = new Map<string, string>();
if (tableNames.length > 0) {
try {
const tableLabels = await prisma.table_labels.findMany({
where: { table_name: { in: tableNames } },
select: { table_name: true, table_label: true },
});
const placeholders = tableNames.map((_, i) => `$${i + 1}`).join(", ");
const tableLabels = await query<{ table_name: string; table_label: string | null }>(
`SELECT table_name, table_label FROM table_labels
WHERE table_name IN (${placeholders})`,
tableNames
);
tableLabelMap = new Map(
tableLabels.map((tl) => [