# WACE ERP Backend - 아키텍처 요약 > **작성일**: 2026-02-06 > **목적**: 워크플로우 문서 통합용 백엔드 아키텍처 요약 --- ## 1. 기술 스택 ``` 언어: TypeScript (Node.js 20.10.0+) 프레임워크: Express.js 데이터베이스: PostgreSQL (pg 라이브러리, Raw Query) 인증: JWT (jsonwebtoken) 스케줄러: node-cron 메일: nodemailer + IMAP 파일업로드: multer 외부DB: MySQL, MSSQL, Oracle 지원 ``` ## 2. 계층 구조 ``` ┌─────────────────┐ │ Controller │ ← API 요청 수신, 응답 생성 └────────┬────────┘ │ ┌────────▼────────┐ │ Service │ ← 비즈니스 로직, 트랜잭션 관리 └────────┬────────┘ │ ┌────────▼────────┐ │ Database │ ← PostgreSQL Raw Query └─────────────────┘ ``` ## 3. 디렉토리 구조 ``` backend-node/src/ ├── app.ts # Express 앱 진입점 ├── config/ # 환경설정 ├── controllers/ # 70+ 컨트롤러 ├── services/ # 80+ 서비스 ├── routes/ # 70+ 라우터 ├── middleware/ # 인증/권한/에러핸들러 ├── database/ # DB 연결 (pg Pool) ├── types/ # TypeScript 타입 (26개) └── utils/ # 유틸리티 (JWT, 암호화, 로거) ``` ## 4. 미들웨어 스택 순서 ```typescript 1. Process Level Exception Handlers (unhandledRejection, uncaughtException) 2. Helmet (보안 헤더) 3. Compression (Gzip) 4. Body Parser (JSON, URL-encoded, 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 ``` ## 5. 인증/인가 시스템 ### 5.1 인증 흐름 ``` 로그인 요청 ↓ AuthController.login() ↓ AuthService.processLogin() ├─ loginPwdCheck() → 비밀번호 검증 (bcrypt) ├─ getPersonBeanFromSession() → 사용자 정보 조회 ├─ insertLoginAccessLog() → 로그인 이력 저장 └─ JwtUtils.generateToken() → JWT 토큰 생성 ↓ 응답: { token, userInfo, firstMenuPath } ``` ### 5.2 JWT Payload ```json { "userId": "user123", "userName": "홍길동", "companyCode": "ILSHIN", "userType": "COMPANY_ADMIN", "iat": 1234567890, "exp": 1234654290, "iss": "PMS-System" } ``` ### 5.3 권한 체계 (3단계) | 권한 | company_code | userType | 권한 범위 | |------|--------------|----------|-----------| | **SUPER_ADMIN** | `*` | `SUPER_ADMIN` | 전체 회사, DDL 실행, 회사 생성/삭제 | | **COMPANY_ADMIN** | `ILSHIN` | `COMPANY_ADMIN` | 자기 회사만, 사용자/설정 관리 | | **USER** | `ILSHIN` | `USER` | 자기 회사만, 읽기/쓰기 | ## 6. 멀티테넌시 구현 ### 핵심 원칙 ```typescript // ✅ 올바른 패턴 const companyCode = req.user!.companyCode; // JWT에서 추출 if (companyCode === "*") { // 슈퍼관리자: 모든 데이터 조회 query = "SELECT * FROM table ORDER BY company_code"; } else { // 일반 사용자: 자기 회사 + 슈퍼관리자 데이터 제외 query = "SELECT * FROM table WHERE company_code = $1 AND company_code != '*'"; params = [companyCode]; } // ❌ 잘못된 패턴 (보안 위험!) const companyCode = req.body.companyCode; // 클라이언트에서 받음 ``` ### 슈퍼관리자 숨김 규칙 ```sql -- 일반 회사 사용자에게 슈퍼관리자(company_code='*')는 보이면 안 됨 SELECT * FROM user_info WHERE company_code = $1 AND company_code != '*' -- 필수! ``` ## 7. API 라우트 (70+개) ### 7.1 인증/관리자 - `POST /api/auth/login` - 로그인 - `GET /api/auth/me` - 현재 사용자 정보 - `POST /api/auth/switch-company` - 회사 전환 (슈퍼관리자) - `GET /api/admin/users` - 사용자 목록 - `GET /api/admin/menus` - 메뉴 목록 ### 7.2 테이블/화면 - `GET /api/table-management/tables` - 테이블 목록 - `POST /api/table-management/tables/:table/data` - 데이터 조회 - `POST /api/table-management/multi-table-save` - 다중 테이블 저장 - `GET /api/screen-management/screens` - 화면 목록 ### 7.3 플로우 - `GET /api/flow/definitions` - 플로우 정의 목록 - `POST /api/flow/move` - 데이터 이동 (단건) - `POST /api/flow/move-batch` - 데이터 이동 (다건) ### 7.4 외부 연동 - `GET /api/external-db-connections` - 외부 DB 연결 목록 - `POST /api/external-db-connections/:id/test` - 연결 테스트 - `POST /api/multi-connection/query` - 멀티 DB 쿼리 ### 7.5 배치 - `GET /api/batch-configs` - 배치 설정 목록 - `POST /api/batch-management/:id/execute` - 배치 즉시 실행 ### 7.6 메일 - `POST /api/mail/send` - 메일 발송 - `GET /api/mail/sent` - 발송 이력 ### 7.7 파일 - `POST /api/files/upload` - 파일 업로드 - `GET /uploads/:filename` - 정적 파일 서빙 ## 8. 비즈니스 도메인 (8개) | 도메인 | 컨트롤러 | 주요 기능 | |--------|----------|-----------| | **관리자** | `adminController` | 사용자/메뉴/권한 관리 | | **테이블/화면** | `tableManagementController` | 메타데이터, 동적 화면 생성 | | **플로우** | `flowController` | 워크플로우 엔진, 데이터 이동 | | **데이터플로우** | `dataflowController` | ERD, 관계도 | | **외부 연동** | `externalDbConnectionController` | 외부 DB/REST API | | **배치** | `batchController` | Cron 스케줄러, 데이터 동기화 | | **메일** | `mailSendSimpleController` | 메일 발송/수신 | | **파일** | `fileController` | 파일 업로드/다운로드 | ## 9. 데이터베이스 접근 ### Connection Pool 설정 ```typescript { min: 2~5, // 최소 연결 수 max: 10~20, // 최대 연결 수 connectionTimeout: 30000, // 30초 idleTimeout: 600000, // 10분 statementTimeout: 60000 // 쿼리 실행 60초 } ``` ### Raw Query 패턴 ```typescript // 1. 다중 행 const users = await query('SELECT * FROM user_info WHERE company_code = $1', [companyCode]); // 2. 단일 행 const user = await queryOne('SELECT * FROM user_info WHERE user_id = $1', [userId]); // 3. 트랜잭션 await transaction(async (client) => { await client.query('INSERT INTO table1 ...', [...]); await client.query('INSERT INTO table2 ...', [...]); }); ``` ## 10. 외부 시스템 연동 ### 지원 데이터베이스 - PostgreSQL - MySQL - Microsoft SQL Server - Oracle ### Connector Factory Pattern ```typescript DatabaseConnectorFactory ├── PostgreSQLConnector ├── MySQLConnector ├── MSSQLConnector └── OracleConnector ``` ## 11. 배치/스케줄 시스템 ### Cron 스케줄러 ```typescript // node-cron 기반 // 매일 새벽 2시: "0 2 * * *" // 5분마다: "*/5 * * * *" // 평일 오전 8시: "0 8 * * 1-5" // 서버 시작 시 자동 초기화 BatchSchedulerService.initializeScheduler(); ``` ### 배치 실행 흐름 ``` 1. 소스 DB에서 데이터 조회 ↓ 2. 컬럼 매핑 적용 ↓ 3. 타겟 DB에 INSERT/UPDATE ↓ 4. 실행 로그 기록 (batch_execution_logs) ``` ## 12. 파일 처리 ### 업로드 경로 ``` uploads/ └── {company_code}/ └── {timestamp}-{uuid}-{filename} ``` ### Multer 설정 - 최대 파일 크기: 10MB - 허용 타입: 이미지, PDF, Office 문서 - 파일명 중복 방지: 타임스탬프 + UUID ## 13. 보안 ### 암호화 - **비밀번호**: bcrypt (12 rounds) - **민감정보**: AES-256-CBC (외부 DB 비밀번호 등) - **JWT Secret**: 환경변수 관리 ### 보안 헤더 - Helmet (CSP, X-Frame-Options) - CORS (credentials: true) - Rate Limiting (1분 10000회) ### SQL Injection 방지 - Parameterized Query 사용 (pg 라이브러리) - 동적 쿼리 빌더 패턴 ## 14. 에러 핸들링 ### PostgreSQL 에러 코드 매핑 - `23505` → "중복된 데이터" - `23503` → "참조 무결성 위반" - `23502` → "필수 입력값 누락" ### 프로세스 레벨 - `unhandledRejection` → 로깅 (서버 유지) - `uncaughtException` → 로깅 (서버 유지, 주의) - `SIGTERM/SIGINT` → Graceful Shutdown ## 15. 로깅 (Winston) ### 로그 파일 - `logs/error.log` - 에러만 (10MB × 5파일) - `logs/combined.log` - 전체 로그 (10MB × 10파일) ### 로그 레벨 ``` error (0) → warn (1) → info (2) → debug (5) ``` ## 16. 성능 최적화 ### Pool 모니터링 - 5분마다 상태 체크 - 대기 연결 5개 이상 시 경고 ### 느린 쿼리 감지 - 1초 이상 걸린 쿼리 자동 경고 ### 캐싱 (Redis) - 메뉴 목록: 10분 TTL - 공통코드: 30분 TTL ### Gzip 압축 - 1KB 이상 응답만 압축 (레벨 6) --- ## 🎯 핵심 체크리스트 ### 개발 시 반드시 지켜야 할 규칙 ✅ **모든 쿼리에 `company_code` 필터 추가** ✅ **JWT 토큰에서 `company_code` 추출 (클라이언트 신뢰 금지)** ✅ **Parameterized Query 사용 (SQL Injection 방지)** ✅ **슈퍼관리자 데이터 숨김 (`company_code != '*'`)** ✅ **비밀번호는 bcrypt, 민감정보는 AES-256** ✅ **에러 핸들링 try/catch 필수** ✅ **트랜잭션이 필요한 경우 `transaction()` 사용** ✅ **파일 업로드는 회사별 디렉토리 분리** --- **문서 버전**: 1.0 **마지막 업데이트**: 2026-02-06