# WACE ERP 시스템 전체 워크플로우 문서 > 작성일: 2026-02-06 > 분석 방법: Multi-Agent System (Backend + Frontend + DB 전문가 병렬 분석) --- ## 목차 1. [시스템 개요](#1-시스템-개요) 2. [기술 스택](#2-기술-스택) 3. [전체 아키텍처](#3-전체-아키텍처) 4. [백엔드 아키텍처](#4-백엔드-아키텍처) 5. [프론트엔드 아키텍처](#5-프론트엔드-아키텍처) 6. [데이터베이스 구조](#6-데이터베이스-구조) 7. [인증/인가 워크플로우](#7-인증인가-워크플로우) 8. [화면 디자이너 워크플로우](#8-화면-디자이너-워크플로우) 9. [사용자 업무 워크플로우](#9-사용자-업무-워크플로우) 10. [플로우 엔진 워크플로우](#10-플로우-엔진-워크플로우) 11. [데이터플로우 시스템](#11-데이터플로우-시스템) 12. [대시보드 시스템](#12-대시보드-시스템) 13. [배치/스케줄 시스템](#13-배치스케줄-시스템) 14. [멀티테넌시 아키텍처](#14-멀티테넌시-아키텍처) 15. [외부 연동](#15-외부-연동) 16. [배포 환경](#16-배포-환경) --- ## 1. 시스템 개요 WACE는 **로우코드(Low-Code) ERP 플랫폼**이다. 관리자가 코드 없이 드래그앤드롭으로 업무 화면을 설계하면, 사용자는 해당 화면으로 바로 업무를 처리할 수 있는 구조다. ### 핵심 컨셉 ``` 관리자 → 화면 디자이너로 화면 설계 → 메뉴에 연결 ↓ 사용자 → 메뉴 클릭 → 화면 자동 렌더링 → 업무 수행 ``` ### 주요 특징 - **드래그앤드롭 화면 디자이너**: 코드 없이 UI 구성 - **동적 컴포넌트 시스템**: V2 통합 컴포넌트 10종으로 모든 UI 표현 - **플로우 엔진**: 워크플로우(승인, 이동 등) 자동화 - **데이터플로우**: 비즈니스 로직을 비주얼 다이어그램으로 설계 - **멀티테넌시**: 회사별 완벽한 데이터 격리 - **다국어 지원**: KR/EN/CN 다국어 라벨 관리 --- ## 2. 기술 스택 | 영역 | 기술 | 비고 | |------|------|------| | **Frontend** | Next.js 15 (App Router) | React 19, TypeScript | | **UI 라이브러리** | shadcn/ui + Radix UI | Tailwind CSS 4 | | **상태 관리** | React Context + Zustand | React Query (서버 상태) | | **Backend** | Node.js + Express | TypeScript | | **Database** | PostgreSQL | Raw Query (ORM 미사용) | | **인증** | JWT | 자동 갱신, 세션 관리 | | **빌드/배포** | Docker | dev/prod 분리 | | **포트** | FE: 9771(dev)/5555(prod) | BE: 8080 | --- ## 3. 전체 아키텍처 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 사용자 브라우저 │ │ Next.js App (React 19 + shadcn/ui + Tailwind CSS) │ │ ├── 인증: JWT + Cookie + localStorage │ │ ├── 상태: Context + Zustand + React Query │ │ └── API: Axios Client (lib/api/) │ └──────────────────────────┬──────────────────────────────────────┘ │ HTTP/JSON (JWT Bearer Token) ↓ ┌─────────────────────────────────────────────────────────────────┐ │ Express Backend (Node.js) │ │ ├── Middleware: Helmet → CORS → RateLimit → Auth → Permission │ │ ├── Routes: 60+ 모듈 │ │ ├── Controllers: 69개 │ │ ├── Services: 87개 │ │ └── Database: pg Pool (Raw Query) │ └──────────────────────────┬──────────────────────────────────────┘ │ TCP/SQL ↓ ┌─────────────────────────────────────────────────────────────────┐ │ PostgreSQL Database │ │ ├── 시스템 테이블: 사용자, 회사, 메뉴, 권한, 화면 │ │ ├── 메타데이터: 테이블/컬럼 정의, 코드, 카테고리 │ │ ├── 비즈니스: 동적 생성 테이블 (화면별) │ │ └── 멀티테넌시: 모든 테이블에 company_code │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 4. 백엔드 아키텍처 ### 4.1 디렉토리 구조 ``` backend-node/src/ ├── app.ts # Express 앱 진입점 ├── config/ # 환경설정, Multer ├── controllers/ # 69개 컨트롤러 ├── services/ # 87개 서비스 ├── routes/ # 60+ 라우트 모듈 ├── middleware/ # 인증, 권한, 에러 처리 │ ├── authMiddleware.ts # JWT 인증 │ ├── permissionMiddleware.ts # 3단계 권한 체크 │ ├── superAdminMiddleware.ts # 슈퍼관리자 전용 │ └── errorHandler.ts # 전역 에러 처리 ├── database/ # DB 연결, 커넥터 팩토리 │ ├── db.ts # PostgreSQL Pool │ ├── DatabaseConnectorFactory.ts │ ├── PostgreSQLConnector.ts │ ├── MySQLConnector.ts │ └── MariaDBConnector.ts ├── types/ # TypeScript 타입 (26개) └── utils/ # 유틸리티 (16개) ``` ### 4.2 미들웨어 스택 (실행 순서) ``` 요청 → Helmet (보안 헤더) → Compression (응답 압축) → Body Parser (JSON/URLEncoded, 10MB) → CORS (교차 출처 허용) → Rate Limiter (10,000 req/min) → Token Refresh (자동 갱신) → Route Handlers (비즈니스 로직) → Error Handler (전역 에러 처리) ``` ### 4.3 API 라우트 도메인별 분류 #### 인증/사용자 관리 | 라우트 | 역할 | |--------|------| | `/api/auth` | 로그인, 로그아웃, 토큰 갱신, 회사 전환 | | `/api/admin/users` | 사용자 CRUD, 비밀번호 초기화, 상태 변경 | | `/api/company-management` | 회사 CRUD | | `/api/departments` | 부서 관리 | | `/api/roles` | 권한 그룹 관리 | #### 화면/메뉴 관리 | 라우트 | 역할 | |--------|------| | `/api/screen-management` | 화면 정의 CRUD, 그룹, 파일, 임베딩 | | `/api/admin/menus` | 메뉴 트리 CRUD, 화면 할당 | | `/api/table-management` | 테이블 CRUD, 엔티티 조인, 카테고리 | | `/api/common-codes` | 공통 코드/카테고리 관리 | | `/api/multilang` | 다국어 키/번역 관리 | #### 데이터 관리 | 라우트 | 역할 | |--------|------| | `/api/data` | 동적 테이블 CRUD, 조인 쿼리 | | `/api/data/:tableName` | 특정 테이블 데이터 조회 | | `/api/data/join` | 조인 쿼리 실행 | | `/api/dynamic-form` | 동적 폼 데이터 저장 | | `/api/entity-search` | 엔티티 검색 | | `/api/entity-reference` | 엔티티 참조 | | `/api/numbering-rules` | 채번 규칙 관리 | | `/api/cascading-*` | 연쇄 드롭다운 관계 | #### 자동화 | 라우트 | 역할 | |--------|------| | `/api/flow` | 플로우 정의/단계/연결/실행 | | `/api/dataflow` | 데이터플로우 다이어그램/실행 | | `/api/batch-configs` | 배치 작업 설정 | | `/api/batch-management` | 배치 작업 관리 | | `/api/batch-execution-logs` | 배치 실행 로그 | #### 대시보드/리포트 | 라우트 | 역할 | |--------|------| | `/api/dashboards` | 대시보드 CRUD, 쿼리 실행 | | `/api/reports` | 리포트 생성 | #### 외부 연동 | 라우트 | 역할 | |--------|------| | `/api/external-db-connections` | 외부 DB 연결 (PostgreSQL, MySQL, MariaDB, MSSQL, Oracle) | | `/api/external-rest-api-connections` | 외부 REST API 연결 | | `/api/mail` | 메일 발송/수신/템플릿 | | `/api/tax-invoice` | 세금계산서 | #### 특수 도메인 | 라우트 | 역할 | |--------|------| | `/api/delivery` | 배송/화물 관리 | | `/api/risk-alerts` | 위험 알림 | | `/api/todos` | 할일 관리 | | `/api/bookings` | 예약 관리 | | `/api/digital-twin` | 디지털 트윈 (야드 모니터링) | | `/api/schedule` | 스케줄 자동 생성 | | `/api/vehicle` | 차량 운행 | | `/api/driver` | 운전자 관리 | | `/api/files` | 파일 업로드/다운로드 | | `/api/ddl` | DDL 실행 (슈퍼관리자 전용) | ### 4.4 서비스 레이어 패턴 ```typescript // 표준 서비스 패턴 class ExampleService { // 목록 조회 (멀티테넌시 적용) async findAll(companyCode: string, filters?: any) { if (companyCode === "*") { // 슈퍼관리자: 전체 데이터 return await db.query("SELECT * FROM table ORDER BY company_code"); } else { // 일반 사용자: 자기 회사 데이터만 return await db.query( "SELECT * FROM table WHERE company_code = $1", [companyCode] ); } } } ``` ### 4.5 에러 처리 전략 ```typescript // 전역 에러 핸들러 (errorHandler.ts) - PostgreSQL 에러: 중복키(23505), 외래키(23503), 널 제약(23502) 등 - JWT 에러: 만료, 유효하지 않은 토큰 - 일반 에러: 500 Internal Server Error - 개발 환경: 상세 에러 스택 포함 - 운영 환경: 일반적인 에러 메시지만 반환 ``` --- ## 5. 프론트엔드 아키텍처 ### 5.1 디렉토리 구조 ``` frontend/ ├── app/ # Next.js App Router │ ├── (auth)/ # 인증 (로그인) │ ├── (main)/ # 메인 앱 (인증 필요) │ ├── (pop)/ # 모바일/팝업 │ └── (admin)/ # 특수 관리자 ├── components/ # React 컴포넌트 │ ├── screen/ # 화면 디자이너 & 뷰어 │ ├── admin/ # 관리 기능 │ ├── dashboard/ # 대시보드 위젯 │ ├── dataflow/ # 데이터플로우 디자이너 │ ├── v2/ # V2 통합 컴포넌트 │ ├── ui/ # shadcn/ui 기본 컴포넌트 │ └── report/ # 리포트 디자이너 ├── lib/ │ ├── api/ # API 클라이언트 (57개 모듈) │ ├── registry/ # 컴포넌트 레지스트리 (482개) │ ├── utils/ # 유틸리티 │ └── v2-core/ # V2 코어 로직 ├── contexts/ # React Context (인증, 메뉴, 화면 등) ├── hooks/ # Custom Hooks ├── stores/ # Zustand 상태관리 └── middleware.ts # Next.js 인증 미들웨어 ``` ### 5.2 페이지 라우팅 구조 ``` /login → 로그인 /main → 메인 대시보드 /screens/[screenId] → 동적 화면 뷰어 (사용자) /admin/screenMng/screenMngList → 화면 관리 /admin/screenMng/dashboardList → 대시보드 관리 /admin/screenMng/reportList → 리포트 관리 /admin/systemMng/tableMngList → 테이블 관리 /admin/systemMng/commonCodeList → 공통코드 관리 /admin/systemMng/dataflow → 데이터플로우 관리 /admin/systemMng/i18nList → 다국어 관리 /admin/userMng/userMngList → 사용자 관리 /admin/userMng/companyList → 회사 관리 /admin/userMng/rolesList → 권한 관리 /admin/automaticMng/flowMgmtList → 플로우 관리 /admin/automaticMng/batchmngList → 배치 관리 /admin/automaticMng/mail/* → 메일 시스템 /admin/menu → 메뉴 관리 /dashboard/[dashboardId] → 대시보드 뷰어 /pop/work → 모바일 작업 화면 ``` ### 5.3 V2 통합 컴포넌트 시스템 **"하나의 컴포넌트, 여러 모드"** 철학으로 설계된 10개 통합 컴포넌트: | 컴포넌트 | 모드 | 역할 | |----------|------|------| | **V2Input** | text, number, password, slider, color | 텍스트/숫자 입력 | | **V2Select** | dropdown, radio, checkbox, tag, toggle | 선택 입력 | | **V2Date** | date, datetime, time, range | 날짜/시간 입력 | | **V2List** | table, card, kanban, list | 데이터 목록 표시 | | **V2Layout** | grid, split-panel, flex | 레이아웃 구성 | | **V2Group** | tab, accordion, section, modal | 그룹 컨테이너 | | **V2Media** | image, video, audio, file | 미디어 표시 | | **V2Biz** | flow, rack, numbering-rule | 비즈니스 로직 | | **V2Hierarchy** | tree, org-chart, BOM, cascading | 계층 구조 | | **V2Repeater** | inline-table, modal, button | 반복 데이터 | ### 5.4 API 클라이언트 규칙 ```typescript // 절대 금지: fetch 직접 사용 const res = await fetch('/api/flow/definitions'); // ❌ // 반드시 사용: lib/api/ 클라이언트 import { getFlowDefinitions } from '@/lib/api/flow'; const res = await getFlowDefinitions(); // ✅ ``` 환경별 URL 자동 처리: | 환경 | 프론트엔드 | 백엔드 API | |------|-----------|-----------| | 로컬 개발 | localhost:9771 | localhost:8080/api | | 운영 | v1.vexplor.com | api.vexplor.com/api | ### 5.5 상태 관리 체계 ``` 전역 상태 ├── AuthContext → 인증/세션/토큰 ├── MenuContext → 메뉴 트리/권한 ├── ScreenPreviewContext → 프리뷰 모드 ├── ScreenMultiLangContext → 다국어 라벨 ├── TableOptionsContext → 테이블 옵션 └── ActiveTabContext → 활성 탭 로컬 상태 ├── Zustand Stores → 화면 디자이너 상태, 사용자 상태 └── React Query → 서버 데이터 캐시 (5분 stale, 30분 GC) ``` ### 5.6 레지스트리 시스템 ```typescript // 컴포넌트 등록 (482개 등록됨) ComponentRegistry.registerComponent({ id: "v2-input", name: "통합 입력", category: ComponentCategory.V2, component: V2Input, configPanel: V2InputConfigPanel, defaultConfig: { inputType: "text" } }); // 동적 렌더링 ``` --- ## 6. 데이터베이스 구조 ### 6.1 테이블 도메인별 분류 #### 사용자/인증/회사 | 테이블 | 역할 | |--------|------| | `company_mng` | 회사 마스터 | | `user_info` | 사용자 정보 | | `user_info_history` | 사용자 변경 이력 | | `user_dept` | 사용자-부서 매핑 | | `dept_info` | 부서 정보 | | `authority_master` | 권한 그룹 마스터 | | `authority_sub_user` | 사용자-권한 매핑 | | `login_access_log` | 로그인 로그 | #### 메뉴/화면 | 테이블 | 역할 | |--------|------| | `menu_info` | 메뉴 트리 구조 | | `screen_definitions` | 화면 정의 (screenId, 테이블명 등) | | `screen_layouts_v2` | V2 레이아웃 (JSON) | | `screen_layouts` | V1 레이아웃 (레거시) | | `screen_groups` | 화면 그룹 (계층구조) | | `screen_group_screens` | 화면-그룹 매핑 | | `screen_menu_assignments` | 화면-메뉴 할당 | | `screen_field_joins` | 화면 필드 조인 설정 | | `screen_data_flows` | 화면 데이터 플로우 | | `screen_table_relations` | 화면-테이블 관계 | #### 메타데이터 | 테이블 | 역할 | |--------|------| | `table_type_columns` | 테이블 타입별 컬럼 정의 (회사별) | | `table_column_category_values` | 컬럼 카테고리 값 | | `code_category` | 공통 코드 카테고리 | | `code_info` | 공통 코드 값 | | `category_column_mapping` | 카테고리-컬럼 매핑 | | `cascading_relation` | 연쇄 드롭다운 관계 | | `numbering_rules` | 채번 규칙 | | `numbering_rule_parts` | 채번 규칙 파트 | #### 플로우/자동화 | 테이블 | 역할 | |--------|------| | `flow_definition` | 플로우 정의 | | `flow_step` | 플로우 단계 | | `flow_step_connection` | 플로우 단계 연결 | | `node_flows` | 노드 플로우 (버튼 액션) | | `dataflow_diagrams` | 데이터플로우 다이어그램 | | `batch_definitions` | 배치 작업 정의 | | `batch_schedules` | 배치 스케줄 | | `batch_execution_logs` | 배치 실행 로그 | #### 외부 연동 | 테이블 | 역할 | |--------|------| | `external_db_connections` | 외부 DB 연결 정보 | | `external_rest_api_connections` | 외부 REST API 연결 | #### 다국어 | 테이블 | 역할 | |--------|------| | `multi_lang_key_master` | 다국어 키 마스터 | #### 기타 | 테이블 | 역할 | |--------|------| | `work_history` | 작업 이력 | | `todo_items` | 할일 목록 | | `file_uploads` | 파일 업로드 | | `ddl_audit_log` | DDL 감사 로그 | ### 6.2 동적 테이블 생성 패턴 관리자가 화면 생성 시 비즈니스 테이블이 동적으로 생성된다: ```sql CREATE TABLE "dynamic_table_name" ( "id" VARCHAR(500) PRIMARY KEY DEFAULT gen_random_uuid()::text, "created_date" TIMESTAMP DEFAULT now(), "updated_date" TIMESTAMP DEFAULT now(), "writer" VARCHAR(500), "company_code" VARCHAR(500), -- 멀티테넌시 필수! -- 사용자 정의 컬럼들 (모두 VARCHAR(500)) "product_name" VARCHAR(500), "price" VARCHAR(500), ... ); CREATE INDEX idx_dynamic_company ON "dynamic_table_name"(company_code); ``` ### 6.3 테이블 관계도 ``` company_mng (company_code PK) │ ├── user_info (company_code FK) │ ├── authority_sub_user (user_id FK) │ └── user_dept (user_id FK) │ ├── menu_info (company_code) │ └── screen_menu_assignments (menu_objid FK) │ ├── screen_definitions (company_code) │ ├── screen_layouts_v2 (screen_id FK) │ ├── screen_groups → screen_group_screens (screen_id FK) │ └── screen_field_joins (screen_id FK) │ ├── authority_master (company_code) │ └── authority_sub_user (master_objid FK) │ ├── flow_definition (company_code) │ ├── flow_step (flow_id FK) │ └── flow_step_connection (flow_id FK) │ └── [동적 비즈니스 테이블들] (company_code) ``` --- ## 7. 인증/인가 워크플로우 ### 7.1 로그인 프로세스 ``` ┌─── 사용자 ───┐ ┌─── 프론트엔드 ───┐ ┌─── 백엔드 ───┐ ┌─── DB ───┐ │ │ │ │ │ │ │ │ │ ID/PW 입력 │────→│ POST /auth/login │────→│ 비밀번호 검증 │────→│ user_info│ │ │ │ │ │ │ │ 조회 │ │ │ │ │ │ JWT 토큰 생성 │ │ │ │ │ │ │←────│ 토큰 반환 │ │ │ │ │ │ │ │ │ │ │ │ │ │ localStorage 저장│ │ │ │ │ │ │ │ Cookie 저장 │ │ │ │ │ │ │ │ /main 리다이렉트 │ │ │ │ │ └──────────────┘ └──────────────────┘ └──────────────┘ └──────────┘ ``` ### 7.2 JWT 토큰 관리 ``` 토큰 저장: localStorage (주 저장소) + Cookie (SSR 미들웨어용) 자동 갱신: ├── 10분마다 만료 시간 체크 ├── 만료 30분 전: 백그라운드 자동 갱신 ├── 401 응답 시: 즉시 갱신 시도 └── 갱신 실패 시: /login 리다이렉트 세션 관리: ├── 데스크톱: 30분 비활성 → 세션 만료 (5분 전 경고) └── 모바일: 24시간 비활성 → 세션 만료 (1시간 전 경고) ``` ### 7.3 권한 체계 (3단계) ``` SUPER_ADMIN (company_code = "*") ├── 모든 회사 데이터 접근 가능 ├── DDL 실행 가능 ├── 시스템 설정 변경 └── 다른 회사로 전환 (switch-company) COMPANY_ADMIN (userType = "COMPANY_ADMIN") ├── 자기 회사 데이터만 접근 ├── 사용자 관리 가능 └── 메뉴/화면 관리 가능 USER (일반 사용자) ├── 자기 회사 데이터만 접근 ├── 권한 그룹에 따른 메뉴 접근 └── 할당된 화면만 사용 가능 ``` --- ## 8. 화면 디자이너 워크플로우 ### 8.1 관리자: 화면 설계 ``` Step 1: 화면 생성 └→ /admin/screenMng/screenMngList └→ "새 화면" 클릭 → 화면명, 설명, 메인 테이블 입력 Step 2: 화면 디자이너 진입 (ScreenDesigner.tsx) ├── 좌측 패널: 컴포넌트 팔레트 (V2 컴포넌트 10종) ├── 중앙 캔버스: 드래그앤드롭 영역 └── 우측 패널: 선택된 컴포넌트 속성 설정 Step 3: 컴포넌트 배치 └→ V2Input 드래그 → 캔버스 배치 → 속성 설정: ├── 위치: x, y 좌표 ├── 크기: width, height ├── 데이터 바인딩: columnName = "product_name" ├── 라벨: "제품명" ├── 조건부 표시: 특정 조건에서만 보이기 └── 플로우 연결: 버튼 클릭 시 실행할 플로우 Step 4: 레이아웃 저장 └→ screen_layouts_v2 테이블에 JSON 형태로 저장 └→ Zod 스키마 검증 → V2 형식 우선, V1 호환 저장 Step 5: 메뉴에 화면 할당 └→ /admin/menu → 메뉴 트리에서 "제품 관리" 선택 └→ 화면 연결 (screen_menu_assignments) ``` ### 8.2 화면 레이아웃 저장 구조 (V2) ```json { "version": "v2", "components": [ { "id": "comp-1", "componentType": "v2-input", "position": { "x": 100, "y": 50 }, "size": { "width": 200, "height": 40 }, "config": { "inputType": "text", "columnName": "product_name", "label": "제품명", "required": true } }, { "id": "comp-2", "componentType": "v2-list", "position": { "x": 100, "y": 150 }, "size": { "width": 600, "height": 400 }, "config": { "listType": "table", "tableName": "products", "columns": ["product_name", "price", "quantity"] } } ] } ``` --- ## 9. 사용자 업무 워크플로우 ### 9.1 전체 흐름 ``` 사용자 로그인 ↓ 메인 대시보드 (/main) ↓ 좌측 메뉴에서 "제품 관리" 클릭 ↓ /screens/[screenId] 라우팅 ↓ InteractiveScreenViewer 렌더링 ├── screen_definitions에서 화면 정보 로드 ├── screen_layouts_v2에서 레이아웃 JSON 로드 ├── V2 → Legacy 변환 (호환성) └── 메인 테이블 데이터 자동 로드 ↓ 컴포넌트별 렌더링 ├── V2Input → formData 바인딩 ├── V2List → 테이블 데이터 표시 ├── V2Select → 드롭다운/라디오 선택 └── Button → 플로우/액션 연결 ↓ 사용자 인터랙션 ├── 폼 입력 → formData 업데이트 ├── 테이블 행 선택 → selectedRowsData 업데이트 └── 버튼 클릭 → 플로우 실행 ↓ 플로우 실행 (nodeFlowButtonExecutor) ├── Step 1: 데이터 검증 ├── Step 2: API 호출 (INSERT/UPDATE/DELETE) ├── Step 3: 성공/실패 처리 └── Step 4: 테이블 자동 새로고침 ``` ### 9.2 조건부 표시 워크플로우 ``` 관리자 설정: "특별 할인 입력" 컴포넌트 └→ 조건: product_type === "PREMIUM" 일 때만 표시 사용자 사용: 1. 화면 진입 → evaluateConditional() 실행 2. product_type ≠ "PREMIUM" → "특별 할인 입력" 숨김 3. 사용자가 product_type을 "PREMIUM"으로 변경 4. formData 업데이트 → evaluateConditional() 재평가 5. product_type === "PREMIUM" → "특별 할인 입력" 표시! ``` --- ## 10. 플로우 엔진 워크플로우 ### 10.1 플로우 정의 (관리자) ``` /admin/automaticMng/flowMgmtList ↓ 플로우 생성: ├── 이름: "제품 승인 플로우" ├── 테이블: "products" └── 단계 정의: Step 1: "신청" (requester) Step 2: "부서장 승인" (manager) Step 3: "최종 승인" (director) 연결: Step 1 → Step 2 → Step 3 ``` ### 10.2 플로우 실행 (사용자) ``` 1. 사용자: 제품 신청 └→ "저장" 버튼 클릭 └→ flowApi.startFlow() → 상태: "부서장 승인 대기" 2. 부서장: 승인 화면 └→ V2Biz (flow) 컴포넌트 → 현재 단계 표시 └→ [승인] 클릭 → flowApi.approveStep() └→ 상태: "최종 승인 대기" 3. 이사: 최종 승인 └→ [승인] 클릭 → flowApi.approveStep() └→ 상태: "완료" └→ products.approval_status = "APPROVED" ``` ### 10.3 데이터 이동 (moveData) ``` 플로우의 핵심 동작: 데이터를 한 스텝에서 다음 스텝으로 이동 Step 1 (접수) → Step 2 (검토) → Step 3 (완료) ├── 단건 이동: moveData(flowId, dataId, fromStep, toStep) └── 배치 이동: moveBatchData(flowId, dataIds[], fromStep, toStep) ``` --- ## 11. 데이터플로우 시스템 ### 11.1 개요 데이터플로우는 비즈니스 로직을 **비주얼 다이어그램**으로 설계하는 시스템이다. ``` /admin/systemMng/dataflow ↓ React Flow 기반 캔버스 ├── InputNode: 데이터 입력 (폼 데이터, 테이블 데이터) ├── TransformNode: 데이터 변환 (매핑, 필터링, 계산) ├── DatabaseNode: DB 조회/저장 ├── RestApiNode: 외부 API 호출 ├── ConditionNode: 조건 분기 ├── LoopNode: 반복 처리 ├── MergeNode: 데이터 합치기 └── OutputNode: 결과 출력 ``` ### 11.2 데이터플로우 실행 ``` 버튼 클릭 → 데이터플로우 트리거 ↓ InputNode: formData 수집 ↓ TransformNode: 데이터 가공 ↓ ConditionNode: 조건 분기 (가격 > 10000?) ├── Yes → DatabaseNode: INSERT INTO premium_products └── No → DatabaseNode: INSERT INTO standard_products ↓ OutputNode: 결과 반환 → toast.success("저장 완료") ``` --- ## 12. 대시보드 시스템 ### 12.1 구조 ``` 관리자: /admin/screenMng/dashboardList └→ 대시보드 생성 → 위젯 추가 → 레이아웃 저장 사용자: /dashboard/[dashboardId] └→ 위젯 그리드 렌더링 → 실시간 데이터 표시 ``` ### 12.2 위젯 종류 | 카테고리 | 위젯 | 역할 | |----------|------|------| | 시각화 | CustomMetricWidget | 커스텀 메트릭 표시 | | | StatusSummaryWidget | 상태 요약 | | 리스트 | CargoListWidget | 화물 목록 | | | VehicleListWidget | 차량 목록 | | 지도 | MapTestWidget | 지도 표시 | | | WeatherMapWidget | 날씨 지도 | | 작업 | TodoWidget | 할일 목록 | | | WorkHistoryWidget | 작업 이력 | | 알림 | BookingAlertWidget | 예약 알림 | | | RiskAlertWidget | 위험 알림 | | 기타 | ClockWidget | 시계 | | | CalendarWidget | 캘린더 | --- ## 13. 배치/스케줄 시스템 ### 13.1 구조 ``` 관리자: /admin/automaticMng/batchmngList ↓ 배치 작업 생성: ├── 이름: "일일 재고 집계" ├── 실행 쿼리: SQL 또는 데이터플로우 ID ├── 스케줄: Cron 표현식 ("0 0 * * *" = 매일 자정) └── 활성화/비활성화 ↓ 배치 스케줄러 (batch_schedules) ↓ 자동 실행 → 실행 로그 (batch_execution_logs) ``` ### 13.2 배치 실행 흐름 ``` Cron 트리거 → 배치 정의 조회 → SQL/데이터플로우 실행 ↓ 성공: execution_log에 "SUCCESS" 기록 실패: execution_log에 "FAILED" + 에러 메시지 기록 ``` --- ## 14. 멀티테넌시 아키텍처 ### 14.1 핵심 원칙 ``` 모든 비즈니스 테이블: company_code 컬럼 필수 모든 쿼리: WHERE company_code = $1 필수 모든 JOIN: ON a.company_code = b.company_code 필수 모든 집계: GROUP BY company_code 필수 ``` ### 14.2 데이터 격리 ``` 회사 A (company_code = "COMPANY_A"): └→ 자기 데이터만 조회/수정/삭제 가능 회사 B (company_code = "COMPANY_B"): └→ 자기 데이터만 조회/수정/삭제 가능 슈퍼관리자 (company_code = "*"): └→ 모든 회사 데이터 조회 가능 └→ 일반 회사는 "*" 데이터를 볼 수 없음 중요: company_code = "*"는 공통 데이터가 아니라 슈퍼관리자 전용 데이터! ``` ### 14.3 코드 패턴 ```typescript // 백엔드 표준 패턴 const companyCode = req.user!.companyCode; if (companyCode === "*") { // 슈퍼관리자: 전체 데이터 query = "SELECT * FROM table ORDER BY company_code"; } else { // 일반 사용자: 자기 회사만, "*" 제외 query = "SELECT * FROM table WHERE company_code = $1 AND company_code != '*'"; params = [companyCode]; } ``` --- ## 15. 외부 연동 ### 15.1 외부 DB 연결 ``` 지원 DB: PostgreSQL, MySQL, MariaDB, MSSQL, Oracle 관리: /api/external-db-connections ├── 연결 정보 등록 (host, port, database, credentials) ├── 연결 테스트 ├── 쿼리 실행 └── 데이터플로우에서 DatabaseNode로 사용 ``` ### 15.2 외부 REST API 연결 ``` 관리: /api/external-rest-api-connections ├── API 엔드포인트 등록 (URL, method, headers) ├── 인증 설정 (Bearer, Basic, API Key) ├── 테스트 호출 └── 데이터플로우에서 RestApiNode로 사용 ``` ### 15.3 메일 시스템 ``` 관리: /admin/automaticMng/mail/* ├── 메일 템플릿 관리 ├── 메일 발송 (개별/대량) ├── 수신 메일 확인 └── 발송 이력 조회 ``` --- ## 16. 배포 환경 ### 16.1 Docker 구성 ``` 개발 환경 (Mac): ├── docker/dev/docker-compose.backend.mac.yml (BE: 8080) └── docker/dev/docker-compose.frontend.mac.yml (FE: 9771) 운영 환경: ├── docker/prod/docker-compose.backend.prod.yml (BE: 8080) └── docker/prod/docker-compose.frontend.prod.yml (FE: 5555) ``` ### 16.2 서버 정보 | 환경 | 서버 | 포트 | DB | |------|------|------|-----| | 개발 | 39.117.244.52 | FE:9771, BE:8080 | 39.117.244.52:11132 | | 운영 | 211.115.91.141 | FE:5555, BE:8080 | 211.115.91.141:11134 | ### 16.3 백엔드 시작 시 자동 작업 ``` 서버 시작 (app.ts) ├── 마이그레이션 실행 (DB 스키마 업데이트) ├── 배치 스케줄러 초기화 ├── 위험 알림 캐시 로드 └── 메일 정리 Cron 시작 ``` --- ## 부록: 업무 진행 요약 ### 새로운 업무 화면을 만드는 전체 프로세스 ``` 1. [DB] 테이블 관리에서 비즈니스 테이블 생성 └→ 컬럼 정의, 타입 설정 2. [화면] 화면 관리에서 새 화면 생성 └→ 메인 테이블 지정 3. [디자인] 화면 디자이너에서 UI 구성 └→ V2 컴포넌트 배치, 데이터 바인딩 4. [로직] 데이터플로우 설계 (필요시) └→ 저장/수정/삭제 로직 다이어그램 5. [플로우] 플로우 정의 (승인 프로세스 필요시) └→ 단계 정의, 연결 6. [메뉴] 메뉴에 화면 할당 └→ 사용자가 접근할 수 있게 메뉴 트리 배치 7. [권한] 권한 그룹에 메뉴 할당 └→ 특정 사용자 그룹만 접근 가능하게 8. [사용] 사용자가 메뉴 클릭 → 업무 시작! ```