feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료

외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환:

## 전환 완료 (8개 Prisma 호출)

1. **getConfigs()** - 목록 조회
   - prisma.findMany → query<ExternalCallConfig>()
   - 동적 WHERE 조건 (5개 필터)
   - ILIKE 검색 (config_name, description)

2. **getConfigById()** - 단건 조회
   - prisma.findUnique → queryOne<ExternalCallConfig>()

3-4. **createConfig()** - 생성
   - 중복 검사: prisma.findFirst → queryOne()
   - 생성: prisma.create → queryOne() with INSERT RETURNING
   - JSON 필드 처리: config_data

5-6. **updateConfig()** - 수정
   - 중복 검사: prisma.findFirst → queryOne() with id != $4
   - 수정: prisma.update → queryOne() with 동적 UPDATE
   - 9개 필드에 대한 조건부 SET 절 생성

7. **deleteConfig()** - 논리 삭제
   - prisma.update → query() with is_active = 'N'

8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용
   - prisma.findMany with select → query() with SELECT

## 기술적 개선사항

- **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱
- **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성
- **JSON 필드**: config_data를 JSON.stringify()로 처리
- **ILIKE 검색**: 대소문자 구분 없는 검색 구현
- **중복 검사**: id 제외 조건으로 자신 제외 로직 유지

## 코드 정리

- prisma import 완전 제거
- query, queryOne 함수 사용
- 컴파일 및 린터 오류 없음

문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md
진행률: Phase 3 136/162 (84.0%)
This commit is contained in:
kjs
2025-10-01 12:07:14 +09:00
parent 510c7b2416
commit b4b4c774fb
3 changed files with 202 additions and 107 deletions

View File

