# 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
