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

46 KiB

WACE ERP 백엔드 아키텍처 상세 분석

작성일: 2026-02-06
분석 대상: ERP-node/backend-node
Stack: Node.js + Express + TypeScript + PostgreSQL Raw Query


📋 목차

  1. 전체 디렉토리 구조
  2. API 라우트 목록 및 역할
  3. 인증/인가 워크플로우
  4. 비즈니스 도메인별 모듈 분류
  5. 미들웨어 스택 구성
  6. 서비스 레이어 패턴
  7. 멀티테넌시 구현 방식
  8. 에러 핸들링 전략
  9. 파일 업로드/다운로드 처리
  10. 외부 연동
  11. 배치/스케줄 처리
  12. 컨트롤러/서비스 상세 역할

1. 전체 디렉토리 구조

backend-node/
├── src/
│   ├── app.ts                    # Express 앱 진입점, 라우트 등록, 미들웨어 설정
│   ├── config/
│   │   └── environment.ts        # 환경변수 관리 (PORT, DB, JWT, CORS 등)
│   ├── controllers/              # 69개 컨트롤러 (요청 처리 및 응답)
│   ├── services/                 # 87개 서비스 (비즈니스 로직)
│   ├── routes/                   # 77개 라우터 (엔드포인트 정의)
│   ├── middleware/               # 4개 미들웨어 (인증, 권한, 에러 핸들링)
│   ├── database/                 # DB 연결 풀, 커넥터, 마이그레이션
│   ├── utils/                    # 16개 유틸리티 (JWT, 암호화, 로거 등)
│   ├── types/                    # 26개 TypeScript 타입 정의
│   ├── interfaces/               # 인터페이스 정의
│   └── tests/                    # 테스트 파일
├── scripts/                      # 배치 및 유틸리티 스크립트
├── data/                         # JSON 기반 설정 데이터
├── uploads/                      # 파일 업로드 디렉토리
└── package.json                  # 의존성 관리

주요 특징

  • Layered Architecture: Controller → Service → Database 3계층 구조
  • TypeScript Strict Mode: 타입 안전성 보장
  • Raw Query 기반: Prisma → PostgreSQL Raw Query 전환 완료
  • Connection Pool: pg 라이브러리 기반 연결 풀 관리
  • 마이크로서비스 지향: 도메인별 명확한 분리

2. API 라우트 목록 및 역할

2.1 인증 및 관리자 (Auth & Admin)

엔드포인트 메서드 역할 인증
/api/auth/login POST 로그인 (JWT 토큰 발급)
/api/auth/signup POST 회원가입 (공차중계)
/api/auth/me GET 현재 사용자 정보 조회
/api/auth/logout POST 로그아웃
/api/auth/refresh POST JWT 토큰 갱신
/api/auth/switch-company POST 관리자 전용: 회사 전환
/api/admin/menus GET 메뉴 목록 조회
/api/admin/users GET/POST/PUT 사용자 관리 (CRUD)
/api/admin/companies GET/POST/PUT/DELETE 회사 관리 (CRUD)
/api/admin/departments GET 부서 목록 조회

2.2 테이블 및 데이터 관리

