ERP-node/docs/DDD1542/DB_STRUCTURE_DIAGRAM.md

469 lines
17 KiB
Markdown

# Vexplor 구조 다이어그램
> 생성일: 2026-01-22 | 총 테이블: 164개 | 코드 기반 관계 분석 완료
---
## 1. 테이블 JOIN 관계도 (핵심)
### 1-1. 사용자/권한 시스템 JOIN 관계
| CRUD | 테이블 순서 | 설명 |
|------|-------------|------|
| **C** | `user_info``user_dept``authority_sub_user` | 사용자 생성 → 부서 배정 → 권한 부여 |
| **R** | `user_info` + `company_mng` + `authority_sub_user` + `authority_master` JOIN | 로그인/조회 시 회사+권한 JOIN |
| **U** | `user_info` / `user_dept` / `authority_sub_user` 개별 | 각 테이블 독립 수정 |
| **D** | 각각 독립 삭제 (별도 API) | user_dept, authority_sub_user, user_info 각각 삭제 |
```mermaid
erDiagram
company_mng {
varchar company_code PK "회사코드"
varchar company_name "회사명"
}
user_info {
varchar user_id PK "사용자ID"
varchar company_code "회사코드 (멀티테넌시)"
varchar user_name "사용자명"
varchar user_type "SUPER_ADMIN | COMPANY_ADMIN | USER"
}
dept_info {
varchar dept_code PK "부서코드"
varchar company_code "회사코드"
varchar dept_name "부서명"
}
user_dept {
varchar user_id "사용자ID"
varchar dept_code "부서코드"
varchar company_code "회사코드"
}
authority_master {
int objid PK "권한그룹ID"
varchar company_code "회사코드"
varchar auth_group_name "권한그룹명"
}
authority_sub_user {
int master_objid "권한그룹ID"
varchar user_id "사용자ID"
varchar company_code "회사코드"
}
company_mng ||--o{ user_info : "company_code = company_code"
company_mng ||--o{ dept_info : "company_code = company_code"
user_info ||--o{ user_dept : "user_id = user_id"
dept_info ||--o{ user_dept : "dept_code = dept_code"
authority_master ||--o{ authority_sub_user : "objid = master_objid"
user_info ||--o{ authority_sub_user : "user_id = user_id"
```
**실제 코드 JOIN 예시:**
```sql
-- 사용자 권한 조회 (authService.ts:158)
SELECT am.auth_group_name, am.objid
FROM authority_sub_user asu
INNER JOIN authority_master am ON asu.master_objid = am.objid
WHERE asu.user_id = $1
```
### 1-2. 메뉴/권한 시스템 JOIN 관계
| CRUD | 테이블 순서 | 설명 |
|------|-------------|------|
| **C** | `menu_info``rel_menu_auth` | 메뉴 생성 → 권한그룹에 메뉴 할당 |
| **R** | `authority_master``rel_menu_auth``menu_info` | 사용자 권한으로 접근 가능 메뉴 필터링 |
| **U** | `menu_info` 단독 / `rel_menu_auth` 삭제 후 재생성 | 메뉴 수정 or 권한 재할당 |
| **D** | `rel_menu_auth``menu_info` | 권한 매핑 먼저 삭제 → 메뉴 삭제 |
```mermaid
erDiagram
menu_info {
int objid PK "메뉴ID"
varchar company_code "회사코드"
varchar menu_name_kor "메뉴명"
varchar menu_url "메뉴URL"
int parent_obj_id "상위메뉴ID"
}
rel_menu_auth {
int menu_objid "메뉴ID"
int auth_objid "권한그룹ID"
varchar company_code "회사코드"
}
authority_master {
int objid PK "권한그룹ID"
varchar company_code "회사코드"
}
menu_info ||--o{ rel_menu_auth : "objid = menu_objid"
authority_master ||--o{ rel_menu_auth : "objid = auth_objid"
```
**실제 코드 JOIN 예시:**
```sql
-- 사용자 메뉴 조회 (adminService.ts)
SELECT mi.*
FROM menu_info mi
JOIN rel_menu_auth rma ON mi.objid = rma.menu_objid
WHERE rma.auth_objid IN (사용자권한목록)
AND mi.company_code = $companyCode
```
### 1-3. 화면 시스템 JOIN 관계
| CRUD | 테이블 순서 | 설명 |
|------|-------------|------|
| **C** | `screen_definitions``screen_layouts``screen_menu_assignments` | 화면 정의 → 레이아웃 → 메뉴 연결 |
| **R** | `menu_info``screen_menu_assignments``screen_definitions` + `screen_layouts` JOIN | 메뉴에서 화면+레이아웃 JOIN |
| **U** | `screen_definitions` / `screen_layouts` 개별 (같은 screen_id) | 정의와 레이아웃 각각 수정 |
| **D** | `screen_layouts``screen_menu_assignments``screen_definitions` | 레이아웃 → 메뉴연결 → 정의 순서 |
> **그룹**: `screen_groups` → `screen_group_screens`는 별도 API로 관리 (복사/그룹화 용도)
```mermaid
erDiagram
screen_definitions {
uuid screen_id PK "화면ID"
varchar company_code "회사코드"
varchar screen_name "화면명"
varchar table_name "연결테이블"
}
screen_layouts {
uuid screen_id PK "화면ID"
jsonb layout_metadata "레이아웃JSON"
}
screen_menu_assignments {
uuid screen_id "화면ID"
int menu_objid "메뉴ID"
varchar company_code "회사코드"
}
screen_groups {
int id PK "그룹ID"
varchar company_code "회사코드"
varchar group_name "그룹명"
}
screen_group_screens {
int group_id "그룹ID"
uuid screen_id "화면ID"
varchar company_code "회사코드"
}
screen_definitions ||--|| screen_layouts : "screen_id = screen_id"
screen_definitions ||--o{ screen_menu_assignments : "screen_id = screen_id"
menu_info ||--o{ screen_menu_assignments : "objid = menu_objid"
screen_groups ||--o{ screen_group_screens : "id = group_id"
screen_definitions ||--o{ screen_group_screens : "screen_id = screen_id"
```
**실제 코드 JOIN 예시:**
```sql
-- 화면 정의 + 레이아웃 조회 (screenGroupController.ts:1272)
SELECT sd.*, sl.layout_metadata
FROM screen_definitions sd
JOIN screen_layouts sl ON sd.screen_id = sl.screen_id
WHERE sd.screen_id = $1
```
### 1-4. 테이블 타입/메타데이터 JOIN 관계
| CRUD | 테이블 순서 | 설명 |
|------|-------------|------|
| **C** | 각 테이블 독립 생성 | DDL 실행 시 자동 생성, 또는 개별 등록 |
| **R** | `table_type_columns` + `table_labels` + `table_relationships` LEFT JOIN | 화면 로딩 시 메타데이터 조합 |
| **U** | 각 테이블 개별 (table_name + column_name + company_code 기준) | 컬럼 정의/라벨/관계 각각 수정 |
| **D** | 각 테이블 독립 삭제 | 테이블 삭제 시 관련 메타데이터 개별 삭제 |
> **코드값 조회**: `table_column_category_values` → `code_category` → `code_info` (드롭다운 옵션)
```mermaid
erDiagram
table_type_columns {
varchar table_name PK "테이블명"
varchar column_name PK "컬럼명"
varchar company_code PK "회사코드"
varchar display_name "표시명"
varchar data_type "데이터타입"
varchar reference_table "참조테이블"
varchar reference_column "참조컬럼"
}
table_labels {
varchar table_name PK "테이블명"
varchar company_code PK "회사코드"
varchar display_name "테이블표시명"
}
table_column_category_values {
varchar table_name "테이블명"
varchar column_name "컬럼명"
varchar category_code "카테고리코드"
varchar company_code "회사코드"
}
table_relationships {
varchar table_name "테이블명"
varchar source_column "소스컬럼"
varchar target_table "타겟테이블"
varchar target_column "타겟컬럼"
varchar company_code "회사코드"
}
code_category {
varchar category_code PK "카테고리코드"
varchar company_code PK "회사코드"
varchar category_name "카테고리명"
}
code_info {
varchar category_code "카테고리코드"
varchar code_value PK "코드값"
varchar company_code PK "회사코드"
varchar code_name "코드명"
}
table_type_columns ||--o{ table_labels : "table_name = table_name"
table_type_columns ||--o{ table_column_category_values : "table_name, column_name"
table_type_columns ||--o{ table_relationships : "table_name = table_name"
code_category ||--o{ code_info : "category_code = category_code"
table_column_category_values }o--|| code_category : "category_code = category_code"
```
**실제 코드 JOIN 예시:**
```sql
-- 테이블 컬럼 정보 조회 (tableManagementService.ts:210)
SELECT ttc.*, cl.display_name as column_label
FROM table_type_columns ttc
LEFT JOIN column_labels cl
ON ttc.table_name = cl.table_name
AND ttc.column_name = cl.column_name
WHERE ttc.table_name = $1
AND ttc.company_code = $2
```
### 1-5. 플로우 시스템 JOIN 관계
| CRUD | 테이블 순서 | 설명 |
|------|-------------|------|
| **C** | `flow_definition``flow_step``flow_step_connection``flow_data_mapping` | 플로우 → 스텝 → 연결선 → 매핑 |
| **R** | `flow_definition` + `flow_step` + `flow_step_connection` JOIN | 플로우 화면 렌더링 |
| **U** | 각 테이블 개별 (definition_id/step_id 기준) | 정의/스텝/연결 각각 수정 |
| **D** | 각 테이블 독립 삭제 (DB CASCADE 의존) | step/connection/definition 각각 삭제 API |
> **데이터 이동**: `flow_data_mapping`(컬럼 변환) → 소스→타겟 INSERT → `flow_audit_log`(자동 기록)
```mermaid
erDiagram
flow_definition {
int id PK "플로우ID"
varchar company_code "회사코드"
varchar name "플로우명"
}
flow_step {
int id PK "스텝ID"
int definition_id "플로우ID"
varchar company_code "회사코드"
varchar step_name "스텝명"
varchar table_name "연결테이블"
int step_order "순서"
}
flow_step_connection {
int id PK "연결ID"
int from_step_id "출발스텝ID"
int to_step_id "도착스텝ID"
int definition_id "플로우ID"
}
flow_data_mapping {
int from_step_id "출발스텝ID"
int to_step_id "도착스텝ID"
varchar source_column "소스컬럼"
varchar target_column "타겟컬럼"
}
flow_audit_log {
int id PK "로그ID"
int definition_id "플로우ID"
int from_step_id "출발스텝ID"
int to_step_id "도착스텝ID"
int data_id "데이터ID"
timestamp moved_at "이동시간"
}
flow_definition ||--o{ flow_step : "id = definition_id"
flow_step ||--o{ flow_step_connection : "id = from_step_id"
flow_step ||--o{ flow_step_connection : "id = to_step_id"
flow_step ||--o{ flow_data_mapping : "id = from_step_id"
flow_step ||--o{ flow_audit_log : "id = from_step_id"
```
**실제 코드 JOIN 예시:**
```sql
-- 플로우 감사로그 조회 (flowDataMoveService.ts:461)
SELECT fal.*,
fs_from.step_name as from_step_name,
fs_to.step_name as to_step_name
FROM flow_audit_log fal
LEFT JOIN flow_step fs_from ON fal.from_step_id = fs_from.id
LEFT JOIN flow_step fs_to ON fal.to_step_id = fs_to.id
WHERE fal.definition_id = $1
```
### 1-6. 배치/수집 시스템 JOIN 관계
| CRUD | 테이블 순서 | 설명 |
|------|-------------|------|
| **C** | `external_db_connections``batch_configs``batch_mappings` | 외부DB 연결 → 배치 설정 → 매핑 규칙 |
| **R** | `batch_configs` + `external_db_connections` + `batch_mappings` JOIN | 배치 실행 시 전체 설정 조회 |
| **U** | `batch_mappings` 삭제 후 재생성 / `batch_configs` 개별 수정 | 매핑은 전체 교체 방식 |
| **D** | `batch_configs` 삭제 시 `batch_mappings` CASCADE 삭제 | 설정만 삭제하면 매핑 자동 삭제 |
> **실행 시**: 크론 → 외부DB 조회 → 내부 테이블 동기화 → `batch_execution_logs`(결과 기록)
```mermaid
erDiagram
external_db_connections {
int id PK "연결ID"
varchar company_code "회사코드"
varchar connection_name "연결명"
varchar db_type "postgresql|mysql|mssql"
varchar host "호스트"
int port "포트"
}
batch_configs {
int id PK "배치ID"
varchar company_code "회사코드"
varchar batch_name "배치명"
varchar cron_expression "크론식"
int connection_id "연결ID"
varchar is_active "Y|N"
}
batch_mappings {
int id PK "매핑ID"
int batch_config_id "배치ID"
varchar source_table "소스테이블"
varchar source_column "소스컬럼"
varchar target_table "타겟테이블"
varchar target_column "타겟컬럼"
}
batch_execution_logs {
int id PK "로그ID"
int batch_config_id "배치ID"
timestamp started_at "시작시간"
timestamp finished_at "종료시간"
varchar status "SUCCESS|FAILED"
}
external_db_connections ||--o{ batch_configs : "id = connection_id"
batch_configs ||--o{ batch_mappings : "id = batch_config_id"
batch_configs ||--o{ batch_execution_logs : "id = batch_config_id"
```
**실제 코드 JOIN 예시:**
```sql
-- 배치 설정 + 매핑 조회 (batchService.ts:143)
SELECT bc.*, bm.*
FROM batch_configs bc
LEFT JOIN batch_mappings bm ON bc.id = bm.batch_config_id
WHERE bc.id = $1
AND bc.company_code = $2
ORDER BY bm.mapping_order
```
---
## 2. 로직 플로우 요약
> 위 JOIN 관계가 **언제** 사용되는지 간략 설명
### 2-1. 로그인 → 화면 접근 순서
| 단계 | 테이블 | JOIN 관계 | 설명 |
|------|--------|-----------|------|
| 1 | `user_info` | - | user_id, password 확인 |
| 2 | `user_info` | - | company_code 조회 → 멀티테넌시 분기 |
| 3 | `company_mng` | user_info.company_code = company_mng.company_code | 회사명 조회 |
| 4 | `authority_sub_user``authority_master` | asu.master_objid = am.objid | 사용자 권한 조회 |
| 5 | `menu_info``rel_menu_auth` | mi.objid = rma.menu_objid | 권한별 메뉴 필터 |
| 6 | `screen_menu_assignments``screen_definitions` | sma.screen_id = sd.screen_id | 메뉴-화면 연결 |
| 7 | `screen_definitions``screen_layouts` | sd.screen_id = sl.screen_id | 화면+레이아웃 |
| 8 | `table_type_columns` | WHERE table_name = $1 | 컬럼 메타데이터 |
### 2-2. 데이터 조회 순서
| 단계 | 테이블 | JOIN 관계 | 설명 |
|------|--------|-----------|------|
| 1 | `table_type_columns` | - | 컬럼 정의 조회 |
| 2 | `table_labels` | ttc.table_name = tl.table_name | 테이블 표시명 |
| 3 | `table_column_category_values` | ttc.table_name, column_name | 카테고리 값 |
| 4 | `table_relationships` | ttc.table_name = tr.table_name | 참조 관계 |
| 5 | `code_category``code_info` | cc.category_code = ci.category_code | 코드값 조회 |
| 6 | 비즈니스 테이블 | LEFT JOIN (table_relationships 기반) | 실제 데이터 |
### 2-3. 플로우 데이터 이동 순서
| 단계 | 테이블 | JOIN 관계 | 설명 |
|------|--------|-----------|------|
| 1 | `flow_definition` | - | 플로우 정의 |
| 2 | `flow_step` | fs.definition_id = fd.id | 스텝 목록 |
| 3 | `flow_step_connection` | fsc.from_step_id = fs.id | 연결 관계 |
| 4 | `flow_data_mapping` | fdm.from_step_id, to_step_id | 컬럼 매핑 |
| 5 | 소스 테이블 | - | 데이터 조회 |
| 6 | 타겟 테이블 | - | 데이터 INSERT |
| 7 | `flow_audit_log` | - | 이동 기록 |
### 2-4. 배치 실행 순서
| 단계 | 테이블 | JOIN 관계 | 설명 |
|------|--------|-----------|------|
| 1 | `batch_configs` | - | 활성 배치 조회 |
| 2 | `external_db_connections` | bc.connection_id = edc.id | 외부 DB 정보 |
| 3 | `batch_mappings` | bm.batch_config_id = bc.id | 매핑 규칙 |
| 4 | 외부 DB | - | 데이터 조회 |
| 5 | 내부 테이블 | - | 데이터 동기화 |
| 6 | `batch_execution_logs` | bel.batch_config_id = bc.id | 실행 로그 |
---
## 3. 멀티테넌시 (company_code) 적용 요약
| 테이블 | company_code 필터 | 비고 |
|--------|------------------|------|
| `user_info` | O | 사용자별 회사 구분 |
| `menu_info` | O | 회사별 메뉴 |
| `screen_definitions` | O | 회사별 화면 |
| `table_type_columns` | O | 회사별 컬럼 정의 |
| `flow_definition` | O | 회사별 플로우 |
| `batch_configs` | O | 회사별 배치 |
| 모든 비즈니스 테이블 | O | 자동 필터 적용 |
| `company_mng` | X (PK) | 회사 마스터 |
**company_code = '*'**: 최고관리자, 모든 회사 데이터 접근 가능
---
## 4. 비효율성 분석
> 상세 내용: [DB_INEFFICIENCY_ANALYSIS.md](./DB_INEFFICIENCY_ANALYSIS.md)
| 심각도 | 항목 | 권장 조치 |
|--------|------|-----------|
| 🔴 | `screen_definitions.layout_metadata` | 미사용 컬럼 삭제 |
| 🔴 | `user_dept` 비정규화 | 정규화 리팩토링 |
| 🟡 | 히스토리 테이블 39개 | 통합 감사 테이블 |
| 🟡 | cascading 미사용 3개 | 테이블 삭제 |
| 🟢 | `dept_info.company_name` | 선택적 정규화 |