ERP-node/docs/backend-architecture-summar...

343 lines
9.4 KiB
Markdown
Raw 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.

# 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