엔드포인트 메서드 역할 인증
/api/table-management/tables GET 테이블 목록 조회
/api/table-management/columns GET 컬럼 정보 조회
/api/table-management/entity-joins GET/POST 테이블 조인 설정
/api/data/* GET/POST/PUT/DELETE 동적 테이블 데이터 CRUD
/api/ddl/* POST DDL 실행 (테이블 생성/수정/삭제) (Super Admin)

2.3 화면 및 폼 관리

엔드포인트 메서드 역할 인증
/api/screen-management/* GET/POST/PUT/DELETE 화면 메타데이터 관리
/api/screen-groups/* GET/POST/PUT/DELETE 화면 그룹 관리
/api/dynamic-form/* GET/POST 동적 폼 생성 및 렌더링
/api/admin/web-types GET/POST 웹 컴포넌트 타입 표준 관리
/api/admin/button-actions GET/POST 버튼 액션 표준 관리
/api/admin/template-standards GET/POST 템플릿 표준 관리
/api/admin/component-standards GET/POST 컴포넌트 표준 관리

2.4 플로우 및 데이터플로우

엔드포인트 메서드 역할 인증
/api/flow/definitions GET/POST/PUT/DELETE 플로우 정의 관리
/api/flow/definitions/:id/steps GET/POST 플로우 단계 관리
/api/flow/connections GET/POST/DELETE 플로우 연결 관리
/api/flow/move POST 데이터 이동 실행
/api/flow/audit/:flowId GET 플로우 오딧 로그 조회
/api/dataflow/* GET/POST/PUT/DELETE 데이터플로우 관계 관리
/api/dataflow-diagrams/* GET/POST/PUT/DELETE 데이터플로우 다이어그램
/api/dataflow/execute POST 데이터플로우 실행

2.5 배치 관리

엔드포인트 메서드 역할 인증
/api/batch-configs GET/POST/PUT/DELETE 배치 설정 관리
/api/batch-configs/connections GET 사용 가능한 커넥션 목록
/api/batch-configs/:id/execute POST 배치 수동 실행
/api/batch-management/* GET/POST 배치 실행 관리
/api/batch-execution-logs GET 배치 실행 이력 조회

2.6 외부 연동

엔드포인트 메서드 역할 인증
/api/external-db-connections GET/POST/PUT/DELETE 외부 DB 연결 관리
/api/external-db-connections/:id/test POST 외부 DB 연결 테스트
/api/external-rest-api-connections GET/POST/PUT/DELETE 외부 REST API 연결
/api/external-calls/* GET/POST 외부 API 호출 설정
/api/multi-connection/query POST 멀티 DB 통합 쿼리

2.7 메일 관리

엔드포인트 메서드 역할 인증
/api/mail/accounts GET/POST/PUT/DELETE 메일 계정 관리
/api/mail/templates-file GET/POST/PUT/DELETE 메일 템플릿 관리
/api/mail/send POST 메일 발송 (단일/대량)
/api/mail/sent GET 발송 이력 조회
/api/mail/receive GET 메일 수신함 조회

2.8 기타 도메인

엔드포인트 메서드 역할 인증
/api/dashboards/* GET/POST 대시보드 관리
/api/admin/reports/* GET/POST 리포트 생성 및 조회
/api/files/* POST 파일 업로드/다운로드
/api/delivery/* GET/POST 배송/화물 관리
/api/risk-alerts/* GET/POST 리스크/알림 관리
/api/todos/* GET/POST/PUT/DELETE To-Do 관리
/api/bookings/* GET/POST 예약 관리
/api/digital-twin/* GET/POST 디지털 트윈 (야드 관제)
/api/schedule/* GET/POST 스케줄 자동 생성
/api/work-history/* GET 작업 이력 조회
/api/table-history/* GET 테이블 변경 이력 조회
/api/roles/* GET/POST 권한 그룹 관리
/api/numbering-rules/* GET/POST 채번 규칙 관리
/api/entity-search/* GET 엔티티 검색
/api/cascading-* GET/POST 연쇄 드롭다운 관계
/api/category-tree/* GET/POST 카테고리 트리
/api/vehicle/* GET/POST 차량 운행 이력
/api/tax-invoice/* GET/POST 세금계산서 관리

총 77개 라우터 파일, 200개 이상의 엔드포인트 제공


3. 인증/인가 워크플로우

3.1 인증 메커니즘

로그인 요청 (userId, password)
    ↓
1. AuthController.login()
    ↓
2. AuthService.processLogin()
    ├─ 비밀번호 검증 (BCrypt + 마스터 패스워드)
    ├─ 사용자 정보 조회 (user_info 테이블)
    ├─ 로그인 로그 기록 (LOGIN_ACCESS_LOG)
    └─ JWT 토큰 생성 (JwtUtils.generateToken)
    ↓
3. JWT 토큰 응답
    ├─ accessToken (24시간 유효)
    ├─ refreshToken (7일 유효)
    └─ userInfo (userId, userName, companyCode, userType)

3.2 JWT 토큰 구조

// JWT Payload
{
  userId: string;          // 사용자 ID
  userName: string;        // 사용자 이름
  companyCode: string;     // 회사 코드 (멀티테넌시 핵심)
  userType: string;        // 사용자 유형 (SUPER_ADMIN, COMPANY_ADMIN, USER)
  userLang?: string;       // 사용자 언어
  iat: number;             // 발급 시간
  exp: number;             // 만료 시간
}

3.3 미들웨어 체인

1. refreshTokenIfNeeded (자동 토큰 갱신)
    ↓
2. authenticateToken (JWT 검증 및 사용자 정보 설정)
    ↓
3. 권한 미들웨어 (선택적)
    ├─ requireSuperAdmin (회사코드 '*' 필수)
    ├─ requireAdmin (회사관리자 이상)
    ├─ requireCompanyAccess (회사 데이터 접근 권한)
    ├─ requireDDLPermission (DDL 실행 권한)
    └─ requireUserManagement (사용자 관리 권한)
    ↓
4. Controller 실행
    ↓
5. errorHandler (에러 발생 시)

3.4 권한 레벨 (3단계)

레벨 companyCode userType 권한 범위
Super Admin * SUPER_ADMIN 전체 시스템 접근, DDL 실행, 회사 생성/삭제
Company Admin 회사코드 COMPANY_ADMIN 자사 데이터 관리, 사용자 관리, 설정 변경
일반 사용자 회사코드 USER 자사 데이터 조회/수정 (권한 범위 내)

3.5 토큰 갱신 전략

  • 자동 갱신: 토큰이 1시간 이내 만료 시 응답 헤더(X-New-Token)에 새 토큰 포함
  • 명시적 갱신: /api/auth/refresh 엔드포인트 호출
  • 만료 처리: 만료된 토큰은 401 Unauthorized 응답 (TOKEN_EXPIRED)

4. 비즈니스 도메인별 모듈 분류

4.1 관리자 영역 (Admin)

파일:

  • adminController.ts, adminService.ts, adminRoutes.ts

주요 기능:

  • 메뉴 관리 (CRUD, 복사, 상태 토글, 일괄 삭제)
  • 사용자 관리 (등록, 수정, 상태 변경, 비밀번호 초기화)
  • 회사 관리 (등록, 수정, 삭제, 조회)
  • 부서 관리 (조회, 사용자-부서 통합 저장)
  • 로케일 설정 (다국어 지원)
  • 테이블 스키마 조회 (엑셀 매핑용)

특징:

  • 멀티테넌시 기반 회사별 데이터 격리
  • Super Admin만 회사 생성/삭제 가능
  • 사용자 변경 이력 추적

4.2 테이블 및 데이터 관리 (Table Management & Data)

파일:

  • tableManagementController.ts, tableManagementService.ts
  • dataController.ts, dataService.ts
  • entityJoinController.ts, entityJoinService.ts

주요 기능:

  • 테이블 목록 조회 (PostgreSQL information_schema 활용)
  • 컬럼 정보 조회 (타입, 라벨, 제약조건, 참조 관계)
  • 동적 테이블 데이터 CRUD (Raw Query 기반)
  • 테이블 조인 설정 및 실행 (1:N, N:M 관계)
  • 컬럼 라벨 및 설정 관리 (table_type_columns)

특징:

  • 캐시 기반 성능 최적화 (테이블/컬럼 정보)
  • 멀티테넌시 자동 필터링 (company_code 조건)
  • 코드 타입 컬럼 자동 처리 (공통 코드 연동)

4.3 화면 관리 (Screen Management)

파일:

  • screenManagementController.ts, screenManagementService.ts
  • screenGroupController.ts, screenEmbeddingController.ts

주요 기능:

  • 화면 메타데이터 관리 (테이블 연결, 컬럼 설정, 레이아웃)
  • 화면 그룹 관리 (폴더 구조)
  • 화면 임베딩 (부모-자식 화면 데이터 전달)
  • 동적 폼 생성 (JSON 기반 폼 설정 → React 컴포넌트)

특징:

  • Low-Code 화면 구성
  • 웹 컴포넌트 타입 표준 기반 렌더링
  • 버튼 액션 표준 지원 (저장, 삭제, 조회, 커스텀)

4.4 플로우 관리 (Flow Management)

파일:

  • flowController.ts, flowService.ts
  • flowExecutionService.ts, flowStepService.ts
  • flowConnectionService.ts, flowDataMoveService.ts

주요 기능:

  • 플로우 정의 관리 (작업 흐름 설계)
  • 플로우 단계 관리 (스텝 생성, 수정, 삭제)
  • 플로우 연결 관리 (스텝 간 조건부 연결)
  • 데이터 이동 실행 (스텝 간 데이터 이동)
  • 오딧 로그 조회 (변경 이력 추적)

특징:

  • 비주얼 워크플로우 엔진
  • 조건부 분기 지원
  • 배치 데이터 이동 지원

4.5 데이터플로우 (Dataflow)

파일:

  • dataflowController.ts, dataflowService.ts
  • dataflowDiagramController.ts, dataflowDiagramService.ts
  • dataflowExecutionController.ts

주요 기능:

  • 테이블 관계 정의 (1:1, 1:N, N:M)
  • 데이터플로우 다이어그램 생성 (ERD 같은 시각화)
  • 데이터플로우 실행 (자동 데이터 동기화)
  • 관계 기반 데이터 조회 (조인 쿼리 자동 생성)

특징:

  • 그래프 기반 데이터 관계 모델링
  • 다이어그램별 관계 그룹화

4.6 배치 관리 (Batch Management)

파일:

  • batchController.ts, batchService.ts
  • batchSchedulerService.ts, batchExecutionLogService.ts
  • batchExternalDbService.ts

주요 기능:

  • 배치 설정 관리 (CRUD)
  • Cron 기반 스케줄링 (node-cron)
  • 배치 수동/자동 실행
  • 실행 이력 조회 (성공/실패 로그)
  • 외부 DB 연동 배치 지원

특징:

  • 실시간 스케줄러 업데이트
  • 다중 DB 간 데이터 동기화
  • 실행 시간 제한 및 오류 알림

4.7 외부 연동 (External Integration)

파일:

  • externalDbConnectionController.ts, externalDbConnectionService.ts
  • externalRestApiConnectionController.ts, externalRestApiConnectionService.ts
  • externalCallController.ts, externalCallService.ts
  • multiConnectionQueryService.ts

주요 기능:

  • 외부 DB 연결 관리 (PostgreSQL, MySQL, MSSQL, Oracle, MariaDB)
  • 외부 REST API 연결 관리
  • 멀티 DB 통합 쿼리 실행
  • 연결 테스트 및 상태 확인
  • 크레덴셜 암호화 저장

특징:

  • 5종 DB 지원 (PostgreSQL, MySQL, MSSQL, Oracle, MariaDB)
  • Connection Pool 기반 연결 관리
  • 비밀번호 암호화 (AES-256-CBC)

4.8 메일 관리 (Mail Management)

파일:

  • mailAccountFileController.ts, mailAccountFileService.ts
  • mailTemplateFileController.ts, mailTemplateFileService.ts
  • mailSendSimpleController.ts, mailSendSimpleService.ts
  • mailSentHistoryController.ts, mailSentHistoryService.ts
  • mailReceiveBasicController.ts, mailReceiveBasicService.ts

주요 기능:

  • 메일 계정 관리 (SMTP/IMAP 설정)
  • 메일 템플릿 관리 (JSON 기반 컴포넌트 조합)
  • 메일 발송 (단일/대량, 첨부파일 지원)
  • 발송 이력 조회 (30일 자동 삭제)
  • 메일 수신함 조회 (IMAP)

특징:

  • Nodemailer 기반 발송
  • 템플릿 변수 치환
  • 대량 발송 지원 (100건/배치)
  • 메일 예약 발송

4.9 대시보드 (Dashboard)

파일:

  • DashboardController.ts, DashboardService.ts

주요 기능:

  • 대시보드 위젯 관리 (차트, 테이블, 카드)
  • 실시간 데이터 조회 (집계 쿼리)
  • 사용자별 대시보드 설정

특징:

  • JSON 기반 위젯 설정
  • 캐시 기반 성능 최적화

4.10 기타 도메인

파일 및 주요 기능:

  • 리포트: 리포트 생성 및 조회 (reportController.ts, reportService.ts)
  • 파일: 파일 업로드/다운로드 (fileController.ts, Multer)
  • 배송/화물: 배송 관리, 화물 추적 (deliveryController.ts)
  • 리스크/알림: 리스크 알림, 캐시 기반 자동 갱신 (riskAlertController.ts)
  • To-Do: 할 일 관리 (todoController.ts)
  • 예약: 예약 요청 관리 (bookingController.ts)
  • 디지털 트윈: 야드 관제, 3D 레이아웃 (digitalTwinController.ts)
  • 스케줄: 스케줄 자동 생성 (scheduleController.ts)
  • 작업 이력: 작업 로그 조회 (workHistoryController.ts)
  • 권한 그룹: 권한 그룹 관리 (roleController.ts)
  • 채번 규칙: 자동 채번 규칙 (numberingRuleController.ts)
  • 엔티티 검색: 동적 엔티티 검색 (entitySearchController.ts)
  • 연쇄 드롭다운: 조건부 드롭다운 (cascadingController.ts 시리즈)

5. 미들웨어 스택 구성

5.1 미들웨어 실행 순서 (app.ts 기준)

1. 프로세스 레벨 예외 처리 (unhandledRejection, uncaughtException)
2. 보안 헤더 (helmet)
3. 압축 (compression)
4. 바디 파싱 (express.json, express.urlencoded)
5. 정적 파일 서빙 (/uploads)
6. CORS (cors)
7. Rate Limiting (express-rate-limit)
8. 토큰 자동 갱신 (refreshTokenIfNeeded)
9. [라우트별 미들웨어]
    ├─ authenticateToken (모든 /api/* 라우트)
    ├─ 권한 미들웨어 (선택적)
    └─ 컨트롤러 실행
10. 404 핸들러
11. 에러 핸들러 (errorHandler)

5.2 미들웨어 파일

authMiddleware.ts

  • authenticateToken: JWT 토큰 검증 및 사용자 정보 설정
  • optionalAuth: 선택적 인증 (토큰 없어도 통과)
  • requireAdmin: 관리자 권한 필수 (userId === 'plm_admin')
  • refreshTokenIfNeeded: 토큰 자동 갱신 (1시간 이내 만료 시)
  • checkAuthStatus: 인증 상태 확인 (유효성 검사만)

permissionMiddleware.ts

  • requireSuperAdmin: 슈퍼관리자 권한 필수 (companyCode === '*')
  • requireAdmin: 관리자 이상 권한 필수 (Super Admin + Company Admin)
  • requireCompanyAccess: 회사 데이터 접근 권한 체크
  • requireUserManagement: 사용자 관리 권한 체크
  • requireCompanySettingsManagement: 회사 설정 변경 권한 체크
  • requireCompanyManagement: 회사 생성/삭제 권한 체크
  • requireDDLPermission: DDL 실행 권한 체크

superAdminMiddleware.ts

  • requireSuperAdmin: 슈퍼관리자 권한 확인 (DDL 전용)
  • validateDDLPermission: DDL 실행 전 추가 보안 검증 (5초 간격 제한)
  • isSuperAdmin: 슈퍼관리자 여부 확인 유틸 함수
  • checkDDLPermission: DDL 권한 체크 (미들웨어 없이 사용)

errorHandler.ts

  • AppError: 커스텀 에러 클래스 (statusCode, isOperational)
  • errorHandler: 전역 에러 핸들러 (PostgreSQL, JWT 에러 처리)
  • notFoundHandler: 404 에러 핸들러

5.3 보안 설정

// helmet: 보안 헤더 설정
helmet({
  contentSecurityPolicy: {
    directives: {
      'frame-ancestors': ['self', 'http://localhost:9771', 'http://localhost:3000']
    }
  }
})

// Rate Limiting: 1분당 10,000 요청 (개발), 100 요청 (운영)
rateLimit({
  windowMs: 1 * 60 * 1000,
  max: process.env.NODE_ENV === 'development' ? 10000 : 100,
  skip: (req) => {
    // 헬스 체크, 자주 호출되는 API는 제외
    return req.path === '/health' 
        || req.path.includes('/table-management/')
        || req.path.includes('/external-db-connections/')
  }
})

// CORS: 환경별 origin 설정
cors({
  origin: process.env.NODE_ENV === 'development' 
    ? true 
    : ['http://localhost:9771', 'http://39.117.244.52:5555'],
  credentials: true
})

6. 서비스 레이어 패턴

6.1 서비스 레이어 구조

Controller (요청 처리)
    ↓
Service (비즈니스 로직)
    ↓
Database (Raw Query 실행)
    ↓
PostgreSQL (데이터 저장소)

6.2 데이터베이스 접근 방식

db.ts - Raw Query 매니저

// 기본 쿼리 실행
async function query<T>(text: string, params?: any[]): Promise<T[]>

// 단일 행 조회
async function queryOne<T>(text: string, params?: any[]): Promise<T | null>

// 트랜잭션
async function transaction<T>(callback: (client: PoolClient) => Promise<T>): Promise<T>

// 연결 풀 상태
function getPoolStatus(): { totalCount, idleCount, waitingCount }

Connection Pool 설정

new Pool({
  host: dbConfig.host,
  port: dbConfig.port,
  database: dbConfig.database,
  user: dbConfig.user,
  password: dbConfig.password,
  
  // 연결 풀 설정
  min: process.env.NODE_ENV === 'production' ? 5 : 2,
  max: process.env.NODE_ENV === 'production' ? 20 : 10,
  
  // 타임아웃 설정
  connectionTimeoutMillis: 30000,  // 30초
  idleTimeoutMillis: 600000,       // 10분
  statement_timeout: 60000,        // 60초
  query_timeout: 60000,
  
  application_name: 'WACE-PLM-Backend'
})

6.3 서비스 패턴 예시

멀티테넌시 쿼리 패턴

// Super Admin: 모든 데이터 조회
if (companyCode === '*') {
  query = 'SELECT * FROM table_name ORDER BY company_code';
  params = [];
}
// 일반 사용자: 자사 데이터만 조회 (Super Admin 데이터 제외)
else {
  query = `
    SELECT * FROM table_name 
    WHERE company_code = $1 AND company_code != '*'
    ORDER BY created_at DESC
  `;
  params = [companyCode];
}

트랜잭션 패턴

await transaction(async (client) => {
  // 1. 부모 레코드 삽입
  const parent = await client.query(
    'INSERT INTO parent_table (...) VALUES (...) RETURNING *',
    [...]
  );
  
  // 2. 자식 레코드 삽입
  await client.query(
    'INSERT INTO child_table (parent_id, ...) VALUES ($1, ...) RETURNING *',
    [parent.rows[0].id, ...]
  );
  
  return { success: true };
});

캐시 패턴

// 캐시 조회
const cachedData = cache.get<T>(CacheKeys.TABLE_LIST);
if (cachedData) {
  return cachedData;
}

// DB 조회
const data = await query<T>('SELECT ...');

// 캐시 저장 (10분 TTL)
cache.set(CacheKeys.TABLE_LIST, data, 10 * 60 * 1000);

return data;

6.4 외부 DB 커넥터 패턴

// DatabaseConnectorFactory.ts
export class DatabaseConnectorFactory {
  static createConnector(dbType: string, config: ConnectionConfig): DatabaseConnector {
    switch (dbType) {
      case 'postgresql': return new PostgreSQLConnector(config);
      case 'mysql': return new MySQLConnector(config);
      case 'mssql': return new MSSQLConnector(config);
      case 'oracle': return new OracleConnector(config);
      case 'mariadb': return new MariaDBConnector(config);
      default: throw new Error(`Unsupported DB type: ${dbType}`);
    }
  }
}

// 사용 예시
const connector = DatabaseConnectorFactory.createConnector('mysql', config);
await connector.connect();
const result = await connector.executeQuery('SELECT * FROM users');
await connector.disconnect();

7. 멀티테넌시 구현 방식

7.1 핵심 원칙

CRITICAL PROJECT RULES:

  1. 모든 쿼리는 company_code 필터 필수
  2. req.user!.companyCode 사용 (클라이언트 전송 값 신뢰 금지)
  3. Super Admin (company_code = '*')만 전체 데이터 조회
  4. 일반 사용자는 company_code = '*' 데이터 조회 불가

7.2 쿼리 패턴

const companyCode = req.user!.companyCode;

// Super Admin: 모든 회사 데이터 조회
if (companyCode === '*') {
  query = 'SELECT * FROM users ORDER BY company_code';
  params = [];
}
// 일반 사용자: 자사 데이터만 조회 (Super Admin 제외)
else {
  query = `
    SELECT * FROM users 
    WHERE company_code = $1 AND company_code != '*'
  `;
  params = [companyCode];
}

7.3 테이블 설계

-- 모든 비즈니스 테이블에 company_code 컬럼 필수
CREATE TABLE table_name (
  id SERIAL PRIMARY KEY,
  company_code VARCHAR(50) NOT NULL,  -- 회사 코드
  ...
  INDEX idx_company_code (company_code)
);

-- Super Admin 데이터: company_code = '*'
-- 회사별 데이터: company_code = '회사코드'

7.4 회사 전환 (Super Admin 전용)

// POST /api/auth/switch-company
{
  targetCompanyCode: "ILSHIN"  // 전환할 회사 코드
}

// 응답
{
  success: true,
  token: "새로운 JWT 토큰",  // companyCode가 변경된 토큰
  userInfo: { companyCode: "ILSHIN", ... }
}

7.5 권한 체크

// 회사 데이터 접근 권한 확인
export function canAccessCompanyData(user: PersonBean, targetCompanyCode: string): boolean {
  // Super Admin: 모든 회사 접근 가능
  if (user.companyCode === '*') {
    return true;
  }
  
  // 일반 사용자: 자사만 접근 가능
  return user.companyCode === targetCompanyCode;
}

8. 에러 핸들링 전략

8.1 에러 핸들링 구조

Controller (try-catch)
    ↓ 에러 발생
Service (throw error)
    ↓
errorHandler (미들웨어)
    ├─ PostgreSQL 에러 처리
    ├─ JWT 에러 처리
    ├─ 커스텀 에러 처리 (AppError)
    └─ 응답 전송 (JSON)

8.2 커스텀 에러 클래스

export class AppError extends Error {
  public statusCode: number;
  public isOperational: boolean;

  constructor(message: string, statusCode: number = 500) {
    super(message);
    this.statusCode = statusCode;
    this.isOperational = true;
  }
}

// 사용 예시
throw new AppError('중복된 데이터가 존재합니다.', 400);

8.3 PostgreSQL 에러 처리

// errorHandler.ts
if (pgError.code === '23505') {  // unique_violation
  error = new AppError('중복된 데이터가 존재합니다.', 400);
} else if (pgError.code === '23503') {  // foreign_key_violation
  error = new AppError('참조 무결성 제약 조건 위반입니다.', 400);
} else if (pgError.code === '23502') {  // not_null_violation
  error = new AppError('필수 입력값이 누락되었습니다.', 400);
}

8.4 에러 응답 형식

{
  "success": false,
  "error": {
    "code": "UNIQUE_VIOLATION",
    "message": "중복된 데이터가 존재합니다.",
    "details": "사용자 ID가 이미 존재합니다.",
    "stack": "..." // 개발 환경에서만 포함
  }
}

8.5 에러 로깅

// logger.ts (Winston 기반)
logger.error({
  message: error.message,
  stack: error.stack,
  url: req.url,
  method: req.method,
  ip: req.ip,
  userAgent: req.get('User-Agent')
});

8.6 프로세스 레벨 예외 처리

// app.ts
process.on('unhandledRejection', (reason, promise) => {
  logger.error('⚠️ Unhandled Promise Rejection:', reason);
  // 프로세스 종료하지 않고 로깅만 수행
});

process.on('uncaughtException', (error) => {
  logger.error('🔥 Uncaught Exception:', error);
  // 심각한 에러 시 graceful shutdown 고려
});

9. 파일 업로드/다운로드 처리

9.1 파일 업로드

파일: fileController.ts, fileRoutes.ts

// Multer 설정
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'uploads/');
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
  }
});

const upload = multer({
  storage,
  limits: { fileSize: 10 * 1024 * 1024 },  // 10MB
  fileFilter: (req, file, cb) => {
    // 허용된 확장자 체크
    const allowedTypes = /jpeg|jpg|png|gif|pdf|doc|docx|xls|xlsx/;
    const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
    const mimetype = allowedTypes.test(file.mimetype);
    
    if (mimetype && extname) {
      return cb(null, true);
    } else {
      cb(new Error('허용되지 않는 파일 형식입니다.'));
    }
  }
});

// 라우트
router.post('/upload', authenticateToken, upload.single('file'), uploadFile);
router.post('/upload-multiple', authenticateToken, upload.array('files', 10), uploadMultipleFiles);

9.2 파일 다운로드

// 정적 파일 서빙 (app.ts)
app.use('/uploads', 
  (req, res, next) => {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
    res.setHeader('Cache-Control', 'public, max-age=3600');
    next();
  },
  express.static(path.join(process.cwd(), 'uploads'))
);

// 다운로드 엔드포인트
router.get('/download/:filename', authenticateToken, async (req, res) => {
  const filename = req.params.filename;
  const filePath = path.join(process.cwd(), 'uploads', filename);
  
  if (!fs.existsSync(filePath)) {
    return res.status(404).json({ error: '파일을 찾을 수 없습니다.' });
  }
  
  res.download(filePath);
});

9.3 화면별 파일 관리

파일: screenFileController.ts, screenFileService.ts

// 화면별 파일 업로드
router.post('/screens/:screenId/files', authenticateToken, upload.single('file'), uploadScreenFile);

// 화면별 파일 목록 조회
router.get('/screens/:screenId/files', authenticateToken, getScreenFiles);

// 파일 삭제
router.delete('/screens/:screenId/files/:fileId', authenticateToken, deleteScreenFile);

10. 외부 연동

10.1 외부 DB 연결

지원 DB: PostgreSQL, MySQL, MSSQL, Oracle, MariaDB

파일:

  • externalDbConnectionService.ts
  • PostgreSQLConnector.ts, MySQLConnector.ts, MSSQLConnector.ts, OracleConnector.ts, MariaDBConnector.ts
// 외부 DB 연결 설정
{
  connection_name: "외부 ERP DB",
  db_type: "mysql",
  host: "192.168.0.100",
  port: 3306,
  database: "erp_db",
  username: "erp_user",
  password: "encrypted_password",  // AES-256-CBC 암호화
  company_code: "ILSHIN",
  is_active: "Y"
}

// 연결 테스트
POST /api/external-db-connections/:id/test
{
  success: true,
  message: "연결 테스트 성공"
}

// 쿼리 실행
POST /api/external-db-connections/:id/query
{
  query: "SELECT * FROM products WHERE category = ?",
  params: ["전자제품"]
}

10.2 외부 REST API 연결

파일: externalRestApiConnectionService.ts

// 외부 REST API 연결 설정
{
  connection_name: "날씨 API",
  base_url: "https://api.weather.com",
  auth_type: "bearer",  // bearer, api-key, basic, oauth2
  auth_credentials: {
    token: "encrypted_token"
  },
  headers: {
    "Content-Type": "application/json"
  },
  company_code: "ILSHIN"
}

// API 호출
POST /api/external-rest-api-connections/:id/call
{
  method: "GET",
  endpoint: "/weather",
  params: { city: "Seoul" }
}

10.3 멀티 DB 통합 쿼리

파일: multiConnectionQueryService.ts

// 여러 DB에서 동시 쿼리 실행
POST /api/multi-connection/query
{
  connections: [
    {
      connectionId: 1,
      query: "SELECT * FROM orders WHERE status = 'pending'"
    },
    {
      connectionId: 2,
      query: "SELECT * FROM inventory WHERE quantity < 10"
    }
  ]
}

// 응답
{
  success: true,
  results: [
    { connectionId: 1, data: [...], rowCount: 15 },
    { connectionId: 2, data: [...], rowCount: 8 }
  ]
}

10.4 Open API Proxy

파일: openApiProxyController.ts

// 날씨 API
GET /api/open-api/weather?city=Seoul

// 환율 API
GET /api/open-api/exchange-rate?from=USD&to=KRW

11. 배치/스케줄 처리

11.1 배치 스케줄러

파일: batchSchedulerService.ts

// 배치 설정
{
  batch_name: "일일 재고 동기화",
  batch_type: "external_db",  // external_db, rest_api, internal
  cron_schedule: "0 2 * * *",  // 매일 새벽 2시
  source_connection_id: 1,
  source_query: "SELECT * FROM inventory",
  target_table: "inventory_sync",
  mapping: {
    product_id: "item_id",
    quantity: "stock_qty"
  },
  is_active: "Y"
}

// 스케줄러 초기화 (서버 시작 시)
await BatchSchedulerService.initializeScheduler();

// 배치 수동 실행
POST /api/batch-configs/:id/execute

11.2 Cron 기반 자동 실행

// node-cron 사용
const task = cron.schedule(
  config.cron_schedule,  // "0 2 * * *"
  async () => {
    logger.info(`배치 실행 시작: ${config.batch_name}`);
    await executeBatchConfig(config);
  },
  { timezone: 'Asia/Seoul' }
);

// 스케줄 업데이트
await BatchSchedulerService.updateBatchSchedule(configId);

// 스케줄 제거
await BatchSchedulerService.removeBatchSchedule(configId);

11.3 배치 실행 로그

파일: batchExecutionLogService.ts

// 배치 실행 이력
{
  batch_config_id: 1,
  execution_status: "success",  // success, failed, running
  start_time: "2024-12-24T02:00:00Z",
  end_time: "2024-12-24T02:05:23Z",
  rows_processed: 1523,
  rows_inserted: 1200,
  rows_updated: 300,
  rows_failed: 23,
  error_message: null,
  execution_log: "..."
}

// 배치 이력 조회
GET /api/batch-execution-logs?batch_config_id=1&page=1&limit=10

11.4 자동 스케줄 작업

파일: app.ts

// 메일 자동 삭제 (매일 새벽 2시)
cron.schedule('0 2 * * *', async () => {
  logger.info('🗑️ 30일 지난 삭제된 메일 자동 삭제 시작...');
  const deletedCount = await mailSentHistoryService.cleanupOldDeletedMails();
  logger.info(`✅ 30일 지난 메일 ${deletedCount}개 자동 삭제 완료`);
});

// 리스크/알림 자동 갱신 (10분 간격)
const cacheService = RiskAlertCacheService.getInstance();
cacheService.startAutoRefresh();

12. 컨트롤러/서비스 상세 역할

12.1 인증 및 관리자

authController.ts / authService.ts

  • 로그인: 비밀번호 검증, JWT 토큰 발급, 로그인 로그 기록
  • 회원가입: 공차중계 사용자 등록
  • 토큰 갱신: accessToken, refreshToken 갱신
  • 현재 사용자 정보: JWT 기반 사용자 정보 조회
  • 로그아웃: 토큰 무효화 (클라이언트 측 처리)
  • 회사 전환: Super Admin 전용 회사 전환

adminController.ts / adminService.ts

  • 메뉴 관리: 메뉴 트리 조회, 메뉴 CRUD, 메뉴 복사, 상태 토글, 일괄 삭제
  • 사용자 관리: 사용자 목록, 사용자 CRUD, 상태 변경, 비밀번호 초기화, 변경 이력
  • 회사 관리: 회사 목록, 회사 CRUD (Super Admin 전용)
  • 부서 관리: 부서 목록, 사용자-부서 통합 저장
  • 로케일 설정: 사용자 언어 설정 (ko, en)
  • 테이블 스키마: 엑셀 업로드 컬럼 매핑용 스키마 조회

12.2 테이블 및 데이터

tableManagementController.ts / tableManagementService.ts

  • 테이블 목록: PostgreSQL information_schema 조회
  • 컬럼 정보: 컬럼 타입, 제약조건, 라벨, 참조 관계
  • 컬럼 라벨 관리: 다국어 라벨, 표시 순서, 표시 여부
  • 컬럼 설정: 입력 타입, 코드 카테고리, 필수 여부, 기본값
  • 테이블 조회 설정: 조회 컬럼, 정렬 순서, 필터 조건
  • 캐시 관리: 테이블/컬럼 정보 캐시 (10분 TTL)

dataController.ts / dataService.ts

  • 동적 데이터 조회: 테이블명 기반 데이터 조회 (페이지네이션, 필터, 정렬)
  • 동적 데이터 생성: INSERT 쿼리 자동 생성
  • 동적 데이터 수정: UPDATE 쿼리 자동 생성
  • 동적 데이터 삭제: DELETE 쿼리 자동 생성 (논리 삭제 지원)
  • 멀티테넌시 자동 필터링: company_code 자동 추가

entityJoinController.ts / entityJoinService.ts

  • 조인 설정 관리: 테이블 간 조인 관계 설정 (1:N, N:M)
  • 조인 쿼리 실행: 설정된 조인 관계 기반 데이터 조회
  • 참조 데이터 캐싱: 자주 사용되는 참조 데이터 캐시

12.3 화면 관리

screenManagementController.ts / screenManagementService.ts

  • 화면 메타데이터 관리: 화면 설정 (테이블, 컬럼, 레이아웃)
  • 화면 목록 조회: 회사별, 화면 그룹별 필터링
  • 화면 복사: 화면 설정 복제
  • 화면 삭제: 논리 삭제
  • 화면 설정 조회: 화면 메타데이터 상세 조회

dynamicFormController.ts / dynamicFormService.ts

  • 동적 폼 생성: JSON 기반 폼 설정 → React 컴포넌트
  • 폼 유효성 검사: 필수 입력, 데이터 타입, 길이 제한
  • 폼 제출: 데이터 저장 (INSERT/UPDATE)

buttonActionStandardController.ts / buttonActionStandardService.ts

  • 버튼 액션 표준: 저장, 삭제, 조회, 엑셀 다운로드, 커스텀 액션
  • 버튼 액션 설정: 액션 타입, 파라미터, 권한 설정

12.4 플로우 및 데이터플로우

flowController.ts / flowService.ts

  • 플로우 정의: 플로우 생성, 수정, 삭제, 조회
  • 플로우 단계: 단계 생성, 수정, 삭제, 순서 변경
  • 플로우 연결: 단계 간 연결 (조건부 분기)
  • 데이터 이동: 단계 간 데이터 이동 (단일/배치)
  • 오딧 로그: 플로우 실행 이력 조회

dataflowController.ts / dataflowService.ts

  • 테이블 관계 정의: 테이블 간 관계 설정 (1:1, 1:N, N:M)
  • 데이터플로우 다이어그램: ERD 같은 시각화
  • 데이터플로우 실행: 관계 기반 데이터 동기화
  • 관계 조회: 다이어그램별 관계 목록

12.5 배치 관리

batchController.ts / batchService.ts

  • 배치 설정 관리: 배치 CRUD
  • 배치 실행: 수동 실행, 스케줄 실행
  • 배치 이력: 실행 로그, 성공/실패 통계
  • 커넥션 조회: 사용 가능한 외부 DB/API 목록

batchSchedulerService.ts

  • 스케줄러 초기화: 서버 시작 시 활성 배치 등록
  • 스케줄 등록: Cron 표현식 기반 스케줄 등록
  • 스케줄 업데이트: 배치 설정 변경 시 스케줄 재등록
  • 스케줄 제거: 배치 삭제 시 스케줄 제거

batchExternalDbService.ts

  • 외부 DB 배치: 외부 DB → 내부 DB 데이터 동기화
  • 컬럼 매핑: 소스-타겟 컬럼 매핑
  • 데이터 변환: 타입 변환, 값 변환

12.6 외부 연동

externalDbConnectionController.ts / externalDbConnectionService.ts

  • 외부 DB 연결 관리: 연결 CRUD
  • 연결 테스트: 연결 유효성 검증
  • 쿼리 실행: 외부 DB 쿼리 실행
  • 테이블 목록: 외부 DB 테이블 목록 조회
  • 컬럼 정보: 외부 DB 컬럼 정보 조회

externalRestApiConnectionController.ts / externalRestApiConnectionService.ts

  • REST API 연결 관리: API 연결 CRUD
  • API 호출: 외부 API 호출 (GET, POST, PUT, DELETE)
  • 인증 처리: Bearer, API Key, Basic, OAuth2
  • 응답 캐싱: API 응답 캐싱 (TTL 설정)

multiConnectionQueryService.ts

  • 멀티 DB 통합 쿼리: 여러 DB에서 동시 쿼리 실행
  • 결과 병합: 여러 DB 쿼리 결과 병합
  • 오류 처리: 부분 실패 시 에러 로그 기록

12.7 메일 관리

mailAccountFileController.ts / mailAccountFileService.ts

  • 메일 계정 관리: SMTP/IMAP 계정 CRUD
  • 계정 테스트: 연결 유효성 검증
  • 계정 상태: 활성/비활성 상태 관리

mailTemplateFileController.ts / mailTemplateFileService.ts

  • 메일 템플릿 관리: 템플릿 CRUD
  • 템플릿 컴포넌트: JSON 기반 컴포넌트 조합 (헤더, 본문, 버튼, 푸터)
  • 변수 치환: {변수명} 형태의 변수 치환

mailSendSimpleController.ts / mailSendSimpleService.ts

  • 메일 발송: 단일 발송, 대량 발송 (100건/배치)
  • 첨부파일: 다중 첨부파일 지원
  • 참조/숨은참조: CC, BCC 지원
  • 발송 이력: 발송 성공/실패 로그 기록

mailSentHistoryController.ts / mailSentHistoryService.ts

  • 발송 이력 조회: 페이지네이션, 필터링, 검색
  • 이력 삭제: 논리 삭제 (30일 후 물리 삭제)
  • 자동 삭제: Cron 기반 자동 삭제 (매일 새벽 2시)

mailReceiveBasicController.ts / mailReceiveBasicService.ts

  • 메일 수신: IMAP 기반 메일 수신
  • 메일 목록: 수신함 목록 조회
  • 메일 읽기: 메일 상세 조회, 첨부파일 다운로드

12.8 대시보드 및 리포트

DashboardController.ts / DashboardService.ts

  • 대시보드 위젯: 차트, 테이블, 카드 위젯
  • 실시간 데이터: 집계 쿼리 기반 실시간 데이터 조회
  • 사용자 설정: 사용자별 대시보드 레이아웃 저장

reportController.ts / reportService.ts

  • 리포트 생성: 동적 리포트 생성 (PDF, Excel, Word)
  • 리포트 템플릿: 템플릿 기반 리포트 생성
  • 리포트 스케줄: 정기 리포트 자동 생성 및 메일 발송

12.9 기타 도메인

deliveryController.ts / deliveryService.ts

  • 배송 관리: 배송 정보 등록, 조회, 수정
  • 화물 추적: 배송 상태 추적

riskAlertController.ts / riskAlertService.ts / riskAlertCacheService.ts

  • 리스크 알림: 리스크 기준 설정, 알림 발생
  • 자동 갱신: 10분 간격 자동 갱신 (캐시 기반)

todoController.ts / todoService.ts

  • To-Do 관리: 할 일 CRUD, 상태 변경 (대기, 진행, 완료)

bookingController.ts / bookingService.ts

  • 예약 관리: 예약 요청 CRUD, 승인/거부

digitalTwinController.ts / digitalTwinLayoutController.ts / digitalTwinDataController.ts

  • 디지털 트윈: 야드 관제, 3D 레이아웃, 실시간 데이터 시각화

scheduleController.ts / scheduleService.ts

  • 스케줄 자동 생성: 작업 스케줄 자동 생성 (규칙 기반)

workHistoryController.ts / workHistoryService.ts

  • 작업 이력: 작업 로그 조회, 필터링, 검색

roleController.ts / roleService.ts

  • 권한 그룹: 권한 그룹 CRUD, 사용자-권한 매핑

numberingRuleController.ts / numberingRuleService.ts

  • 채번 규칙: 자동 채번 규칙 설정 (접두사, 연번, 접미사)

entitySearchController.ts / entitySearchService.ts

  • 엔티티 검색: 동적 엔티티 검색 (테이블, 컬럼, 조건 기반)

cascadingController.ts 시리즈

  • 연쇄 드롭다운: 조건부 드롭다운 관계 설정
  • 자동 입력: 연쇄 자동 입력 관계 설정
  • 상호 배제: 상호 배타적 선택 관계 설정
  • 다단계 계층: 계층 구조 관계 설정

📊 통계 요약

구분 개수
컨트롤러 69개
서비스 87개
라우터 77개
미들웨어 4개
엔드포인트 200개 이상
데이터베이스 커넥터 5종 (PostgreSQL, MySQL, MSSQL, Oracle, MariaDB)
유틸리티 16개
타입 정의 26개

🔧 기술 스택

{
  "런타임": "Node.js 20.10.0+",
  "언어": "TypeScript 5.3.3",
  "프레임워크": "Express 4.18.2",
  "데이터베이스": "PostgreSQL (pg 8.16.3)",
  "인증": "JWT (jsonwebtoken 9.0.2)",
  "암호화": "BCrypt (bcryptjs 2.4.3)",
  "로깅": "Winston 3.11.0",
  "스케줄링": "node-cron 4.2.1",
  "메일": "Nodemailer 6.10.1 + IMAP 0.8.19",
  "파일 업로드": "Multer 1.4.5",
  "보안": "Helmet 7.1.0",
  "외부 DB": "mysql2, mssql, oracledb",
  "캐싱": "In-Memory Cache (Map 기반)",
  "압축": "compression 1.7.4",
  "Rate Limiting": "express-rate-limit 7.1.5"
}

📁 핵심 파일 경로

backend-node/
├── src/
│   ├── app.ts                                      # 앱 진입점
│   ├── config/environment.ts                       # 환경변수 설정
│   ├── database/
│   │   ├── db.ts                                   # Raw Query 매니저
│   │   ├── DatabaseConnectorFactory.ts             # DB 커넥터 팩토리
│   │   └── [DB]Connector.ts                        # 각 DB별 커넥터
│   ├── middleware/
│   │   ├── authMiddleware.ts                       # JWT 인증
│   │   ├── permissionMiddleware.ts                 # 권한 체크
│   │   ├── superAdminMiddleware.ts                 # Super Admin 체크
│   │   └── errorHandler.ts                         # 에러 핸들링
│   ├── utils/
│   │   ├── logger.ts                               # Winston 로거
│   │   ├── jwtUtils.ts                             # JWT 유틸
│   │   ├── encryptUtil.ts                          # BCrypt 암호화
│   │   ├── passwordEncryption.ts                   # AES 암호화
│   │   ├── cache.ts                                # 캐시 유틸
│   │   └── permissionUtils.ts                      # 권한 유틸
│   └── types/
│       ├── auth.ts                                 # 인증 타입
│       ├── tableManagement.ts                      # 테이블 관리 타입
│       └── ...
└── package.json                                    # 의존성 관리

🚀 서버 시작 프로세스

1. dotenv 환경변수 로드
2. Express 앱 생성
3. 미들웨어 설정 (helmet, cors, compression, rate-limit)
4. 데이터베이스 연결 풀 초기화
5. 라우터 등록 (77개 라우터)
6. 에러 핸들러 등록
7. 서버 리스닝 (기본 포트: 8080)
8. 데이터베이스 마이그레이션 실행
9. 배치 스케줄러 초기화
10. 리스크/알림 자동 갱신 시작
11. 메일 자동 삭제 스케줄러 시작

🔒 보안 고려사항

  1. JWT 기반 인증: 세션 없이 무상태(Stateless) 인증
  2. 비밀번호 암호화: BCrypt (12 rounds)
  3. 외부 DB 크레덴셜 암호화: AES-256-CBC
  4. SQL Injection 방지: Parameterized Query 필수
  5. XSS 방지: Helmet 보안 헤더
  6. CSRF 방지: CORS 설정 + JWT
  7. Rate Limiting: 1분당 요청 수 제한
  8. DDL 실행 제한: Super Admin만 가능 + 5초 간격 제한
  9. 멀티테넌시 격리: company_code 자동 필터링
  10. 에러 정보 노출 방지: 운영 환경에서 스택 트레이스 숨김

📝 추천 개선 사항

  1. API 문서화: Swagger/OpenAPI 자동 생성
  2. 단위 테스트: Jest 기반 테스트 커버리지 확대
  3. Redis 캐싱: In-Memory 캐시 → Redis 전환
  4. 로그 중앙화: Winston → ELK Stack 연동
  5. 성능 모니터링: APM 도구 연동 (New Relic, Datadog)
  6. Docker 컨테이너화: Dockerfile 및 docker-compose 개선
  7. CI/CD 파이프라인: GitHub Actions, Jenkins 연동
  8. API Rate Limiting 세분화: 엔드포인트별 제한 설정
  9. WebSocket 지원: 실시간 알림 및 데이터 업데이트
  10. GraphQL API: REST API + GraphQL 병행 지원

문서 작성자: WACE 백엔드 전문가
최종 수정일: 2026-02-06
버전: 1.0.0