문제:
- Oracle DB에 INSERT 해도 데이터가 실제로 저장되지 않음
- executeQuery에서 autoCommit 옵션이 없었음
수정:
1. 쿼리 타입 확인 (INSERT/UPDATE/DELETE/MERGE)
2. DML 쿼리는 autoCommit: true 설정 ✅
3. SELECT 쿼리는 autoCommit: false (기본값)
로깅 추가:
- isDML 확인
- autoCommit 상태
- rowsAffected 추가
결과:
- ✅ INSERT 실행 후 자동 COMMIT
- ✅ UPDATE/DELETE도 자동 COMMIT
- ✅ SELECT는 영향 없음
- ✅ 오라클 데이터 정상 저장
문제:
- UPDATE 액션 실행 시 ID 필요 에러
- executeUpdate가 하드코딩된 id 필드만 찾음
- 실제 테이블 기본키는 다를 수 있음
해결:
1. 테이블 기본키 동적 조회
2. 기본키 값 동적 추출
3. 동적 UPDATE 쿼리 생성
4. 상세 로깅 추가
결과:
- 모든 테이블의 UPDATE 동작
- 동적 기본키 처리
문제:
- query() 함수에 스프레드 연산자로 파라미터 전달
- pg 라이브러리는 배열을 요구함
- 'Query values must be an array' 에러 발생
수정:
tableManagementService.ts (2곳):
- line 1501: query(...searchValues) → query(searchValues)
- line 1512: query(...searchValues, size, offset)
→ query([...searchValues, size, offset])
결과:
- ✅ 쿼리 파라미터 배열로 정확히 전달
- ✅ 테이블 데이터 조회 정상 동작
변경된 파일:
1. DOCKER.md:
- 기술 스택: Prisma → PostgreSQL (Raw Query)
- Prisma 관련 섹션 제거
- 데이터베이스 관련 섹션으로 교체
- 프로젝트 구조: prisma/ → database/
2. backend-node/Dockerfile.win:
- npx prisma generate 명령 제거
- Prisma 클라이언트 생성 단계 삭제
3. backend-node/README.md:
- ORM: Prisma → Database: PostgreSQL (Raw Query with pg)
- 프로젝트 구조: prisma/ → database/
- Prisma 클라이언트 생성 단계 제거
- npx prisma studio 스크립트 제거
- 데이터베이스 스키마 변경 가이드 업데이트
- Phase 1 체크리스트: Prisma → Raw Query
문서 정리 완료:
- ✅ Docker 가이드 업데이트
- ✅ Dockerfile Prisma 명령 제거
- ✅ README 기술 스택 업데이트
- ✅ 개발 가이드 Raw Query로 변경
최종 작업:
1. config/database.ts 삭제:
- Prisma 기반 database.ts 완전 제거
- 더 이상 사용되지 않는 파일
2. referenceCacheService.ts 전환 (3개):
- ✅ getTableRowCount: $queryRawUnsafe → query
- ✅ cacheReferenceTable: $queryRawUnsafe → query
- ✅ batchLookup: $queryRaw → query (ANY 연산자)
전체 완료:
- ✅ 모든 Prisma 호출 전환 완료
- ✅ PrismaClient import 완전 제거 (에러핸들러 제외)
- ✅ database.ts 삭제
- ✅ Raw Query 기반 시스템으로 완전 전환
최종 진행률: 54/54 (100%) 🎉
문제:
- 로컬 변수 'query'와 import한 함수 'query'가 충돌
- TypeScript 에러: 'query' is used before being assigned
해결:
- 로컬 변수 'query'를 'sql'로 변경
- SELECT 쿼리 문자열 변수명 통일 (query → sql)
영향:
- executeMainDbOperation의 select case만 수정
- insert, update, delete는 이미 고유한 변수명 사용
문제:
- pool이 null일 수 있다는 TypeScript 에러 발생
- pool.connect()를 직접 사용하는 것은 안전하지 않음
해결:
- pool import를 transaction으로 변경
- 수동 트랜잭션 관리 코드를 transaction 함수로 교체
- BEGIN/COMMIT/ROLLBACK 자동 처리
- 파라미터 개수 최적화 (updated_date를 NOW()로 변경)
장점:
- 타입 안전성 향상
- 에러 처리 자동화
- 코드 간소화
문제:
- buttonActionStandardController에서 pool을 import하려 했으나
- db.ts에서 pool이 export되지 않아 컴파일 에러 발생
해결:
- db.ts에 'export { pool }' 추가
- pool 직접 접근이 필요한 경우를 위해 명시적 export
영향받는 파일:
- backend-node/src/database/db.ts
- backend-node/src/controllers/buttonActionStandardController.ts (사용)
현재 상황 분석 및 문서화:
컨트롤러 레이어:
- ✅ adminController.ts (28개) 완료
- ✅ screenFileController.ts (2개) 완료
- 🔄 남은 파일 (12개 호출):
* webTypeStandardController.ts (11개)
* fileController.ts (1개)
Routes & Services:
- ddlRoutes.ts (2개)
- companyManagementRoutes.ts (2개)
- multiConnectionQueryService.ts (4개)
Config:
- database.ts (4개 - 제거 예정)
새로운 계획서:
- PHASE4_REMAINING_PRISMA_CALLS.md (상세 전환 계획)
- 파일별 Prisma 호출 상세 분석
- 전환 패턴 및 우선순위 정리
전체 진행률: 445/444 (100.2%)
남은 작업: 12개 (추가 조사 필요한 파일 제외)
batch_mappings 테이블의 실제 컬럼명으로 수정:
- field_name → from_column_name, to_column_name
- source_field → from_table_name, to_table_name
- 전체 컬럼 구조를 실제 DB 스키마에 맞게 수정
수정된 함수:
- loadActiveBatchConfigs()
- updateBatchSchedule()
에러 해결: column bm.field_name does not exist
4개 서비스 18개 Prisma 호출 전환 완료:
1. **EnhancedDynamicFormService** (6개)
- validateTableExists - information_schema 조회
- getTableColumns - 테이블 컬럼 정보 조회 with 캐싱
- getColumnWebTypes - 웹타입 정보 조회
- getPrimaryKeys - Primary Key 조회
- performInsert - 동적 INSERT with RETURNING
- performUpdate - 동적 UPDATE with RETURNING
2. **DataMappingService** (5개)
- getSourceData - 소스 테이블 데이터 조회
- executeInsert - 동적 INSERT
- executeUpsert - ON CONFLICT DO UPDATE
- executeUpdate - 동적 UPDATE
- disconnect - 제거 (Raw Query 불필요)
3. **DataService** (4개)
- getTableData - 동적 SELECT with 동적 WHERE/ORDER BY
- checkTableExists - information_schema 테이블 존재 확인
- getTableColumnsSimple - 컬럼 정보 조회
- getColumnLabel - 컬럼 라벨 조회
4. **AdminService** (3개)
- getAdminMenuList - WITH RECURSIVE 쿼리
- getUserMenuList - WITH RECURSIVE 쿼리
- getMenuInfo - LEFT JOIN으로 회사 정보 포함
기술적 성과:
- 변수명 충돌 해결 (query vs sql)
- WITH RECURSIVE 쿼리 전환
- Prisma include → LEFT JOIN 전환
- 동적 쿼리 생성 (WHERE, ORDER BY)
- SQL 인젝션 방지 (컬럼명 검증)
진행률: Phase 3 173/186 (93.0%)
문서: PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md
엔티티 조인 관계 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환
전환 완료: 5개 Prisma 호출
1. detectEntityJoins - 엔티티 컬럼 감지
- column_labels.findMany to query
- web_type = entity 필터
2-3. validateJoinConfig - 테이블/컬럼 존재 확인
- queryRaw to query
- information_schema 조회
4-5. getReferenceTableColumns - 컬럼 정보/라벨 조회
- queryRaw, findMany to query
- 문자열 타입 컬럼 필터링
기술적 개선사항:
- information_schema 쿼리 파라미터 바인딩
- IS NOT NULL 조건 변환
- 타입 안전성 강화
문서: PHASE3.13_ENTITY_JOIN_SERVICE_MIGRATION.md
진행률: Phase 3 141/162 (87.0%)
외부 호출 설정 관리 서비스의 모든 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%)
## 백엔드
- DashboardController: 대시보드 CRUD 및 쿼리 실행 API
- DashboardService: 비즈니스 로직 처리
- PostgreSQL 연동 및 데이터 관리
## 프론트엔드
- DashboardDesigner: 캔버스 기반 대시보드 디자이너
- QueryEditor: SQL 쿼리 편집 및 미리보기
- ChartRenderer: 다양한 차트 타입 지원 (Bar, Line, Area, Donut, Stacked, Combo)
- DashboardViewer: 실시간 데이터 반영 뷰어
## 개선사항
- 콘솔 로그 프로덕션 준비 (주석 처리)
- 차트 컴포넌트 확장 (6가지 타입)
- 실시간 쿼리 실행 및 데이터 바인딩
DDL 감사 로깅 서비스의 모든 Prisma 호출을 Raw Query로 전환:
## 전환 완료 (8개 Prisma 호출)
1. **logDDLExecution()** - DDL 실행 로그 INSERT
- prisma.$executeRaw → query()
- 7개 파라미터로 로그 기록
2. **getAuditLogs()** - 감사 로그 목록 조회
- prisma.$queryRawUnsafe → query<any>()
- 동적 WHERE 조건 생성
- 페이징 (LIMIT)
3. **getDDLStatistics()** - 통계 조회 (4개 쿼리)
- totalStats: CASE WHEN 집계로 성공/실패 통계
- ddlTypeStats: GROUP BY로 DDL 타입별 통계
- userStats: GROUP BY로 사용자별 통계
- recentFailures: 최근 실패 로그 조회
4. **getTableDDLHistory()** - 테이블 히스토리
- prisma.$queryRawUnsafe → query<any>()
- table_name 필터링
5. **cleanupOldLogs()** - 오래된 로그 삭제
- prisma.$executeRaw → query()
- 날짜 기반 DELETE
## 기술적 개선사항
- PostgreSQL $1, $2 파라미터 바인딩으로 통일
- 동적 WHERE 조건 생성 로직 유지
- 복잡한 집계 쿼리 (CASE WHEN, GROUP BY, SUM) 완벽 전환
- 기존 에러 처리 및 로깅 구조 유지
- TypeScript 타입 안전성 확보
## 코드 정리
- PrismaClient import 제거
- query, queryOne 함수 사용
- 컴파일 및 린터 오류 없음
문서: PHASE3.11_DDL_AUDIT_LOGGER_MIGRATION.md
진행률: Phase 3 128/162 (79.0%)
6개 Prisma 호출을 모두 Raw Query로 전환
- JSON 필드 검색 (JSONB 연산자 활용)
- 동적 INSERT 쿼리 (PostgreSQL 플레이스홀더)
- 동적 UPDATE 쿼리 (WHERE 조건 + 플레이스홀더)
- 동적 DELETE 쿼리 (WHERE 조건)
- UPSERT 쿼리 (ON CONFLICT)
- 다이어그램 단건 조회 (findUnique → queryOne)
주요 기술적 해결:
- JSON 필드 검색 ($queryRaw → query)
- category::text = '"data-save"'
- category::jsonb ? 'data-save'
- category::jsonb @> '["data-save"]'
- MySQL 플레이스홀더(?) → PostgreSQL 플레이스홀더($1, $2, ...)
- 동적 테이블 INSERT/UPDATE/DELETE (보안 강화)
- ON CONFLICT를 사용한 UPSERT
- 조건부 실행 로직 유지
TypeScript 컴파일 성공
Prisma import 완전 제거
Phase 3 진행률: 120/162 (74.1%)
전체 진행률: 371/444 (83.6%)
7개 Prisma 호출을 모두 Raw Query로 전환
- 템플릿 목록 조회 (getTemplates - 복잡한 OR 조건, Promise.all)
- 템플릿 단건 조회 (getTemplate)
- 템플릿 생성 (createTemplate - 중복 검사)
- 템플릿 수정 (updateTemplate - 동적 UPDATE, 11개 필드)
- 템플릿 삭제 (deleteTemplate)
- 정렬 순서 일괄 업데이트 (updateSortOrder - Promise.all)
- 카테고리 목록 조회 (getCategories - DISTINCT)
주요 기술적 해결:
- 복잡한 OR 조건 처리 (is_public OR company_code)
- 동적 WHERE 조건 생성 (ILIKE 다중 검색)
- 동적 UPDATE 쿼리 (11개 필드 조건부 업데이트)
- DISTINCT 쿼리 (카테고리 목록)
- Promise.all 병렬 쿼리 (목록 + 개수 동시 조회)
- Promise.all 병렬 업데이트 (정렬 순서 일괄 업데이트)
TypeScript 컴파일 성공
Prisma import 완전 제거
Phase 3 진행률: 114/162 (70.4%)
전체 진행률: 365/444 (82.2%)
10개 Prisma 호출을 모두 Raw Query로 전환
- 카테고리 목록 조회 (getAllCategories)
- 카테고리 단건 조회 (getCategoryByTypeCode)
- 카테고리 생성 (createCategory - 중복 검사)
- 카테고리 수정 (updateCategory - 동적 UPDATE)
- 카테고리 삭제 (deleteCategory - 연결 확인 후 비활성화)
- 연결 통계 조회 (getConnectionStatsByType - LEFT JOIN + GROUP BY)
- 기본 카테고리 초기화 (initializeDefaultCategories - UPSERT)
주요 기술적 해결:
- ApiResponse 래퍼 패턴 유지
- 동적 UPDATE 쿼리 (5개 필드 조건부 업데이트)
- ON CONFLICT를 사용한 UPSERT (기본 카테고리 초기화)
- 연결 확인 (external_db_connections COUNT)
- LEFT JOIN + GROUP BY 통계 쿼리 최적화 (타입별 연결 수)
- 중복 검사 (카테고리 생성 시)
- try-catch 에러 처리 및 ApiResponse 반환
TypeScript 컴파일 성공
Prisma import 완전 제거
Phase 3 진행률: 107/162 (66.0%)
전체 진행률: 358/444 (80.6%)
10개 Prisma 호출을 모두 Raw Query로 전환
- 레이아웃 목록 조회 (getLayouts - 복잡한 OR 조건, Promise.all)
- 레이아웃 단건 조회 (getLayoutById - OR 조건)
- 레이아웃 생성 (createLayout - JSON 필드)
- 레이아웃 수정 (updateLayout - 동적 UPDATE, 10개 필드)
- 레이아웃 삭제 (deleteLayout - Soft Delete)
- 레이아웃 복제 (duplicateLayout - 기존 함수 재사용)
- 카테고리별 통계 (getLayoutCountsByCategory - GROUP BY)
- 코드 자동 생성 (generateLayoutCode - LIKE 검색)
주요 기술적 해결:
- 복잡한 OR 조건 처리 (company_code OR is_public)
- 동적 WHERE 조건 생성 (ILIKE 다중 검색)
- 동적 UPDATE 쿼리 (10개 필드 조건부 업데이트)
- JSON 필드 처리 (default_size, layout_config, zones_config)
- GROUP BY 통계 쿼리 (카테고리별 개수)
- LIKE 검색 (코드 생성 시 패턴 검색)
- Promise.all 병렬 쿼리 (목록 + 개수 동시 조회)
- safeJSONStringify 헬퍼 함수 활용
TypeScript 컴파일 성공
Prisma import 완전 제거
Phase 3 진행률: 97/162 (59.9%)
전체 진행률: 348/444 (78.4%)
CollectionService 전환 완료:
- 11개 Prisma 호출을 모두 Raw Query로 전환
- 수집 설정 CRUD (getCollectionConfigs, getCollectionConfigById, createCollectionConfig, updateCollectionConfig, deleteCollectionConfig)
- 수집 작업 관리 (executeCollection, getCollectionJobs, getCollectionHistory)
- 동적 WHERE 조건 생성 (ILIKE 검색, OR 조건)
- 동적 UPDATE 쿼리 (변경된 필드만 업데이트)
- JSON 필드 처리 (collection_options)
- LEFT JOIN (작업 목록 조회 시 설정 정보 포함)
- 비동기 작업 처리 (setTimeout 내 query 사용)
- 필드명 수정 (schedule_expression → schedule_cron)
- TypeScript 컴파일 성공
- Prisma import 완전 제거
Phase 3 남은 서비스 계획서 작성:
- PHASE3.7_LAYOUT_SERVICE_MIGRATION.md (10개 호출)
- 레이아웃 표준 관리 (CRUD, 통계, JSON 필드)
- PHASE3.8_DB_TYPE_CATEGORY_SERVICE_MIGRATION.md (10개 호출)
- DB 타입 카테고리 관리 (CRUD, 통계, UPSERT)
- PHASE3.9_TEMPLATE_STANDARD_SERVICE_MIGRATION.md (6개 호출)
- 템플릿 표준 관리 (복합 키, JSON 필드, DISTINCT)
Phase 3 진행률: 87/162 (53.7%)
전체 진행률: 338/444 (76.1%)
12개 Prisma 호출을 모두 Raw Query로 전환
- 관계도 목록 조회 (getDataflowDiagrams - 페이지네이션, ILIKE 검색)
- 관계도 단건 조회 (getDataflowDiagramById - 동적 WHERE)
- 관계도 생성 (createDataflowDiagram - JSON 필드)
- 관계도 수정 (updateDataflowDiagram - 동적 UPDATE, JSON 필드)
- 관계도 삭제 (deleteDataflowDiagram)
- 관계도 복제 (copyDataflowDiagram - LIKE 검색, 번호 증가)
- 버튼 제어용 조회 (getAllRelationshipsForButtonControl)
주요 기술적 해결:
- 동적 WHERE 조건 생성 (company_code 필터링)
- 동적 UPDATE 쿼리 (변경된 필드만 업데이트)
- JSON 필드 처리 (relationships, node_positions, control, category, plan)
- LIKE 검색 (복제 시 이름 패턴 검색)
- 복잡한 복제 로직 (자동 번호 증가)
TypeScript 컴파일 성공
Prisma import 완전 제거
Phase 3 진행률: 76/162 (46.9%)
전체 진행률: 327/444 (73.6%)
10개 Prisma 호출을 모두 Raw Query로 전환
- 카테고리 관리 (getCategories, createCategory, updateCategory, deleteCategory)
- 코드 관리 (getCodes, createCode, updateCode, deleteCode)
- 코드 옵션 조회 (getCodeOptions)
- 코드 순서 변경 (reorderCodes)
- 중복 검사 (checkCategoryDuplicate, checkCodeDuplicate)
주요 기술적 해결:
- 동적 WHERE 조건 생성 (ILIKE 검색, OR 조건)
- 동적 UPDATE 쿼리 (변경된 필드만 업데이트)
- IN 절 동적 파라미터 바인딩 (reorderCodes)
- 트랜잭션 처리 (순서 변경)
- 동적 SQL 쿼리 생성 (중복 검사)
TypeScript 컴파일 성공
Prisma import 완전 제거
Phase 3 진행률: 64/162 (39.5%)
전체 진행률: 315/444 (70.9%)
15개 Prisma 호출을 모두 Raw Query로 전환
- 컴포넌트 조회 (getComponents, getComponent)
- 컴포넌트 CRUD (createComponent, updateComponent, deleteComponent)
- 정렬 순서 업데이트 (updateSortOrder)
- 컴포넌트 복제 (duplicateComponent)
- 카테고리 조회 (getCategories)
- 통계 조회 (getStatistics)
- 중복 체크 (checkDuplicate)
주요 기술적 해결:
- 동적 WHERE 조건 생성 (ILIKE 검색, OR 조건)
- 동적 UPDATE 쿼리 (fieldMapping 사용)
- GROUP BY 집계 쿼리 (카테고리별, 상태별)
- DISTINCT 쿼리 (카테고리 목록)
- 트랜잭션 처리 (정렬 순서 업데이트)
- SQL 인젝션 방지 (정렬 컬럼 검증)
TypeScript 컴파일 성공
Prisma import 완전 제거
Phase 3 진행률: 54/162 (33.3%)
전체 진행률: 305/444 (68.7%)
14개 Prisma 호출을 모두 Raw Query로 전환
- 배치 설정 CRUD
- 커넥션 및 테이블 조회
- 데이터 조회 및 삽입
- 실행 로그 관리
- 매핑 검증
주요 기술적 해결:
- 동적 WHERE 조건 생성
- 동적 UPDATE 쿼리
- 복잡한 트랜잭션 처리
- LEFT JOIN으로 배치 매핑 조회
- transaction 함수 사용
TypeScript 컴파일 성공
Prisma import 완전 제거
Phase 3 진행률: 39/162 (24.1%)
전체 진행률: 290/444 (65.3%)
25개 Prisma 호출을 모두 Raw Query로 전환
- 언어 관리 (getLanguages, createLanguage, updateLanguage, toggleLanguage, deleteLanguage)
- 다국어 키 관리 (getLangKeys, createLangKey, updateLangKey, deleteLangKey, toggleLangKey)
- 다국어 텍스트 관리 (getLangTexts, saveLangTexts, getUserText, getLangText)
- 배치 번역 조회 (getBatchTranslations)
주요 기술적 해결:
- 동적 WHERE 조건 생성 (ILIKE 검색 지원)
- 동적 UPDATE 쿼리 (변경된 필드만 업데이트)
- 트랜잭션 처리 (transaction 함수 사용)
- JOIN 쿼리 (multi_lang_text + multi_lang_key_master)
- IN 절 동적 파라미터 바인딩 (배치 번역)
TypeScript 컴파일 성공 (linter 에러 0개)
Prisma import 완전 제거
Phase 3 진행률: 25/162 (15.4%)
전체 진행률: 276/444 (62.2%)
Phase 2.5: ExternalDbConnectionService (15개)
- 15개 Prisma 호출을 모두 Raw Query로 전환
- 동적 WHERE 조건 생성 및 동적 UPDATE 쿼리 구현
- 비밀번호 암호화/복호화 로직 유지
- ILIKE 검색 지원
Phase 2.6: DataflowControlService (6개)
- 6개 Prisma 호출을 모두 Raw Query로 전환
- 파라미터 바인딩 수정 (MySQL ? → PostgreSQL $1, $2)
- 복잡한 비즈니스 로직 및 다중 커넥션 지원 유지
- 조건부 실행, 에러 처리 로직 보존
전체 성과:
- TypeScript 컴파일 성공 (linter 에러 0개)
- Prisma import 완전 제거
- Phase 2 진행률: 152/162 (93.8%)
- 전체 진행률: 238/444 (53.6%)
- 15개 Prisma 호출을 모두 Raw Query로 전환
- 동적 WHERE 조건 생성 구현 (ILIKE 검색 지원)
- 동적 UPDATE 쿼리 구현 (변경된 필드만 업데이트)
- 비밀번호 암호화/복호화 로직 유지
- TypeScript 컴파일 성공 (linter 에러 0개)
- Prisma import 완전 제거
전환된 주요 함수:
- getConnections() - 외부 DB 연결 목록 조회
- createConnection() - 새 연결 생성 + 중복 확인
- updateConnection() - 연결 정보 수정
- deleteConnection() - 연결 삭제
- testConnectionById() - 연결 테스트
- getTables() - 테이블 목록 조회
Phase 2 진행률: 131/162 (80.9%)
전체 진행률: 217/444 (48.9%)
추가 전환 완료:
✅ 조회 및 관리 함수들:
- checkScreenDependencies() - 화면 의존성 확인 (JOIN 쿼리)
- cleanupDeletedScreenMenuAssignments() - 메뉴 할당 정리
- permanentDeleteScreen() - 영구 삭제 (트랜잭션)
- getDeletedScreens() - 휴지통 목록 조회 (페이징 + 테이블 레이블)
📊 진행률: 25+/46 (54%+)
🎯 다음: $queryRaw 함수들 전환 (테이블/컬럼 정보 조회)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Stage 4: 트랜잭션 기반 복잡한 기능 Raw Query 전환
✅ 전환 완료 (3개 트랜잭션 함수):
**트랜잭션 함수들:**
1. copyScreen() - 화면 복사 (화면 + 레이아웃 전체 복사)
- 원본 화면 조회 (SELECT)
- 화면 코드 중복 체크 (SELECT)
- 새 화면 생성 (INSERT RETURNING)
- 원본 레이아웃 조회 (SELECT with ORDER BY)
- ID 매핑 후 레이아웃 복사 (반복 INSERT)
- PoolClient 기반 트랜잭션 사용
2. restoreScreen() - 삭제된 화면 복원
- 화면 코드 중복 체크 (SELECT with multiple conditions)
- 화면 복원 (UPDATE with NULL 설정)
- 메뉴 할당 활성화 (UPDATE)
- 트랜잭션으로 원자성 보장
3. bulkDeletePermanently() - 일괄 영구 삭제
- 삭제 대상 조회 (SELECT with dynamic WHERE)
- 레이아웃 삭제 (DELETE)
- 메뉴 할당 삭제 (DELETE)
- 화면 정의 삭제 (DELETE)
- 각 화면마다 개별 트랜잭션으로 롤백 격리
📊 진행률: 20+/46 (43%+)
🎯 다음: 나머지 Prisma 호출 전환 (조회, UPSERT 등)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
추가 기본 조회 함수 Raw Query 전환
✅ 추가 전환 완료 (2개):
7. getScreens() - 전체 화면 목록 조회 (동적 WHERE)
8. getScreen() - 회사 코드 필터링 포함 조회
📊 진행률: 8/46 (17.4%)
🎯 다음: Stage 2 레이아웃 관리 전환
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>
Phase 1.5 완료: 인증 서비스 Raw Query 전환 및 테스트 완료
✅ AuthService 전환 완료 (5개 Prisma 호출 제거):
- loginPwdCheck(): Raw Query로 사용자 비밀번호 조회
- insertLoginAccessLog(): Raw Query로 로그인 로그 기록
- getUserInfo(): Raw Query로 사용자/권한/회사 정보 조회
- authority_sub_user ↔ authority_master JOIN (master_objid ↔ objid)
- 3개 쿼리로 분리 (사용자, 권한, 회사)
- processLogin(): 전체 로그인 플로우 통합
- processLogout(): 로그아웃 로그 기록
🧪 테스트 완료:
- 단위 테스트: 30개 테스트 모두 통과 ✅
- 로그인 검증 (6개)
- 사용자 정보 조회 (5개)
- 로그인 로그 기록 (4개)
- 전체 로그인 프로세스 (5개)
- 로그아웃 (2개)
- 토큰 검증 (3개)
- Raw Query 전환 검증 (3개)
- 성능 테스트 (2개)
- 통합 테스트: 작성 완료 (auth.integration.test.ts)
- 로그인 → 토큰 발급 → 인증 → 로그아웃 플로우
🔧 주요 변경사항:
- Prisma import 제거 → Raw Query (query from db.ts)
- authority 테이블 JOIN 수정 (auth_code → master_objid/objid)
- 파라미터 바인딩으로 SQL Injection 방지
- 타입 안전성 유지 (TypeScript Generic 사용)
📊 성능:
- 로그인 프로세스: < 1초
- 사용자 정보 조회: < 500ms
- 모든 테스트 실행 시간: 2.016초
🎯 다음 단계:
- Phase 2: 핵심 서비스 전환 (ScreenManagement, TableManagement 등)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Phase 1 완료: Raw Query 기반 데이터베이스 아키텍처 구축
✅ 구현 완료 내용:
- DatabaseManager 클래스 구현 (연결 풀, 트랜잭션 관리)
- QueryBuilder 유틸리티 (동적 쿼리 생성)
- 타입 정의 및 검증 로직 (database.ts, databaseValidator.ts)
- 단위 테스트 작성 및 통과
🔧 전환 완료 서비스:
- externalCallConfigService.ts (Raw Query 전환)
- multiConnectionQueryService.ts (Raw Query 전환)
📚 문서:
- PHASE1_USAGE_GUIDE.md (사용 가이드)
- DETAILED_FILE_MIGRATION_PLAN.md (상세 계획)
- PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md (Phase 1 완료 표시)
🧪 테스트:
- database.test.ts (핵심 기능 테스트)
- 모든 테스트 통과 확인
이제 Phase 2 (핵심 서비스 전환)로 진행 가능
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- 템플릿 파일첨부 컴포넌트와 FileComponentConfigPanel 실시간 동기화
- FileUpload 위젯에 전역 파일 상태 관리 기능 추가
- 파일 업로드/삭제 시 전역 상태 및 localStorage 동기화
- RealtimePreview에서 전역 상태 우선 읽기 및 파일 개수 표시
- 한컴오피스, Apple iWork 파일 형식 지원 추가
- 파일 뷰어 모달 및 미리보기 기능 구현
- 업로드된 파일 디렉토리 .gitignore 추가
- DatabaseConnectorFactory에 Oracle, MariaDB 커넥터 추가
- BatchService에서 PostgreSQL timestamp 타입 캐스팅 추가
- BatchExternalDbService에 쿼리 로깅 추가
- 배치 실행 로그 관련 타입 및 컨트롤러 개선
- 프론트엔드 배치 관리 UI 개선
✨ 주요 기능:
- 배치 설정 관리 (생성/수정/삭제/실행)
- 배치 실행 로그 관리 및 모니터링
- 배치 스케줄러 자동 실행 (cron 기반)
- 외부 DB 연결을 통한 데이터 동기화
- Oracle, MSSQL, MariaDB 커넥터 지원
🔧 백엔드 구현:
- BatchManagementController: 배치 설정 CRUD
- BatchExecutionLogController: 실행 로그 관리
- BatchSchedulerService: 자동 스케줄링
- BatchExternalDbService: 외부 DB 연동
- 배치 관련 테이블 스키마 추가
🎨 프론트엔드 구현:
- 배치 관리 대시보드 UI
- 배치 생성/수정 폼
- 실행 로그 모니터링 화면
- 수동 실행 및 상태 관리
🛡️ 안전성:
- 기존 시스템과 독립적 구현
- 트랜잭션 기반 안전한 데이터 처리
- 에러 핸들링 및 로깅 강화
- 테이블 타입 관리에서 엔티티 타입의 표시 컬럼 설정 완전 제거
- 컬럼 설정 패널에서 엔티티 타입일 때 표시 컬럼 조합 선택 기능 추가
- 기본 테이블과 조인 테이블의 컬럼을 자유롭게 조합 가능
- 구분자 설정 및 실시간 미리보기 기능 포함
- 별도 모달 방식 제거하고 기존 컬럼 설정 패널에 통합
Frontend:
- EntityTypeConfig 인터페이스에 displayColumns 배열 추가
- EntityTypeConfigPanel에서 여러 표시 컬럼 선택 UI 구현
- 구분자 설정 기능 추가
- 하위 호환성을 위한 displayColumn 유지
Backend:
- EntityJoinConfig에 displayColumns 배열 지원
- 화면별 엔티티 설정을 전달받는 API 확장
- CONCAT을 사용한 다중 컬럼 표시 SQL 생성
- 기존 단일 컬럼과의 호환성 유지
이제 화면마다 다른 표시 컬럼 조합을 설정할 수 있음
예: 한 화면에서는 '이름'만, 다른 화면에서는 '이름 - 부서명' 표시
- Revert to dev branch version to fix TypeScript compilation errors
- Main branch version was missing required export functions
- Routes depend on these exported functions for proper API functionality
- Update multilangController.ts to main branch version
- Add Windows development environment files from main
- Include batch files for Windows development support