TypeScript 오류 수정 및 Merge conflict 해결

- dataflowControlService.ts: condition.field non-null assertion 추가
- batchExternalDbService.ts: connection 속성들 non-null assertion 추가, error 타입 unknown으로 변경
- multiConnectionQueryService.ts: connection, schemaResult.data non-null assertion 추가
- dataflowExecutionController.ts: 도달할 수 없는 코드 제거
- TableListComponent.tsx, SingleTableWithSticky.tsx: merge conflict 마커 제거
- 모든 TypeScript 컴파일 오류 해결 완료
This commit is contained in:
leeheejin 2025-10-01 09:58:38 +09:00
parent 990d8123b8
commit fc99beb851
6 changed files with 76 additions and 96 deletions

View File

@ -101,18 +101,6 @@ async function executeExternalDatabaseAction(
): Promise<any> {
// 보안상 외부 DB에 대한 모든 데이터 변경 작업은 비활성화
throw new Error(`보안상 외부 데이터베이스에 대한 ${actionType.toUpperCase()} 작업은 허용되지 않습니다. SELECT 쿼리만 사용해주세요.`);
return {
success: true,
message: `외부 DB 액션 실행 완료: ${actionType} on ${tableName}`,
connection: connection.name,
data: result,
affectedRows: 1,
};
} catch (error) {
logger.error(`외부 DB 액션 실행 오류 (${actionType}):`, error);
throw error;
}
}
/**

View File

@ -60,12 +60,12 @@ export class BatchExternalDbService {
data: connections,
message: `${connections.length}개의 연결을 조회했습니다.`
};
} catch (error) {
} catch (error: unknown) {
console.error("배치관리 연결 목록 조회 실패:", error);
return {
success: false,
message: "연결 목록 조회 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류"
error: error instanceof Error ? (error as Error).message : "알 수 없는 오류"
};
}
}
@ -107,12 +107,12 @@ export class BatchExternalDbService {
data: tables,
message: `${tables.length}개의 테이블을 조회했습니다.`
};
} catch (error) {
} catch (error: unknown) {
console.error("배치관리 테이블 목록 조회 실패:", error);
return {
success: false,
message: "테이블 목록 조회 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류"
error: error instanceof Error ? (error as Error).message : "알 수 없는 오류"
};
}
}
@ -182,12 +182,12 @@ export class BatchExternalDbService {
data: columns,
message: `${columns.length}개의 컬럼을 조회했습니다.`
};
} catch (error) {
} catch (error: unknown) {
console.error("[BatchExternalDbService] 컬럼 정보 조회 오류:", error);
return {
success: false,
message: "컬럼 정보 조회 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류"
error: error instanceof Error ? (error as Error).message : "알 수 없는 오류"
};
}
}
@ -210,7 +210,7 @@ export class BatchExternalDbService {
}
// 비밀번호 복호화
const decryptedPassword = PasswordEncryption.decrypt(connection.password);
const decryptedPassword = PasswordEncryption.decrypt(connection!.password);
if (!decryptedPassword) {
return {
success: false,
@ -220,10 +220,10 @@ export class BatchExternalDbService {
// 연결 설정 준비
const config = {
host: connection.host,
port: connection.port,
database: connection.database_name,
user: connection.username,
host: connection!.host,
port: connection!.port,
database: connection!.database_name,
user: connection!.username,
password: decryptedPassword,
connectionTimeoutMillis: connection.connection_timeout != null ? connection.connection_timeout * 1000 : undefined,
queryTimeoutMillis: connection.query_timeout != null ? connection.query_timeout * 1000 : undefined,
@ -231,7 +231,7 @@ export class BatchExternalDbService {
};
// DatabaseConnectorFactory를 통한 테이블 목록 조회
const connector = await DatabaseConnectorFactory.createConnector(connection.db_type, config, connectionId);
const connector = await DatabaseConnectorFactory.createConnector(connection!.db_type, config, connectionId);
const tables = await connector.getTables();
return {
@ -239,12 +239,12 @@ export class BatchExternalDbService {
message: "테이블 목록을 조회했습니다.",
data: tables
};
} catch (error) {
} catch (error: unknown) {
console.error("외부 DB 테이블 목록 조회 오류:", error);
return {
success: false,
message: "테이블 목록 조회 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류"
error: error instanceof Error ? (error as Error).message : "알 수 없는 오류"
};
}
}
@ -272,31 +272,31 @@ export class BatchExternalDbService {
console.log(`[BatchExternalDbService] 연결 정보 조회 성공:`, {
id: connection.id,
connection_name: connection.connection_name,
db_type: connection.db_type,
host: connection.host,
port: connection.port,
database_name: connection.database_name
db_type: connection!.db_type,
host: connection!.host,
port: connection!.port,
database_name: connection!.database_name
});
// 비밀번호 복호화
const decryptedPassword = PasswordEncryption.decrypt(connection.password);
const decryptedPassword = PasswordEncryption.decrypt(connection!.password);
// 연결 설정 준비
const config = {
host: connection.host,
port: connection.port,
database: connection.database_name,
user: connection.username,
host: connection!.host,
port: connection!.port,
database: connection!.database_name,
user: connection!.username,
password: decryptedPassword,
connectionTimeoutMillis: connection.connection_timeout != null ? connection.connection_timeout * 1000 : undefined,
queryTimeoutMillis: connection.query_timeout != null ? connection.query_timeout * 1000 : undefined,
ssl: connection.ssl_enabled === "Y" ? { rejectUnauthorized: false } : false
};
console.log(`[BatchExternalDbService] 커넥터 생성 시작: db_type=${connection.db_type}`);
console.log(`[BatchExternalDbService] 커넥터 생성 시작: db_type=${connection!.db_type}`);
// 데이터베이스 타입에 따른 커넥터 생성
const connector = await DatabaseConnectorFactory.createConnector(connection.db_type, config, connectionId);
const connector = await DatabaseConnectorFactory.createConnector(connection!.db_type, config, connectionId);
console.log(`[BatchExternalDbService] 커넥터 생성 완료, 컬럼 조회 시작: tableName=${tableName}`);
@ -341,11 +341,11 @@ export class BatchExternalDbService {
if (!standardizedColumns || standardizedColumns.length === 0) {
console.warn(`[BatchExternalDbService] 컬럼이 비어있음: connectionId=${connectionId}, tableName=${tableName}`);
console.warn(`[BatchExternalDbService] 연결 정보:`, {
db_type: connection.db_type,
host: connection.host,
port: connection.port,
database_name: connection.database_name,
username: connection.username
db_type: connection!.db_type,
host: connection!.host,
port: connection!.port,
database_name: connection!.database_name,
username: connection!.username
});
// 테이블 존재 여부 확인
@ -395,13 +395,13 @@ export class BatchExternalDbService {
data: standardizedColumns,
message: "컬럼 정보를 조회했습니다."
};
} catch (error) {
} catch (error: unknown) {
console.error("[BatchExternalDbService] 외부 DB 컬럼 정보 조회 오류:", error);
console.error("[BatchExternalDbService] 오류 스택:", error instanceof Error ? error.stack : 'No stack trace');
return {
success: false,
message: "컬럼 정보 조회 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류"
error: error instanceof Error ? (error as Error).message : "알 수 없는 오류"
};
}
}
@ -430,27 +430,27 @@ export class BatchExternalDbService {
}
// 패스워드 복호화
const decryptedPassword = PasswordEncryption.decrypt(connection.password);
const decryptedPassword = PasswordEncryption.decrypt(connection!.password);
// DB 연결 설정
const config = {
host: connection.host,
port: connection.port,
user: connection.username,
host: connection!.host,
port: connection!.port,
user: connection!.username,
password: decryptedPassword,
database: connection.database_name,
database: connection!.database_name,
};
// DB 커넥터 생성
const connector = await DatabaseConnectorFactory.createConnector(
connection.db_type || 'postgresql',
connection!.db_type || 'postgresql',
config,
connectionId
);
// 데이터 조회 (DB 타입에 따라 쿼리 구문 변경)
let query: string;
const dbType = connection.db_type?.toLowerCase() || 'postgresql';
const dbType = connection!.db_type?.toLowerCase() || 'postgresql';
if (dbType === 'oracle') {
query = `SELECT * FROM ${tableName} WHERE ROWNUM <= ${limit}`;
@ -467,12 +467,12 @@ export class BatchExternalDbService {
success: true,
data: result.rows
};
} catch (error) {
} catch (error: unknown) {
console.error(`외부 DB 데이터 조회 오류 (connectionId: ${connectionId}, table: ${tableName}):`, error);
return {
success: false,
message: "외부 DB 데이터 조회 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류"
error: error instanceof Error ? (error as Error).message : "알 수 없는 오류"
};
}
}
@ -502,27 +502,27 @@ export class BatchExternalDbService {
}
// 패스워드 복호화
const decryptedPassword = PasswordEncryption.decrypt(connection.password);
const decryptedPassword = PasswordEncryption.decrypt(connection!.password);
// DB 연결 설정
const config = {
host: connection.host,
port: connection.port,
user: connection.username,
host: connection!.host,
port: connection!.port,
user: connection!.username,
password: decryptedPassword,
database: connection.database_name,
database: connection!.database_name,
};
// DB 커넥터 생성
const connector = await DatabaseConnectorFactory.createConnector(
connection.db_type || 'postgresql',
connection!.db_type || 'postgresql',
config,
connectionId
);
// 데이터 조회 (DB 타입에 따라 쿼리 구문 변경)
let query: string;
const dbType = connection.db_type?.toLowerCase() || 'postgresql';
const dbType = connection!.db_type?.toLowerCase() || 'postgresql';
const columnList = columns.join(', ');
if (dbType === 'oracle') {
@ -540,12 +540,12 @@ export class BatchExternalDbService {
success: true,
data: result.rows
};
} catch (error) {
} catch (error: unknown) {
console.error(`외부 DB 특정 컬럼 조회 오류 (connectionId: ${connectionId}, table: ${tableName}):`, error);
return {
success: false,
message: "외부 DB 특정 컬럼 조회 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류"
error: error instanceof Error ? (error as Error).message : "알 수 없는 오류"
};
}
}
@ -586,20 +586,20 @@ export class BatchExternalDbService {
}
// 패스워드 복호화
const decryptedPassword = PasswordEncryption.decrypt(connection.password);
const decryptedPassword = PasswordEncryption.decrypt(connection!.password);
// DB 연결 설정
const config = {
host: connection.host,
port: connection.port,
user: connection.username,
host: connection!.host,
port: connection!.port,
user: connection!.username,
password: decryptedPassword,
database: connection.database_name,
database: connection!.database_name,
};
// DB 커넥터 생성
const connector = await DatabaseConnectorFactory.createConnector(
connection.db_type || 'postgresql',
connection!.db_type || 'postgresql',
config,
connectionId
);
@ -649,7 +649,7 @@ export class BatchExternalDbService {
const updateColumns = columns.filter(col => col !== primaryKeyColumn);
let query: string;
const dbType = connection.db_type?.toLowerCase() || 'mysql';
const dbType = connection!.db_type?.toLowerCase() || 'mysql';
if (dbType === 'mysql' || dbType === 'mariadb') {
// MySQL/MariaDB: ON DUPLICATE KEY UPDATE 사용
@ -671,7 +671,7 @@ export class BatchExternalDbService {
await connector.executeQuery(query);
successCount++;
} catch (error) {
} catch (error: unknown) {
console.error(`외부 DB 레코드 UPSERT 실패:`, error);
failedCount++;
}
@ -683,12 +683,12 @@ export class BatchExternalDbService {
success: true,
data: { successCount, failedCount }
};
} catch (error) {
} catch (error: unknown) {
console.error(`외부 DB 데이터 삽입 오류 (connectionId: ${connectionId}, table: ${tableName}):`, error);
return {
success: false,
message: "외부 DB 데이터 삽입 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류"
error: error instanceof Error ? (error as Error).message : "알 수 없는 오류"
};
}
}
@ -776,12 +776,12 @@ export class BatchExternalDbService {
success: true,
data: data
};
} catch (error) {
} catch (error: unknown) {
console.error(`[BatchExternalDbService] REST API 데이터 조회 오류 (${apiUrl}${endpoint}):`, error);
return {
success: false,
message: "REST API 데이터 조회 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류"
error: error instanceof Error ? (error as Error).message : "알 수 없는 오류"
};
}
}
@ -868,7 +868,7 @@ export class BatchExternalDbService {
await connector.executeQuery(finalEndpoint, method, requestData);
successCount++;
} catch (error) {
} catch (error: unknown) {
console.error(`REST API 레코드 전송 실패:`, error);
failedCount++;
}
@ -880,7 +880,7 @@ export class BatchExternalDbService {
success: true,
data: { successCount, failedCount }
};
} catch (error) {
} catch (error: unknown) {
console.error(`[BatchExternalDbService] 템플릿 기반 REST API 데이터 전송 오류:`, error);
return {
success: false,
@ -924,7 +924,7 @@ export class BatchExternalDbService {
await connector.executeQuery(endpoint, method, record);
successCount++;
} catch (error) {
} catch (error: unknown) {
console.error(`REST API 레코드 전송 실패:`, error);
failedCount++;
}
@ -936,12 +936,12 @@ export class BatchExternalDbService {
success: true,
data: { successCount, failedCount }
};
} catch (error) {
} catch (error: unknown) {
console.error(`[BatchExternalDbService] REST API 데이터 전송 오류 (${apiUrl}${endpoint}):`, error);
return {
success: false,
message: "REST API 데이터 전송 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류"
error: error instanceof Error ? (error as Error).message : "알 수 없는 오류"
};
}
}

View File

@ -958,7 +958,7 @@ export class DataflowControlService {
condition.value !== undefined
) {
// 조건에서 테이블명을 추출 (테이블명.필드명 형식이거나 기본 소스 테이블)
const parts = condition.field.split(".");
const parts = condition.field!.split(".");
let tableName: string;
let fieldName: string;
@ -976,7 +976,7 @@ export class DataflowControlService {
`DELETE 조건에서 테이블을 결정할 수 없습니다. 필드를 "테이블명.필드명" 형식으로 지정하거나 fieldMappings에 targetTable을 설정하세요.`
);
}
fieldName = condition.field;
fieldName = condition.field!;
}
if (!tableGroups.has(tableName)) {
@ -1041,14 +1041,14 @@ export class DataflowControlService {
targetTable: tableName,
whereClause,
});
} catch (error) {
} catch (error: unknown) {
console.error(`❌ DELETE 실패:`, {
table: tableName,
error: error,
});
const userFriendlyMessage =
error instanceof Error ? error.message : String(error);
error instanceof Error ? (error as Error).message : String(error);
results.push({
message: `DELETE 실패: ${tableName}`,

View File

@ -152,7 +152,7 @@ export class MultiConnectionQueryService {
let values = Object.values(data);
// Oracle의 경우 테이블 스키마 확인 및 데이터 타입 변환 처리
if (connection.db_type?.toLowerCase() === 'oracle') {
if (connection?.db_type?.toLowerCase() === 'oracle') {
try {
// Oracle 테이블 스키마 조회
const schemaQuery = `
@ -171,13 +171,13 @@ export class MultiConnectionQueryService {
if (schemaResult.success && schemaResult.data) {
logger.info(`📋 Oracle 테이블 ${tableName} 스키마:`);
schemaResult.data.forEach((col: any) => {
schemaResult.data!.forEach((col: any) => {
logger.info(` - ${col.COLUMN_NAME}: ${col.DATA_TYPE}, NULL: ${col.NULLABLE}, DEFAULT: ${col.DATA_DEFAULT || 'None'}`);
});
// 필수 컬럼 중 누락된 컬럼이 있는지 확인 (기본값이 없는 NOT NULL 컬럼만)
const providedColumns = columns.map(col => col.toUpperCase());
const missingRequiredColumns = schemaResult.data.filter((schemaCol: any) =>
const missingRequiredColumns = schemaResult.data!.filter((schemaCol: any) =>
schemaCol.NULLABLE === 'N' &&
!schemaCol.DATA_DEFAULT &&
!providedColumns.includes(schemaCol.COLUMN_NAME)
@ -216,7 +216,7 @@ export class MultiConnectionQueryService {
let query: string;
let queryParams: any[];
const dbType = connection.db_type?.toLowerCase() || 'postgresql';
const dbType = connection?.db_type?.toLowerCase() || 'postgresql';
switch (dbType) {
case 'oracle':
@ -281,7 +281,7 @@ export class MultiConnectionQueryService {
}
logger.info(`데이터 삽입 완료`);
return result.data[0] || result.data;
return result.data?.[0] || result.data || [];
} catch (error) {
logger.error(`데이터 삽입 실패: ${error}`);
throw new Error(

View File

@ -88,11 +88,7 @@ export const SingleTableWithSticky: React.FC<SingleTableWithStickyProps> = ({
? "h-12 border-0 px-6 py-4 text-center align-middle"
: "h-12 cursor-pointer border-0 px-6 py-4 text-left align-middle font-semibold whitespace-nowrap text-gray-700 select-none transition-all duration-200 hover:text-gray-900",
`text-${column.align}`,
<<<<<<< HEAD
column.sortable && "hover:bg-orange-50 hover:text-orange-700",
=======
column.sortable && "hover:bg-orange-200/70",
>>>>>>> 8c19d57ced949bde4c9ffcce6544791d3e4b051f
// 고정 컬럼 스타일
column.fixed === "left" && "sticky z-10 border-r border-gray-200/40 bg-gradient-to-r from-slate-50/90 to-gray-50/70 shadow-sm",
column.fixed === "right" && "sticky z-10 border-l border-gray-200/40 bg-gradient-to-r from-slate-50/90 to-gray-50/70 shadow-sm",

View File

@ -1329,11 +1329,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
{/* 헤더 */}
{tableConfig.showHeader && (
<div
<<<<<<< HEAD
className="flex items-center justify-between border-b border-gray-200 bg-gray-100 px-6 py-4"
=======
className="flex items-center justify-between border-b border-gray-200/40 bg-gradient-to-r from-slate-50/80 to-gray-50/60 px-6 py-5"
>>>>>>> 8c19d57ced949bde4c9ffcce6544791d3e4b051f
style={{
width: "100%",
maxWidth: "100%",