ERP-node/docs/backend-analysis-response.json

240 lines
10 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"status": "success",
"confidence": "high",
"result": {
"summary": "WACE ERP 백엔드 전체 아키텍처 분석 완료",
"details": "Node.js + Express + TypeScript + PostgreSQL Raw Query 기반 멀티테넌시 시스템. 70+ 라우트, 70+ 컨트롤러, 80+ 서비스로 구성된 계층형 아키텍처. JWT 인증, 3단계 권한 체계(SUPER_ADMIN/COMPANY_ADMIN/USER), company_code 기반 완전한 데이터 격리 구현.",
"files_affected": [
"docs/backend-architecture-detailed-analysis.md (상세 분석 문서)",
"docs/backend-architecture-summary.md (요약 문서)",
"docs/backend-api-route-mapping.md (API 라우트 전체 매핑)"
],
"key_findings": {
"architecture_pattern": "Layered Architecture (Controller → Service → Database)",
"tech_stack": {
"language": "TypeScript",
"runtime": "Node.js 20.10.0+",
"framework": "Express.js",
"database": "PostgreSQL (pg 라이브러리, Raw Query)",
"authentication": "JWT (jsonwebtoken)",
"scheduler": "node-cron",
"external_db_support": ["PostgreSQL", "MySQL", "MSSQL", "Oracle"]
},
"directory_structure": {
"controllers": "70+ 파일 (API 요청 수신, 응답 생성)",
"services": "80+ 파일 (비즈니스 로직, 트랜잭션 관리)",
"routes": "70+ 파일 (API 라우팅)",
"middleware": "4개 (인증, 권한, 슈퍼관리자, 에러핸들러)",
"types": "26개 (TypeScript 타입 정의)",
"utils": "유틸리티 함수 (JWT, 암호화, 로거)"
},
"middleware_stack": [
"1. Process Level Exception Handlers",
"2. Helmet (보안 헤더)",
"3. Compression (Gzip)",
"4. Body Parser (10MB limit)",
"5. Static Files (/uploads)",
"6. CORS (credentials: true)",
"7. Rate Limiting (1분 10000회)",
"8. Token Auto Refresh (1시간 이내 만료 시 갱신)",
"9. API Routes (70+개)",
"10. 404 Handler",
"11. Error Handler"
],
"authentication_flow": {
"step1": "로그인 요청 → AuthController.login()",
"step2": "AuthService.processLogin() → loginPwdCheck() (bcrypt 검증)",
"step3": "getPersonBeanFromSession() → 사용자 정보 조회",
"step4": "insertLoginAccessLog() → 로그인 이력 저장",
"step5": "JwtUtils.generateToken() → JWT 토큰 생성",
"step6": "응답: { token, userInfo, firstMenuPath }"
},
"jwt_payload": {
"userId": "사용자 ID",
"userName": "사용자명",
"companyCode": "회사 코드 (멀티테넌시 키)",
"userType": "권한 레벨 (SUPER_ADMIN/COMPANY_ADMIN/USER)",
"exp": "만료 시간 (24시간)"
},
"permission_levels": {
"SUPER_ADMIN": {
"company_code": "*",
"userType": "SUPER_ADMIN",
"capabilities": [
"전체 회사 데이터 접근",
"DDL 실행",
"회사 생성/삭제",
"시스템 설정 변경"
]
},
"COMPANY_ADMIN": {
"company_code": "특정 회사 (예: ILSHIN)",
"userType": "COMPANY_ADMIN",
"capabilities": [
"자기 회사 데이터만 접근",
"자기 회사 사용자 관리",
"회사 설정 변경"
]
},
"USER": {
"company_code": "특정 회사",
"userType": "USER",
"capabilities": [
"자기 회사 데이터만 접근",
"읽기/쓰기 권한만"
]
}
},
"multi_tenancy": {
"principle": "모든 쿼리에 company_code 필터 필수",
"pattern": "JWT 토큰에서 company_code 추출 (클라이언트 신뢰 금지)",
"super_admin_visibility": "일반 회사 사용자에게 슈퍼관리자(company_code='*') 숨김",
"correct_pattern": "WHERE company_code = $1 AND company_code != '*'",
"wrong_pattern": "req.body.companyCode 사용 (보안 위험!)"
},
"api_routes": {
"total_count": "200+개",
"categories": {
"인증/관리자": "15개",
"테이블/화면": "40개",
"플로우": "15개",
"데이터플로우": "5개",
"외부 연동": "15개",
"배치": "10개",
"메일": "5개",
"파일": "5개",
"기타": "90개"
}
},
"business_domains": {
"관리자": {
"controller": "adminController.ts",
"service": "adminService.ts",
"features": ["사용자 관리", "메뉴 관리", "권한 그룹 관리", "시스템 설정"]
},
"테이블/화면": {
"controller": "tableManagementController.ts, screenManagementController.ts",
"service": "tableManagementService.ts, screenManagementService.ts",
"features": ["테이블 메타데이터", "화면 정의", "화면 그룹", "테이블 로그", "엔티티 관계"]
},
"플로우": {
"controller": "flowController.ts",
"service": "flowExecutionService.ts, flowDefinitionService.ts",
"features": ["워크플로우 설계", "단계 관리", "데이터 이동", "조건부 이동", "오딧 로그"]
},
"데이터플로우": {
"controller": "dataflowController.ts, dataflowDiagramController.ts",
"service": "dataflowService.ts, dataflowDiagramService.ts",
"features": ["테이블 관계 정의", "ERD", "다이어그램 시각화", "관계 실행"]
},
"외부 연동": {
"controller": "externalDbConnectionController.ts, externalRestApiConnectionController.ts",
"service": "externalDbConnectionService.ts, dbConnectionManager.ts",
"features": ["외부 DB 연결", "Connection Pool 관리", "REST API 프록시"]
},
"배치": {
"controller": "batchController.ts, batchManagementController.ts",
"service": "batchService.ts, batchSchedulerService.ts",
"features": ["Cron 스케줄러", "외부 DB → 내부 DB 동기화", "컬럼 매핑", "실행 이력"]
},
"메일": {
"controller": "mailSendSimpleController.ts, mailReceiveBasicController.ts",
"service": "mailSendSimpleService.ts, mailReceiveBasicService.ts",
"features": ["메일 발송 (nodemailer)", "메일 수신 (IMAP)", "템플릿 관리", "첨부파일"]
},
"파일": {
"controller": "fileController.ts, screenFileController.ts",
"service": "fileSystemManager.ts",
"features": ["파일 업로드 (multer)", "파일 다운로드", "화면별 파일 관리"]
}
},
"database_access": {
"connection_pool": {
"min": "2~5 (환경별)",
"max": "10~20 (환경별)",
"connectionTimeout": "30000ms",
"idleTimeout": "600000ms",
"statementTimeout": "60000ms"
},
"query_patterns": {
"multi_row": "query('SELECT ...', [params])",
"single_row": "queryOne('SELECT ...', [params])",
"transaction": "transaction(async (client) => { ... })"
},
"sql_injection_prevention": "Parameterized Query 사용 (pg 라이브러리)"
},
"external_integration": {
"supported_databases": ["PostgreSQL", "MySQL", "MSSQL", "Oracle"],
"connector_pattern": "Factory Pattern (DatabaseConnectorFactory)",
"rest_api": "axios 기반 프록시"
},
"batch_scheduler": {
"library": "node-cron",
"timezone": "Asia/Seoul",
"cron_examples": {
"매일 새벽 2시": "0 2 * * *",
"5분마다": "*/5 * * * *",
"평일 오전 8시": "0 8 * * 1-5"
},
"execution_flow": [
"1. 소스 DB에서 데이터 조회",
"2. 컬럼 매핑 적용",
"3. 타겟 DB에 INSERT/UPDATE",
"4. 실행 로그 기록"
]
},
"file_handling": {
"upload_path": "uploads/{company_code}/{timestamp}-{uuid}-{filename}",
"max_file_size": "10MB",
"allowed_types": ["이미지", "PDF", "Office 문서"],
"library": "multer"
},
"security": {
"password_encryption": "bcrypt (12 rounds)",
"sensitive_data_encryption": "AES-256-CBC (외부 DB 비밀번호)",
"jwt_secret": "환경변수 관리",
"security_headers": ["Helmet (CSP, X-Frame-Options)", "CORS (credentials: true)", "Rate Limiting (1분 10000회)"],
"sql_injection_prevention": "Parameterized Query"
},
"error_handling": {
"postgres_error_codes": {
"23505": "중복된 데이터",
"23503": "참조 무결성 위반",
"23502": "필수 입력값 누락"
},
"process_level": {
"unhandledRejection": "로깅 (서버 유지)",
"uncaughtException": "로깅 (서버 유지, 주의)",
"SIGTERM/SIGINT": "Graceful Shutdown"
}
},
"logging": {
"library": "Winston",
"log_files": {
"error.log": "에러만 (10MB × 5파일)",
"combined.log": "전체 로그 (10MB × 10파일)"
},
"log_levels": "error (0) → warn (1) → info (2) → debug (5)"
},
"performance_optimization": {
"pool_monitoring": "5분마다 상태 체크, 대기 연결 5개 이상 시 경고",
"slow_query_detection": "1초 이상 걸린 쿼리 자동 경고",
"caching": "Redis (메뉴: 10분 TTL, 공통코드: 30분 TTL)",
"compression": "Gzip (1KB 이상 응답, 레벨 6)"
}
},
"critical_rules": [
"✅ 모든 쿼리에 company_code 필터 추가",
"✅ JWT 토큰에서 company_code 추출 (클라이언트 신뢰 금지)",
"✅ Parameterized Query 사용 (SQL Injection 방지)",
"✅ 슈퍼관리자 데이터 숨김 (company_code != '*')",
"✅ 비밀번호는 bcrypt, 민감정보는 AES-256",
"✅ 에러 핸들링 try/catch 필수",
"✅ 트랜잭션이 필요한 경우 transaction() 사용",
"✅ 파일 업로드는 회사별 디렉토리 분리"
]
},
"needs_from_others": [],
"questions": []
}