@@ -1,4 +1,4 @@
import prisma from "../config/database";
import { query, queryOne } from "../database/db";
import { logger } from "../utils/logger";
// 외부 호출 설정 타입 정의
@@ -34,43 +34,55 @@ export class ExternalCallConfigService {
logger.info("=== 외부 호출 설정 목록 조회 시작 ===");
logger.info(`필터 조건:`, filter);
const where: any = {};
const conditions: string[] = [];
const params: any[] = [];
let paramIndex = 1;
// 회사 코드 필터
if (filter.company_code) {
where.company_code = filter.company_code;
conditions.push(`company_code = $${paramIndex++}`);
params.push(filter.company_code);
}
// 호출 타입 필터
if (filter.call_type) {
where.call_type = filter.call_type;
conditions.push(`call_type = $${paramIndex++}`);
params.push(filter.call_type);
}
// API 타입 필터
if (filter.api_type) {
where.api_type = filter.api_type;
conditions.push(`api_type = $${paramIndex++}`);
params.push(filter.api_type);
}
// 활성화 상태 필터
if (filter.is_active) {
where.is_active = filter.is_active;
conditions.push(`is_active = $${paramIndex++}`);
params.push(filter.is_active);
}
// 검색어 필터 (설정 이름 또는 설명)
if (filter.search) {
where.OR = [
{ config_name: { contains: filter.search, mode: "insensitive" } },
{ description: { contains: filter.search, mode: "insensitive" } },
];
conditions.push(
`(config_name ILIKE $${paramIndex} OR description ILIKE $${paramIndex})`
);
params.push(`%${filter.search}%`);
paramIndex++;
}
const configs = await prisma.external_call_configs.findMany({
where,
orderBy: [{ is_active: "desc" }, { created_date: "desc" }],
});
const whereClause =
conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
const configs = await query<ExternalCallConfig>(
`SELECT * FROM external_call_configs
${whereClause}
ORDER BY is_active DESC, created_date DESC`,
params
);
logger.info(`외부 호출 설정 조회 결과: ${configs.length}`);
return configs as ExternalCallConfig[];
return configs;
} catch (error) {
logger.error("외부 호출 설정 목록 조회 실패:", error);
throw error;
@@ -84,9 +96,10 @@ export class ExternalCallConfigService {
try {
logger.info(`=== 외부 호출 설정 조회: ID ${id} ===`);
const config = await prisma.external_call_configs.findUnique({
where: { id },
});
const config = await queryOne<ExternalCallConfig>(
`SELECT * FROM external_call_configs WHERE id = $1`,
[id]
);
if (config) {
logger.info(`외부 호출 설정 조회 성공: ${config.config_name}`);
@@ -94,7 +107,7 @@ export class ExternalCallConfigService {
logger.warn(`외부 호출 설정을 찾을 수 없음: ID ${id}`);
}
return config as ExternalCallConfig | null;
return config || null;
} catch (error) {
logger.error(`외부 호출 설정 조회 실패 (ID: ${id}):`, error);
throw error;
@@ -115,13 +128,11 @@ export class ExternalCallConfigService {
});
// 중복 이름 검사
const existingConfig = await prisma.external_call_configs.findFirst({
where: {
config_name: data.config_name,
company_code: data.company_code || "*",
is_active: "Y",
},
});
const existingConfig = await queryOne<ExternalCallConfig>(
`SELECT * FROM external_call_configs
WHERE config_name = $1 AND company_code = $2 AND is_active = $3`,
[data.config_name, data.company_code || "*", "Y"]
);
if (existingConfig) {
throw new Error(
@@ -129,24 +140,29 @@ export class ExternalCallConfigService {
);
}
const newConfig = await prisma.external_call_configs.create({
data: {
config_name: data.config_name,
call_type: data.call_type,
api_type: data.api_type,
config_data: data.config_data,
description: data.description,
company_code: data.company_code || "*",
is_active: data.is_active || "Y",
created_by: data.created_by,
updated_by: data.updated_by,
},
});
const newConfig = await queryOne<ExternalCallConfig>(
`INSERT INTO external_call_configs
(config_name, call_type, api_type, config_data, description,
company_code, is_active, created_by, updated_by, created_date, updated_date)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, NOW(), NOW())
RETURNING *`,
[
data.config_name,
data.call_type,
data.api_type,
JSON.stringify(data.config_data),
data.description,
data.company_code || "*",
data.is_active || "Y",
data.created_by,
data.updated_by,
]
);
logger.info(
`외부 호출 설정 생성 완료: ${newConfig.config_name} (ID: ${newConfig.id})`
`외부 호출 설정 생성 완료: ${newConfig!.config_name} (ID: ${newConfig!.id})`
);
return newConfig as ExternalCallConfig;
return newConfig!;
} catch (error) {
logger.error("외부 호출 설정 생성 실패:", error);
throw error;
@@ -171,14 +187,16 @@ export class ExternalCallConfigService {
// 이름 중복 검사 (다른 설정과 중복되는지)
if (data.config_name && data.config_name !== existingConfig.config_name) {
const duplicateConfig = await prisma.external_call_configs.findFirst({
where: {
config_name: data.config_name,
company_code: data.company_code || existingConfig.company_code,
is_active: "Y",
id: { not: id },
},
});
const duplicateConfig = await queryOne<ExternalCallConfig>(
`SELECT * FROM external_call_configs
WHERE config_name = $1 AND company_code = $2 AND is_active = $3 AND id != $4`,
[
data.config_name,
data.company_code || existingConfig.company_code,
"Y",
id,
]
);
if (duplicateConfig) {
throw new Error(
@@ -187,27 +205,58 @@ export class ExternalCallConfigService {
}
}
const updatedConfig = await prisma.external_call_configs.update({
where: { id },
data: {
...(data.config_name && { config_name: data.config_name }),
...(data.call_type && { call_type: data.call_type }),
...(data.api_type !== undefined && { api_type: data.api_type }),
...(data.config_data && { config_data: data.config_data }),
...(data.description !== undefined && {
description: data.description,
}),
...(data.company_code && { company_code: data.company_code }),
...(data.is_active && { is_active: data.is_active }),
...(data.updated_by && { updated_by: data.updated_by }),
updated_date: new Date(),
},
});
// 동적 UPDATE 쿼리 생성
const updateFields: string[] = ["updated_date = NOW()"];
const params: any[] = [];
let paramIndex = 1;
if (data.config_name) {
updateFields.push(`config_name = $${paramIndex++}`);
params.push(data.config_name);
}
if (data.call_type) {
updateFields.push(`call_type = $${paramIndex++}`);
params.push(data.call_type);
}
if (data.api_type !== undefined) {
updateFields.push(`api_type = $${paramIndex++}`);
params.push(data.api_type);
}
if (data.config_data) {
updateFields.push(`config_data = $${paramIndex++}`);
params.push(JSON.stringify(data.config_data));
}
if (data.description !== undefined) {
updateFields.push(`description = $${paramIndex++}`);
params.push(data.description);
}
if (data.company_code) {
updateFields.push(`company_code = $${paramIndex++}`);
params.push(data.company_code);
}
if (data.is_active) {
updateFields.push(`is_active = $${paramIndex++}`);
params.push(data.is_active);
}
if (data.updated_by) {
updateFields.push(`updated_by = $${paramIndex++}`);
params.push(data.updated_by);
}
params.push(id);
const updatedConfig = await queryOne<ExternalCallConfig>(
`UPDATE external_call_configs
SET ${updateFields.join(", ")}
WHERE id = $${paramIndex}
RETURNING *`,
params
);
logger.info(
`외부 호출 설정 수정 완료: ${updatedConfig.config_name} (ID: ${id})`
`외부 호출 설정 수정 완료: ${updatedConfig!.config_name} (ID: ${id})`
);
return updatedConfig as ExternalCallConfig;
return updatedConfig!;
} catch (error) {
logger.error(`외부 호출 설정 수정 실패 (ID: ${id}):`, error);
throw error;
@@ -228,14 +277,12 @@ export class ExternalCallConfigService {
}
// 논리 삭제 (is_active = 'N')
await prisma.external_call_configs.update({
where: { id },
data: {
is_active: "N",
updated_by: deletedBy,
updated_date: new Date(),
},
});
await query(
`UPDATE external_call_configs
SET is_active = $1, updated_by = $2, updated_date = NOW()
WHERE id = $3`,
["N", deletedBy, id]
);
logger.info(
`외부 호출 설정 삭제 완료: ${existingConfig.config_name} (ID: ${id})`
@@ -401,21 +448,18 @@ export class ExternalCallConfigService {
}>
> {
try {
const configs = await prisma.external_call_configs.findMany({
where: {
company_code: companyCode,
is_active: "Y",
},
select: {
id: true,
config_name: true,
description: true,
config_data: true,
},
orderBy: {
config_name: "asc",
},
});
const configs = await query<{
id: number;
config_name: string;
description: string | null;
config_data: any;
}>(
`SELECT id, config_name, description, config_data
FROM external_call_configs
WHERE company_code = $1 AND is_active = $2
ORDER BY config_name ASC`,
[companyCode, "Y"]
);
return configs.map((config) => {
const configData = config.config_data as any;