412 lines
11 KiB
Markdown
412 lines
11 KiB
Markdown
|
|
# 외부 커넥션 관리 시스템 구현 계획서
|
||
|
|
|
||
|
|
## 📋 프로젝트 개요
|
||
|
|
|
||
|
|
### 목적
|
||
|
|
|
||
|
|
- 제어관리 시스템에서 외부 데이터베이스에 접근할 수 있도록 DB 접속 정보를 중앙 관리
|
||
|
|
- 관리자가 외부 DB 연결 설정을 쉽게 등록, 수정, 삭제, 테스트할 수 있는 시스템 구축
|
||
|
|
|
||
|
|
### 주요 기능
|
||
|
|
|
||
|
|
- 외부 DB 접속 정보 CRUD 관리
|
||
|
|
- 다양한 DB 타입 지원 (MySQL, PostgreSQL, Oracle, SQL Server, SQLite)
|
||
|
|
- 연결 테스트 기능
|
||
|
|
- 비밀번호 암호화 저장
|
||
|
|
- 회사별 접속 정보 관리
|
||
|
|
|
||
|
|
## 🗄️ 데이터베이스 설계
|
||
|
|
|
||
|
|
### 테이블: `external_db_connections`
|
||
|
|
|
||
|
|
```sql
|
||
|
|
CREATE TABLE external_db_connections (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
connection_name VARCHAR(100) NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
|
||
|
|
-- DB 연결 정보
|
||
|
|
db_type VARCHAR(20) NOT NULL, -- mysql, postgresql, oracle, mssql, sqlite
|
||
|
|
host VARCHAR(255) NOT NULL,
|
||
|
|
port INTEGER NOT NULL,
|
||
|
|
database_name VARCHAR(100) NOT NULL,
|
||
|
|
username VARCHAR(100) NOT NULL,
|
||
|
|
password TEXT NOT NULL, -- 암호화된 비밀번호
|
||
|
|
|
||
|
|
-- 고급 설정
|
||
|
|
connection_timeout INTEGER DEFAULT 30,
|
||
|
|
query_timeout INTEGER DEFAULT 60,
|
||
|
|
max_connections INTEGER DEFAULT 10,
|
||
|
|
ssl_enabled CHAR(1) DEFAULT 'N',
|
||
|
|
ssl_cert_path VARCHAR(500),
|
||
|
|
connection_options JSONB, -- 추가 연결 옵션
|
||
|
|
|
||
|
|
-- 관리 정보
|
||
|
|
company_code VARCHAR(20) DEFAULT '*',
|
||
|
|
is_active CHAR(1) DEFAULT 'Y',
|
||
|
|
created_date TIMESTAMP DEFAULT NOW(),
|
||
|
|
created_by VARCHAR(50),
|
||
|
|
updated_date TIMESTAMP DEFAULT NOW(),
|
||
|
|
updated_by VARCHAR(50)
|
||
|
|
);
|
||
|
|
|
||
|
|
-- 인덱스
|
||
|
|
CREATE INDEX idx_external_db_connections_company ON external_db_connections(company_code);
|
||
|
|
CREATE INDEX idx_external_db_connections_active ON external_db_connections(is_active);
|
||
|
|
CREATE INDEX idx_external_db_connections_type ON external_db_connections(db_type);
|
||
|
|
```
|
||
|
|
|
||
|
|
### 샘플 데이터
|
||
|
|
|
||
|
|
```sql
|
||
|
|
INSERT INTO external_db_connections (
|
||
|
|
connection_name, description, db_type, host, port,
|
||
|
|
database_name, username, password, company_code
|
||
|
|
) VALUES
|
||
|
|
(
|
||
|
|
'영업팀 MySQL',
|
||
|
|
'영업팀에서 사용하는 고객 데이터베이스',
|
||
|
|
'mysql',
|
||
|
|
'sales-db.company.com',
|
||
|
|
3306,
|
||
|
|
'sales_db',
|
||
|
|
'sales_user',
|
||
|
|
'encrypted_password_here',
|
||
|
|
'COMP001'
|
||
|
|
),
|
||
|
|
(
|
||
|
|
'재무팀 PostgreSQL',
|
||
|
|
'재무 데이터 및 회계 정보',
|
||
|
|
'postgresql',
|
||
|
|
'finance-db.company.com',
|
||
|
|
5432,
|
||
|
|
'finance_db',
|
||
|
|
'finance_user',
|
||
|
|
'encrypted_password_here',
|
||
|
|
'COMP001'
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
## 🔧 백엔드 구현
|
||
|
|
|
||
|
|
### 1. Prisma 모델 정의
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// prisma/schema.prisma
|
||
|
|
model external_db_connections {
|
||
|
|
id Int @id @default(autoincrement())
|
||
|
|
connection_name String @db.VarChar(100)
|
||
|
|
description String? @db.Text
|
||
|
|
db_type String @db.VarChar(20)
|
||
|
|
host String @db.VarChar(255)
|
||
|
|
port Int
|
||
|
|
database_name String @db.VarChar(100)
|
||
|
|
username String @db.VarChar(100)
|
||
|
|
password String @db.Text
|
||
|
|
connection_timeout Int? @default(30)
|
||
|
|
query_timeout Int? @default(60)
|
||
|
|
max_connections Int? @default(10)
|
||
|
|
ssl_enabled String @default("N") @db.Char(1)
|
||
|
|
ssl_cert_path String? @db.VarChar(500)
|
||
|
|
connection_options Json?
|
||
|
|
company_code String @default("*") @db.VarChar(20)
|
||
|
|
is_active String @default("Y") @db.Char(1)
|
||
|
|
created_date DateTime? @default(now()) @db.Timestamp(6)
|
||
|
|
created_by String? @db.VarChar(50)
|
||
|
|
updated_date DateTime? @default(now()) @updatedAt @db.Timestamp(6)
|
||
|
|
updated_by String? @db.VarChar(50)
|
||
|
|
|
||
|
|
@@index([company_code])
|
||
|
|
@@index([is_active])
|
||
|
|
@@index([db_type])
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. 타입 정의
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// backend-node/src/types/externalDbTypes.ts
|
||
|
|
export interface ExternalDbConnection {
|
||
|
|
id?: number;
|
||
|
|
connection_name: string;
|
||
|
|
description?: string;
|
||
|
|
db_type: "mysql" | "postgresql" | "oracle" | "mssql" | "sqlite";
|
||
|
|
host: string;
|
||
|
|
port: number;
|
||
|
|
database_name: string;
|
||
|
|
username: string;
|
||
|
|
password: string;
|
||
|
|
connection_timeout?: number;
|
||
|
|
query_timeout?: number;
|
||
|
|
max_connections?: number;
|
||
|
|
ssl_enabled?: string;
|
||
|
|
ssl_cert_path?: string;
|
||
|
|
connection_options?: Record<string, unknown>;
|
||
|
|
company_code: string;
|
||
|
|
is_active: string;
|
||
|
|
created_date?: Date;
|
||
|
|
created_by?: string;
|
||
|
|
updated_date?: Date;
|
||
|
|
updated_by?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ExternalDbConnectionFilter {
|
||
|
|
db_type?: string;
|
||
|
|
is_active?: string;
|
||
|
|
company_code?: string;
|
||
|
|
search?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ConnectionTestRequest {
|
||
|
|
id?: number;
|
||
|
|
connection_name?: string;
|
||
|
|
db_type: string;
|
||
|
|
host: string;
|
||
|
|
port: number;
|
||
|
|
database_name: string;
|
||
|
|
username: string;
|
||
|
|
password: string;
|
||
|
|
connection_timeout?: number;
|
||
|
|
ssl_enabled?: string;
|
||
|
|
ssl_cert_path?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ConnectionTestResult {
|
||
|
|
success: boolean;
|
||
|
|
message: string;
|
||
|
|
connection_time?: number;
|
||
|
|
server_version?: string;
|
||
|
|
error_details?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export const DB_TYPE_OPTIONS = [
|
||
|
|
{ value: "mysql", label: "MySQL" },
|
||
|
|
{ value: "postgresql", label: "PostgreSQL" },
|
||
|
|
{ value: "oracle", label: "Oracle" },
|
||
|
|
{ value: "mssql", label: "SQL Server" },
|
||
|
|
{ value: "sqlite", label: "SQLite" },
|
||
|
|
];
|
||
|
|
|
||
|
|
export const DB_TYPE_DEFAULTS = {
|
||
|
|
mysql: { port: 3306, driver: "mysql2" },
|
||
|
|
postgresql: { port: 5432, driver: "pg" },
|
||
|
|
oracle: { port: 1521, driver: "oracledb" },
|
||
|
|
mssql: { port: 1433, driver: "mssql" },
|
||
|
|
sqlite: { port: 0, driver: "sqlite3" },
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. 서비스 계층
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// backend-node/src/services/externalDbConnectionService.ts
|
||
|
|
export class ExternalDbConnectionService {
|
||
|
|
// CRUD 메서드들
|
||
|
|
static async getConnections(filter: ExternalDbConnectionFilter);
|
||
|
|
static async getConnectionById(id: number);
|
||
|
|
static async createConnection(data: ExternalDbConnection);
|
||
|
|
static async updateConnection(
|
||
|
|
id: number,
|
||
|
|
data: Partial<ExternalDbConnection>
|
||
|
|
);
|
||
|
|
static async deleteConnection(id: number); // 논리 삭제
|
||
|
|
static async testConnection(connectionData: ConnectionTestRequest);
|
||
|
|
|
||
|
|
// 유틸리티 메서드들
|
||
|
|
private static encryptPassword(password: string): string;
|
||
|
|
private static decryptPassword(encryptedPassword: string): string;
|
||
|
|
private static validateConnectionData(data: ExternalDbConnection): void;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. API 라우트
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// backend-node/src/routes/externalDbConnectionRoutes.ts
|
||
|
|
// GET /api/external-db-connections - 목록 조회
|
||
|
|
// GET /api/external-db-connections/:id - 상세 조회
|
||
|
|
// POST /api/external-db-connections - 새 연결 생성
|
||
|
|
// PUT /api/external-db-connections/:id - 연결 수정
|
||
|
|
// DELETE /api/external-db-connections/:id - 연결 삭제 (논리삭제)
|
||
|
|
// POST /api/external-db-connections/test - 연결 테스트
|
||
|
|
```
|
||
|
|
|
||
|
|
## 🎨 프론트엔드 구현
|
||
|
|
|
||
|
|
### 1. API 클라이언트
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// frontend/lib/api/externalDbConnection.ts
|
||
|
|
export class ExternalDbConnectionAPI {
|
||
|
|
static async getConnections(filter?: ExternalDbConnectionFilter);
|
||
|
|
static async getConnectionById(id: number);
|
||
|
|
static async createConnection(data: ExternalDbConnection);
|
||
|
|
static async updateConnection(
|
||
|
|
id: number,
|
||
|
|
data: Partial<ExternalDbConnection>
|
||
|
|
);
|
||
|
|
static async deleteConnection(id: number);
|
||
|
|
static async testConnection(connectionData: ConnectionTestRequest);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. 메인 페이지
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// frontend/app/(main)/admin/external-connections/page.tsx
|
||
|
|
- 연결 목록 테이블 (리스트형)
|
||
|
|
- 검색 및 필터링 (DB 타입, 상태, 회사)
|
||
|
|
- 새 연결 추가 버튼
|
||
|
|
- 각 행별 편집/삭제/테스트 버튼
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. 연결 설정 모달
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// frontend/components/admin/ExternalDbConnectionModal.tsx
|
||
|
|
- 기본 정보 입력 (연결명, 설명)
|
||
|
|
- DB 연결 정보 (타입, 호스트, 포트, DB명, 계정)
|
||
|
|
- 고급 설정 (타임아웃, SSL 등) - 접기/펼치기
|
||
|
|
- 연결 테스트 버튼
|
||
|
|
- 저장/취소 버튼
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. 연결 테스트 다이얼로그
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// frontend/components/admin/ConnectionTestDialog.tsx
|
||
|
|
- 테스트 진행 상태 표시
|
||
|
|
- 연결 결과 (성공/실패, 응답시간, 서버 버전)
|
||
|
|
- 오류 상세 정보 표시
|
||
|
|
```
|
||
|
|
|
||
|
|
## 🔒 보안 구현
|
||
|
|
|
||
|
|
### 1. 비밀번호 암호화
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// backend-node/src/utils/passwordEncryption.ts
|
||
|
|
export class PasswordEncryption {
|
||
|
|
private static readonly ALGORITHM = "aes-256-gcm";
|
||
|
|
private static readonly SECRET_KEY = process.env.DB_PASSWORD_SECRET;
|
||
|
|
|
||
|
|
static encrypt(password: string): string;
|
||
|
|
static decrypt(encryptedPassword: string): string;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. 환경 변수 설정
|
||
|
|
|
||
|
|
```env
|
||
|
|
# .env
|
||
|
|
DB_PASSWORD_SECRET=your-super-secret-encryption-key-here
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. 접근 권한 제어
|
||
|
|
|
||
|
|
- 관리자 권한만 접근 가능
|
||
|
|
- 회사별 데이터 분리
|
||
|
|
- API 호출 시 인증 토큰 검증
|
||
|
|
|
||
|
|
## 📅 구현 일정
|
||
|
|
|
||
|
|
### Phase 1: 데이터베이스 및 백엔드 (2-3일)
|
||
|
|
|
||
|
|
- [ ] 데이터베이스 테이블 생성
|
||
|
|
- [ ] Prisma 모델 정의
|
||
|
|
- [ ] 타입 정의 작성
|
||
|
|
- [ ] 서비스 계층 구현
|
||
|
|
- [ ] API 라우트 구현
|
||
|
|
- [ ] 비밀번호 암호화 구현
|
||
|
|
|
||
|
|
### Phase 2: 프론트엔드 기본 구현 (2-3일)
|
||
|
|
|
||
|
|
- [ ] API 클라이언트 작성
|
||
|
|
- [ ] 메인 페이지 구현 (리스트)
|
||
|
|
- [ ] 연결 설정 모달 구현
|
||
|
|
- [ ] 기본 CRUD 기능 구현
|
||
|
|
|
||
|
|
### Phase 3: 고급 기능 및 테스트 (1-2일)
|
||
|
|
|
||
|
|
- [ ] 연결 테스트 기능 구현
|
||
|
|
- [ ] 고급 설정 옵션 구현
|
||
|
|
- [ ] 에러 처리 및 검증 강화
|
||
|
|
- [ ] UI/UX 개선
|
||
|
|
|
||
|
|
### Phase 4: 통합 및 배포 (1일)
|
||
|
|
|
||
|
|
- [ ] 메뉴 등록
|
||
|
|
- [ ] 권한 설정
|
||
|
|
- [ ] 전체 테스트
|
||
|
|
- [ ] 문서화 완료
|
||
|
|
|
||
|
|
## 🧪 테스트 계획
|
||
|
|
|
||
|
|
### 1. 단위 테스트
|
||
|
|
|
||
|
|
- 비밀번호 암호화/복호화
|
||
|
|
- 연결 데이터 검증
|
||
|
|
- API 엔드포인트 테스트
|
||
|
|
|
||
|
|
### 2. 통합 테스트
|
||
|
|
|
||
|
|
- 실제 DB 연결 테스트 (다양한 DB 타입)
|
||
|
|
- 프론트엔드-백엔드 연동 테스트
|
||
|
|
- 권한 및 보안 테스트
|
||
|
|
|
||
|
|
### 3. 사용자 테스트
|
||
|
|
|
||
|
|
- 관리자 시나리오 테스트
|
||
|
|
- UI/UX 사용성 테스트
|
||
|
|
- 오류 상황 처리 테스트
|
||
|
|
|
||
|
|
## 🚀 배포 및 운영
|
||
|
|
|
||
|
|
### 1. 환경 설정
|
||
|
|
|
||
|
|
- 프로덕션 환경 암호화 키 설정
|
||
|
|
- DB 접속 권한 최소화
|
||
|
|
- 로그 모니터링 설정
|
||
|
|
|
||
|
|
### 2. 모니터링
|
||
|
|
|
||
|
|
- 외부 DB 연결 상태 모니터링
|
||
|
|
- 연결 풀 사용률 모니터링
|
||
|
|
- 쿼리 성능 모니터링
|
||
|
|
|
||
|
|
### 3. 백업 및 복구
|
||
|
|
|
||
|
|
- 연결 설정 정보 백업
|
||
|
|
- 암호화 키 관리
|
||
|
|
- 장애 복구 절차
|
||
|
|
|
||
|
|
## 📚 참고사항
|
||
|
|
|
||
|
|
### 1. 지원 DB 드라이버
|
||
|
|
|
||
|
|
- MySQL: `mysql2`
|
||
|
|
- PostgreSQL: `pg`
|
||
|
|
- Oracle: `oracledb`
|
||
|
|
- SQL Server: `mssql`
|
||
|
|
- SQLite: `sqlite3`
|
||
|
|
|
||
|
|
### 2. 연결 풀 관리
|
||
|
|
|
||
|
|
- 각 DB별 연결 풀 생성
|
||
|
|
- 최대 연결 수 제한
|
||
|
|
- 유휴 연결 정리
|
||
|
|
|
||
|
|
### 3. 확장 가능성
|
||
|
|
|
||
|
|
- NoSQL DB 지원 (MongoDB, Redis)
|
||
|
|
- API 연결 지원
|
||
|
|
- 파일 시스템 연결 지원
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**작성일**: 2024년 12월 17일
|
||
|
|
**작성자**: AI Assistant
|
||
|
|
**버전**: 1.0
|
||
|
|
|
||
|
|
|