ERP-node/docs/DB_ARCHITECTURE_ANALYSIS.md

59 KiB

WACE ERP 데이터베이스 아키텍처 분석 보고서

📅 작성일: 2026-01-20
🎯 목적: WACE ERP 시스템 전체 워크플로우 문서화를 위한 DB 구조 분석
📊 DB 엔진: PostgreSQL 16.8


📋 목차

  1. 개요
  2. 전체 테이블 목록
  3. 멀티테넌시 아키텍처
  4. 핵심 시스템 테이블
  5. 메타데이터 관리 시스템
  6. 화면 관리 시스템
  7. 비즈니스 도메인별 테이블
  8. 플로우 및 데이터 통합
  9. 인덱스 전략
  10. 동적 테이블 생성 패턴
  11. 마이그레이션 히스토리

1. 개요

1.1 데이터베이스 통계

- 총 테이블 수: 약 280개
- 총 함수 수: 약 50개
- 총 트리거 수: 약 30개
- 총 시퀀스 수: 약 100개
- 뷰 수: 약 20개

1.2 아키텍처 특징

  • 멀티테넌시: 모든 테이블에 company_code 컬럼으로 회사별 데이터 격리
  • 동적 스키마: 런타임에 테이블 생성/수정 가능
  • 메타데이터 드리븐: UI 컴포넌트가 메타데이터 테이블을 기반으로 동적 렌더링
  • 이력 관리: 주요 테이블에 _log 테이블로 변경 이력 추적
  • 외부 연동: 외부 DB 및 REST API 연결 지원
  • 플로우 기반: 화면 간 데이터 흐름을 정의하고 실행

2. 전체 테이블 목록

2.1 테이블 분류 체계

시스템 관리 (약 30개)
├── 사용자/권한 (10개)
├── 메뉴 관리 (5개)
├── 회사 관리 (3개)
└── 공통 코드 (5개)

메타데이터 시스템 (약 20개)
├── 테이블/컬럼 정의 (8개)
├── 화면 정의 (10개)
└── 레이아웃/컴포넌트 (5개)

비즈니스 도메인 (약 200개)
├── 영업/수주 (30개)
├── 구매/발주 (25개)
├── 재고/창고 (20개)
├── 생산/작업 (25개)
├── 품질/검사 (15개)
├── 물류/운송 (20개)
├── PLM/설계 (30개)
├── 회계/원가 (20개)
└── 기타 (15개)

통합/플로우 (약 30개)
├── 데이터플로우 (10개)
├── 배치 작업 (8개)
└── 외부 연동 (12개)

2.2 주요 테이블 목록 (알파벳순)

전체 테이블 목록 보기 (280개)
approval
attach_file_info
auth_tokens
authority_master
authority_master_history
authority_sub_user
batch_configs
batch_execution_logs
batch_job_executions
batch_job_parameters
batch_jobs
batch_mappings
batch_schedules
button_action_standards
carrier_contract_mng
carrier_contract_mng_log
carrier_mng
carrier_mng_log
carrier_vehicle_mng
carrier_vehicle_mng_log
cascading_auto_fill_group
cascading_auto_fill_mapping
cascading_condition
cascading_hierarchy_group
cascading_hierarchy_level
cascading_multi_parent
cascading_multi_parent_source
cascading_mutual_exclusion
cascading_relation
cascading_reverse_lookup
category_column_mapping
category_value_cascading_group
category_value_cascading_mapping
chartmgmt
check_report_mng
code_category
code_info
collection_batch_executions
collection_batch_management
column_labels
comm_code
comm_code_history
comm_exchange_rate
comments
company_code_sequence
company_mng
component_standards
contract_mgmt
contract_mgmt_option
counselingmgmt
customer_item
customer_item_alias
customer_item_mapping
customer_item_price
customer_mng
customer_service_mgmt
customer_service_part
customer_service_workingtime
dashboard_elements
dashboard_shares
dashboard_slider_items
dashboard_sliders
dashboards
data_collection_configs
data_collection_history
data_collection_jobs
data_relationship_bridge
dataflow_diagrams
dataflow_external_calls
ddl_execution_log
defect_standard_mng
defect_standard_mng_log
delivery_destination
delivery_history
delivery_history_defect
delivery_part_price
delivery_route_mng
delivery_route_mng_log
delivery_status
dept_info
dept_info_history
digital_twin_layout
digital_twin_layout_template
digital_twin_location_layout
digital_twin_objects
digital_twin_zone_layout
drivers
dtg_contracts
dtg_maintenance_history
dtg_management
dtg_management_log
dtg_monthly_settlements
dynamic_form_data
equipment_consumable
equipment_consumable_log
equipment_inspection_item
equipment_inspection_item_log
equipment_mng
equipment_mng_log
estimate_mgmt
excel_mapping_template
expense_detail
expense_master
external_call_configs
external_call_logs
external_connection_permission
external_db_connection
external_db_connections
external_rest_api_connections
external_work_review_info
facility_assembly_plan
file_down_log
flow_audit_log
flow_data_mapping
flow_data_status
flow_definition
flow_external_connection_permission
flow_external_db_connection
flow_integration_log
flow_step
flow_step_connection
fund_mgmt
grid_standards
inbound_mng
inboxtask
injection_cost
input_cost_goal
input_resource
inspection_equipment_mng
inspection_equipment_mng_log
inspection_standard
inventory_history
inventory_stock
item_info
item_inspection_info
item_routing_detail
item_routing_version
klbom_tbl
language_master
layout_instances
layout_standards
login_access_log
logistics_cost_mng
logistics_cost_mng_log
mail_log
maintenance_schedules
material_cost
material_detail_mgmt
material_master_mgmt
material_mng
material_release
menu_info
menu_screen_group_items
menu_screen_groups
mold_dev_request_info
multi_lang_category
multi_lang_key_master
multi_lang_text
node_flows
numbering_rule_parts
numbering_rules
oem_factory_mng
oem_milestone_mng
oem_mng
option_mng
option_price_history
order_mgmt
order_mng_master
order_mng_sub
order_plan_mgmt
order_plan_result_error
order_spec_mng
order_spec_mng_history
outbound_mng
part_bom_qty
part_bom_report
part_distribution_list
part_mgmt
part_mng
part_mng_history
planning_issue
pms_invest_cost_mng
pms_pjt_concept_info
pms_pjt_info
pms_pjt_year_goal
pms_rel_pjt_concept_milestone
pms_rel_pjt_concept_prod
pms_rel_pjt_prod
pms_rel_prod_ref_dept
pms_wbs_task
pms_wbs_task_confirm
pms_wbs_task_info
pms_wbs_task_standard
pms_wbs_template
problem_mng
process_equipment
process_mng
procurement_standard
product_group_mng
product_kind_spec
product_kind_spec_main
product_mgmt
product_mgmt_model
product_mgmt_price_history
product_mgmt_upg_detail
product_mgmt_upg_master
product_mng
product_spec
production_issue
production_record
production_task
profit_loss
profit_loss_coefficient
profit_loss_coolingtime
profit_loss_depth
profit_loss_lossrate
profit_loss_machine
profit_loss_pretime
profit_loss_srrate
profit_loss_total
profit_loss_total_addlist
profit_loss_weight
project
project_mgmt
purchase_detail
purchase_order
purchase_order_master
purchase_order_mng
purchase_order_multi
purchase_order_part
ratecal_mgmt
receive_history
receiving
rel_menu_auth
report_layout
report_master
report_menu_mapping
report_query
report_template
safety_budget_execution
safety_incidents
safety_inspections
safety_inspections_log
sales_bom_part_qty
sales_bom_report
sales_bom_report_part
sales_long_delivery
sales_long_delivery_input
sales_long_delivery_predict
sales_order_detail
sales_order_detail_log
sales_order_mng
sales_part_chg
sales_request_master
sales_request_part
sample_supply
screen_data_flows
screen_data_transfer
screen_definitions
screen_embedding
screen_field_joins
screen_group_members
screen_group_screens
screen_groups
screen_layouts
screen_menu_assignments
screen_split_panel
screen_table_relations
screen_templates
screen_widgets
shipment_detail
shipment_header
shipment_instruction
shipment_instruction_item
shipment_pallet
shipment_plan
standard_doc_info
structural_review_proposal
style_templates
supplier_item
supplier_item_alias
supplier_item_mapping
supplier_item_price
supplier_mng
supplier_mng_log
supply_charger_mng
supply_mng
supply_mng_history
table_column_category_values
table_labels
table_log_config
table_relationships
table_type_columns
tax_invoice
tax_invoice_item
time_sheet
transport_logs
transport_statistics
transport_vehicle_locations
used_mng
user_dept
user_dept_sub
user_info
user_info_history
vehicle_location_history
vehicle_locations
vehicle_trip_summary
vehicles
warehouse_info
warehouse_location
web_type_standards
work_instruction
work_instruction_detail
work_instruction_detail_log
work_instruction_log
work_order
work_orders
work_orders_detail
work_request
yard_layout
yard_material_placement

3. 멀티테넌시 아키텍처

3.1 company_code 패턴

모든 테이블에 필수적으로 포함되는 컬럼:

company_code VARCHAR(20) NOT NULL

의미:

  • 하나의 데이터베이스에서 여러 회사의 데이터를 격리
  • 모든 쿼리는 반드시 company_code 필터 포함 필요

3.2 특별한 company_code 값

company_code = "*" 의미

-- ❌ 잘못된 이해: 모든 회사가 공유하는 공통 데이터
-- ✅ 올바른 이해: 슈퍼 관리자 전용 데이터

-- 일반 회사는 "*" 데이터를 볼 수 없음
SELECT * FROM table_name
WHERE company_code = 'COMPANY_A'
  AND company_code != '*';  -- 필수!

용도:

  • 시스템 관리자용 메타데이터
  • 전역 설정 값
  • 기본 템플릿

3.3 멀티테넌시 쿼리 패턴

-- ✅ 표준 SELECT 패턴
SELECT * FROM table_name
WHERE company_code = $1
  AND company_code != '*'
ORDER BY created_date DESC;

-- ✅ JOIN 패턴 (company_code 매칭 필수!)
SELECT a.*, b.name
FROM table_a a
LEFT JOIN table_b b 
  ON a.ref_id = b.id
  AND a.company_code = b.company_code  -- 필수!
WHERE a.company_code = $1;

-- ✅ 서브쿼리 패턴
SELECT *
FROM orders o
WHERE company_code = $1
  AND product_id IN (
    SELECT id FROM products
    WHERE company_code = $1  -- 서브쿼리에도 필수!
  );

-- ✅ 집계 패턴
SELECT 
  product_type,
  COUNT(*) as total,
  SUM(amount) as total_amount
FROM sales
WHERE company_code = $1
GROUP BY product_type;

3.4 company_code 인덱스 전략

모든 테이블에 필수 인덱스:

CREATE INDEX idx_{table_name}_company_code 
ON {table_name}(company_code);

-- 복합 인덱스 예시
CREATE INDEX idx_sales_company_date 
ON sales(company_code, sale_date DESC);

4. 핵심 시스템 테이블

4.1 사용자 관리

user_info (사용자 정보)

CREATE TABLE user_info (
  sabun VARCHAR(1024),              -- 사번
  user_id VARCHAR(1024) PRIMARY KEY,-- 사용자 ID
  user_password VARCHAR(1024),      -- 암호화된 비밀번호
  user_name VARCHAR(1024),          -- 한글명
  user_name_eng VARCHAR(1024),      -- 영문명
  user_name_cn VARCHAR(1024),       -- 중문명
  dept_code VARCHAR(1024),          -- 부서 코드
  dept_name VARCHAR(1024),          -- 부서명
  position_code VARCHAR(1024),      -- 직위 코드
  position_name VARCHAR(1024),      -- 직위명
  email VARCHAR(1024),              -- 이메일
  tel VARCHAR(1024),                -- 전화번호
  cell_phone VARCHAR(1024),         -- 휴대폰
  user_type VARCHAR(1024),          -- 사용자 유형 코드
  user_type_name VARCHAR(1024),     -- 사용자 유형명
  company_code VARCHAR(50),         -- 회사 코드 (멀티테넌시)
  status VARCHAR(32),               -- active/inactive
  license_number VARCHAR(50),       -- 면허번호
  vehicle_number VARCHAR(50),       -- 차량번호
  signup_type VARCHAR(20),          -- 가입 유형
  branch_name VARCHAR(100),         -- 지점명
  regdate TIMESTAMP,                -- 등록일
  end_date TIMESTAMP                -- 종료일
);

관련 테이블:

  • user_info_history: 사용자 정보 변경 이력
  • user_dept: 사용자-부서 관계
  • user_dept_sub: 사용자 하위 부서

auth_tokens (인증 토큰)

CREATE TABLE auth_tokens (
  id SERIAL PRIMARY KEY,
  user_id VARCHAR(255) NOT NULL,
  token VARCHAR(500) NOT NULL,
  refresh_token VARCHAR(500),
  expires_at TIMESTAMP NOT NULL,
  created_at TIMESTAMP DEFAULT NOW(),
  ip_address VARCHAR(50),
  user_agent TEXT
);

4.2 권한 관리

authority_master (권한 그룹)

CREATE TABLE authority_master (
  objid NUMERIC PRIMARY KEY,
  auth_code VARCHAR(64),           -- 권한 코드
  auth_name VARCHAR(64),           -- 권한명
  company_code VARCHAR(50),        -- 회사 코드
  status VARCHAR(32),              -- 상태
  writer VARCHAR(32),              -- 작성자
  regdate TIMESTAMP                -- 등록일
);

관련 테이블:

  • authority_master_history: 권한 변경 이력
  • authority_sub_user: 권한-사용자 매핑
  • rel_menu_auth: 권한-메뉴 매핑

4.3 메뉴 관리

menu_info (메뉴 정보)

CREATE TABLE menu_info (
  objid NUMERIC PRIMARY KEY,
  menu_type NUMERIC,               -- 0=일반, 1=시스템관리, 2=동적생성
  parent_obj_id NUMERIC,           -- 부모 메뉴 ID
  menu_name_kor VARCHAR(64),       -- 한글 메뉴명
  menu_name_eng VARCHAR(64),       -- 영문 메뉴명
  menu_code VARCHAR(50),           -- 메뉴 코드
  menu_url VARCHAR(256),           -- 메뉴 URL
  seq NUMERIC,                     -- 순서
  screen_code VARCHAR(50),         -- 화면 코드 (동적 생성 시)
  screen_group_id INTEGER,         -- 화면 그룹 ID
  company_code VARCHAR(50),        -- 회사 코드
  status VARCHAR(32),              -- active/inactive
  lang_key VARCHAR(100),           -- 다국어 키
  source_menu_objid BIGINT,        -- 원본 메뉴 ID (복사 시)
  writer VARCHAR(32),
  regdate TIMESTAMP
);

특징:

  • menu_type = 2: 화면 생성 시 자동으로 생성되는 메뉴
  • 트리거: auto_create_menu_for_screen() - 화면 생성 시 자동 메뉴 추가

관련 테이블:

  • menu_screen_groups: 메뉴 화면 그룹
  • menu_screen_group_items: 그룹-화면 연결

4.4 회사 관리

company_mng (회사 정보)

CREATE TABLE company_mng (
  company_code VARCHAR(32) PRIMARY KEY,
  company_name VARCHAR(64),
  business_registration_number VARCHAR(20), -- 사업자등록번호
  representative_name VARCHAR(100),         -- 대표자명
  representative_phone VARCHAR(20),         -- 대표 연락처
  email VARCHAR(255),                       -- 회사 이메일
  website VARCHAR(500),                     -- 웹사이트
  address VARCHAR(500),                     -- 주소
  status VARCHAR(32),
  writer VARCHAR(32),
  regdate TIMESTAMP
);

관련 테이블:

  • company_code_sequence: 회사별 시퀀스 관리

4.5 부서 관리

dept_info (부서 정보)

CREATE TABLE dept_info (
  dept_code VARCHAR(1024) PRIMARY KEY,
  dept_name VARCHAR(1024),
  parent_dept_code VARCHAR(1024),  -- 상위 부서
  company_code VARCHAR(50),
  status VARCHAR(32),
  writer VARCHAR(32),
  regdate TIMESTAMP
);

관련 테이블:

  • dept_info_history: 부서 정보 변경 이력

5. 메타데이터 관리 시스템

WACE ERP의 핵심 특징은 메타데이터 드리븐 아키텍처입니다. 화면, 테이블, 컬럼 정보를 메타데이터 테이블에서 관리하고, 프론트엔드가 이를 기반으로 동적 렌더링합니다.

5.1 테이블 메타데이터

table_labels (테이블 정의)

CREATE TABLE table_labels (
  table_name VARCHAR(100) PRIMARY KEY,  -- 테이블명 (물리명)
  table_label VARCHAR(200),             -- 테이블 한글명
  description TEXT,                     -- 설명
  use_log_table VARCHAR(1) DEFAULT 'N', -- 이력 테이블 사용 여부
  created_date TIMESTAMP,
  updated_date TIMESTAMP
);

역할:

  • 동적으로 생성된 모든 테이블의 메타정보 저장
  • 화면 생성 시 테이블 선택 목록 제공
  • 데이터 딕셔너리로 활용

table_type_columns (컬럼 타입 정의)

CREATE TABLE table_type_columns (
  id SERIAL PRIMARY KEY,
  table_name VARCHAR(255) NOT NULL,
  column_name VARCHAR(255) NOT NULL,
  company_code VARCHAR(20) NOT NULL,    -- 회사별 컬럼 설정
  input_type VARCHAR(50) DEFAULT 'text',-- 입력 타입
  detail_settings TEXT DEFAULT '{}',    -- JSON 상세 설정
  is_nullable VARCHAR(10) DEFAULT 'Y',
  display_order INTEGER DEFAULT 0,      -- 표시 순서
  created_date TIMESTAMP,
  updated_date TIMESTAMP,
  
  UNIQUE(table_name, column_name, company_code)
);

input_type 종류:

  • text: 일반 텍스트
  • number: 숫자
  • date: 날짜
  • select: 드롭다운 (options 필요)
  • textarea: 여러 줄 텍스트
  • entity: 참조 테이블 (referenceTable, referenceColumn 필요)
  • checkbox: 체크박스
  • radio: 라디오 버튼

detail_settings 예시:

// select 타입
{
  "options": [
    {"label": "일반", "value": "normal"},
    {"label": "긴급", "value": "urgent"}
  ]
}

// entity 타입
{
  "referenceTable": "customer_mng",
  "referenceColumn": "customer_code",
  "displayColumn": "customer_name"
}

column_labels (컬럼 라벨 - 레거시)

CREATE TABLE column_labels (
  table_name VARCHAR(100) NOT NULL,
  column_name VARCHAR(100) NOT NULL,
  column_label VARCHAR(200),         -- 한글 라벨
  input_type VARCHAR(50),
  detail_settings TEXT,
  description TEXT,
  display_order INTEGER,
  is_visible BOOLEAN DEFAULT true,
  created_date TIMESTAMP,
  updated_date TIMESTAMP,
  
  PRIMARY KEY (table_name, column_name)
);

참고:

  • 레거시 호환을 위해 유지
  • 새로운 컬럼은 table_type_columns 사용 권장
  • table_type_columns는 회사별 설정, column_labels는 전역 설정

5.2 카테고리 값 관리

table_column_category_values (컬럼 카테고리 값)

CREATE TABLE table_column_category_values (
  id SERIAL PRIMARY KEY,
  table_name VARCHAR(255) NOT NULL,
  column_name VARCHAR(255) NOT NULL,
  company_code VARCHAR(20) NOT NULL,
  category_value VARCHAR(500) NOT NULL, -- 카테고리 값
  display_label VARCHAR(500),           -- 표시 라벨
  display_order INTEGER DEFAULT 0,
  is_active VARCHAR(1) DEFAULT 'Y',
  parent_value VARCHAR(500),            -- 부모 카테고리 (계층 구조)
  created_date TIMESTAMP,
  updated_date TIMESTAMP,
  
  UNIQUE(table_name, column_name, company_code, category_value)
);

용도:

  • 동적 드롭다운 값 관리
  • 계층형 카테고리 지원 (parent_value)
  • 회사별 카테고리 값 커스터마이징

관련 테이블:

  • category_column_mapping: 카테고리-컬럼 매핑
  • category_value_cascading_group: 카테고리 캐스케이딩 그룹
  • category_value_cascading_mapping: 캐스케이딩 매핑

5.3 테이블 관계 관리

table_relationships (테이블 관계)

CREATE TABLE table_relationships (
  id SERIAL PRIMARY KEY,
  parent_table VARCHAR(100),       -- 부모 테이블
  parent_column VARCHAR(100),      -- 부모 컬럼
  child_table VARCHAR(100),        -- 자식 테이블
  child_column VARCHAR(100),       -- 자식 컬럼
  relationship_type VARCHAR(20),   -- one-to-many, many-to-one 등
  created_date TIMESTAMP
);

6. 화면 관리 시스템

WACE ERP는 코드 작성 없이 화면을 동적으로 생성/수정할 수 있는 Low-Code 플랫폼 기능을 제공합니다.

6.1 화면 정의

screen_definitions (화면 정의)

CREATE TABLE screen_definitions (
  screen_id SERIAL PRIMARY KEY,
  screen_name VARCHAR(100) NOT NULL,    -- 화면명
  screen_code VARCHAR(50) NOT NULL,     -- 화면 코드 (URL용)
  table_name VARCHAR(100) NOT NULL,     -- 메인 테이블
  company_code VARCHAR(50) NOT NULL,
  description TEXT,
  is_active CHAR(1) DEFAULT 'Y',        -- Y=활성, N=비활성, D=삭제
  layout_metadata JSONB,                -- 레이아웃 JSON
  
  -- 외부 데이터 소스 지원
  db_source_type VARCHAR(10) DEFAULT 'internal',     -- internal/external
  db_connection_id INTEGER,                          -- 외부 DB 연결 ID
  data_source_type VARCHAR(20) DEFAULT 'database',   -- database/rest_api
  rest_api_connection_id INTEGER,                    -- REST API 연결 ID
  rest_api_endpoint VARCHAR(500),                    -- API 엔드포인트
  rest_api_json_path VARCHAR(200) DEFAULT 'data',    -- JSON 응답 경로
  
  source_screen_id INTEGER,             -- 원본 화면 ID (복사 시)
  
  created_date TIMESTAMP NOT NULL DEFAULT NOW(),
  created_by VARCHAR(50),
  updated_date TIMESTAMP NOT NULL DEFAULT NOW(),
  updated_by VARCHAR(50),
  deleted_date TIMESTAMP,               -- 휴지통 이동 시점
  deleted_by VARCHAR(50),
  delete_reason TEXT,
  
  UNIQUE(screen_code, company_code)
);

화면 생성 플로우:

  1. 관리자가 화면 설정 페이지에서 테이블 선택
  2. screen_definitions 레코드 생성
  3. 트리거 auto_create_menu_for_screen() 실행 → menu_info 자동 생성
  4. 프론트엔드가 /screen/{screen_code} 경로로 접근 시 동적 렌더링

screen_layouts (화면 레이아웃 - 레거시)

CREATE TABLE screen_layouts (
  layout_id SERIAL PRIMARY KEY,
  screen_id INTEGER REFERENCES screen_definitions(screen_id),
  layout_name VARCHAR(100),
  layout_type VARCHAR(50),         -- grid, form, split, tab 등
  layout_config JSONB,             -- 레이아웃 설정
  display_order INTEGER,
  is_active CHAR(1) DEFAULT 'Y',
  company_code VARCHAR(50),
  created_date TIMESTAMP,
  updated_date TIMESTAMP
);

6.2 화면 그룹 관리

screen_groups (화면 그룹)

CREATE TABLE screen_groups (
  id SERIAL PRIMARY KEY,
  group_name VARCHAR(100) NOT NULL,     -- 그룹명
  group_code VARCHAR(50) NOT NULL,      -- 그룹 코드
  main_table_name VARCHAR(100),         -- 메인 테이블
  description TEXT,
  icon VARCHAR(100),                    -- 아이콘
  display_order INT DEFAULT 0,
  is_active VARCHAR(1) DEFAULT 'Y',
  company_code VARCHAR(20) NOT NULL,
  
  -- 계층 구조 지원 (037 마이그레이션에서 추가)
  parent_group_id INTEGER REFERENCES screen_groups(id) ON DELETE CASCADE,
  group_level INTEGER DEFAULT 0,        -- 0=대, 1=중, 2=소
  hierarchy_path VARCHAR(500),          -- 예: /1/3/5/
  
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW(),
  writer VARCHAR(50),
  
  UNIQUE(company_code, group_code)
);

CREATE INDEX idx_screen_groups_company_code ON screen_groups(company_code);
CREATE INDEX idx_screen_groups_parent_id ON screen_groups(parent_group_id);
CREATE INDEX idx_screen_groups_hierarchy_path ON screen_groups(hierarchy_path);

screen_group_screens (화면-그룹 연결)

CREATE TABLE screen_group_screens (
  id SERIAL PRIMARY KEY,
  group_id INT NOT NULL REFERENCES screen_groups(id) ON DELETE CASCADE,
  screen_id INT NOT NULL REFERENCES screen_definitions(screen_id) ON DELETE CASCADE,
  screen_role VARCHAR(50) DEFAULT 'main',  -- main, register, list, detail 등
  display_order INT DEFAULT 0,
  is_default VARCHAR(1) DEFAULT 'N',       -- 기본 화면 여부
  company_code VARCHAR(20) NOT NULL,
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW(),
  writer VARCHAR(50),
  
  UNIQUE(group_id, screen_id)
);

용도:

  • 관련 화면들을 그룹으로 묶어 관리
  • 예: "영업 관리" 그룹 → 견적 화면, 수주 화면, 출하 화면

6.3 화면 필드 조인

screen_field_joins (화면 필드 조인 설정)

CREATE TABLE screen_field_joins (
  id SERIAL PRIMARY KEY,
  screen_id INT NOT NULL REFERENCES screen_definitions(screen_id) ON DELETE CASCADE,
  layout_id INT,
  component_id VARCHAR(500),
  field_name VARCHAR(100),
  
  -- 저장 테이블 설정
  save_table VARCHAR(100) NOT NULL,
  save_column VARCHAR(100) NOT NULL,
  
  -- 조인 테이블 설정
  join_table VARCHAR(100) NOT NULL,
  join_column VARCHAR(100) NOT NULL,
  display_column VARCHAR(100) NOT NULL,
  
  -- 조인 옵션
  join_type VARCHAR(20) DEFAULT 'LEFT',
  filter_condition TEXT,
  sort_column VARCHAR(100),
  sort_direction VARCHAR(10) DEFAULT 'ASC',
  
  is_active VARCHAR(1) DEFAULT 'Y',
  company_code VARCHAR(20) NOT NULL,
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW(),
  writer VARCHAR(50)
);

예시:

{
  "save_table": "sales_order",
  "save_column": "customer_code",
  "join_table": "customer_mng",
  "join_column": "customer_code",
  "display_column": "customer_name"
}

6.4 화면 간 데이터 흐름

screen_data_flows (화면 간 데이터 흐름)

CREATE TABLE screen_data_flows (
  id SERIAL PRIMARY KEY,
  group_id INT REFERENCES screen_groups(id) ON DELETE SET NULL,
  
  -- 소스 화면
  source_screen_id INT NOT NULL REFERENCES screen_definitions(screen_id) ON DELETE CASCADE,
  source_action VARCHAR(50),           -- click, submit, select 등
  
  -- 타겟 화면
  target_screen_id INT NOT NULL REFERENCES screen_definitions(screen_id) ON DELETE CASCADE,
  target_action VARCHAR(50),           -- open, load, refresh 등
  
  -- 데이터 매핑 설정
  data_mapping JSONB,                  -- 필드 매핑 정보
  
  -- 흐름 설정
  flow_type VARCHAR(20) DEFAULT 'unidirectional', -- unidirectional/bidirectional
  flow_label VARCHAR(100),             -- 시각화 라벨
  condition_expression TEXT,           -- 실행 조건식
  
  is_active VARCHAR(1) DEFAULT 'Y',
  company_code VARCHAR(20) NOT NULL,
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW(),
  writer VARCHAR(50)
);

data_mapping 예시:

{
  "customer_code": "customer_code",
  "customer_name": "customer_name",
  "selected_date": "order_date"
}

screen_table_relations (화면-테이블 관계)

CREATE TABLE screen_table_relations (
  id SERIAL PRIMARY KEY,
  group_id INT REFERENCES screen_groups(id) ON DELETE SET NULL,
  screen_id INT NOT NULL REFERENCES screen_definitions(screen_id) ON DELETE CASCADE,
  table_name VARCHAR(100) NOT NULL,
  
  relation_type VARCHAR(20) DEFAULT 'main',  -- main, join, lookup
  crud_operations VARCHAR(20) DEFAULT 'CRUD',-- CRUD 조합
  description TEXT,
  
  is_active VARCHAR(1) DEFAULT 'Y',
  company_code VARCHAR(20) NOT NULL,
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW(),
  writer VARCHAR(50)
);

6.5 컴포넌트 표준

component_standards (컴포넌트 표준)

CREATE TABLE component_standards (
  component_code VARCHAR(50) PRIMARY KEY,
  component_name VARCHAR(100) NOT NULL,
  component_name_eng VARCHAR(100),
  description TEXT,
  category VARCHAR(50) NOT NULL,       -- input, layout, display 등
  icon_name VARCHAR(50),
  default_size JSON,                   -- {width, height}
  component_config JSON NOT NULL,      -- 컴포넌트 설정
  preview_image VARCHAR(255),
  sort_order INTEGER DEFAULT 0,
  is_active CHAR(1) DEFAULT 'Y',
  is_public CHAR(1) DEFAULT 'Y',
  company_code VARCHAR(50) NOT NULL,
  created_date TIMESTAMP,
  updated_date TIMESTAMP
);

layout_standards (레이아웃 표준)

CREATE TABLE layout_standards (
  layout_code VARCHAR(50) PRIMARY KEY,
  layout_name VARCHAR(100) NOT NULL,
  layout_type VARCHAR(50),             -- grid, form, split, tab
  default_config JSON,
  is_active CHAR(1) DEFAULT 'Y',
  company_code VARCHAR(50),
  created_date TIMESTAMP,
  updated_date TIMESTAMP
);

7. 비즈니스 도메인별 테이블

7.1 영업/수주 관리

수주 관리 (Order Management)

sales_order_mng          -- 수주 마스터
├── sales_order_detail   -- 수주 상세
├── sales_order_detail_log -- 수주 상세 이력
├── sales_request_master -- 영업 요청 마스터
├── sales_request_part   -- 영업 요청 부품
└── sales_part_chg       -- 영업 부품 변경

sales_order_mng:

  • 고객별 수주 정보
  • 납기, 금액, 상태 관리

sales_order_detail:

  • 수주 라인 아이템
  • 품목, 수량, 단가 정보

견적 관리

estimate_mgmt            -- 견적 관리
contract_mgmt            -- 계약 관리
├── contract_mgmt_option -- 계약 옵션

BOM 관리

sales_bom_report         -- 영업 BOM 리포트
├── sales_bom_report_part -- 영업 BOM 부품
└── sales_bom_part_qty   -- 영업 BOM 부품 수량

7.2 구매/발주 관리

purchase_order_master    -- 발주 마스터
├── purchase_order       -- 발주 상세
├── purchase_order_part  -- 발주 부품
├── purchase_order_multi -- 다중 발주
└── purchase_detail      -- 구매 상세

supplier_mng             -- 공급업체 관리
├── supplier_mng_log     -- 공급업체 이력
├── supplier_item        -- 공급업체 품목
├── supplier_item_alias  -- 공급업체 품목 별칭
├── supplier_item_mapping -- 공급업체 품목 매핑
└── supplier_item_price  -- 공급업체 품목 가격

7.3 재고/창고 관리

inventory_stock          -- 재고 현황
inventory_history        -- 재고 이력
warehouse_info           -- 창고 정보
warehouse_location       -- 창고 위치
inbound_mng              -- 입고 관리
outbound_mng             -- 출고 관리
receiving                -- 입하
receive_history          -- 입하 이력

7.4 생산/작업 관리

work_orders              -- 작업지시 (신규)
├── work_orders_detail   -- 작업지시 상세
work_order               -- 작업지시 (레거시)
work_instruction         -- 작업 지시서
├── work_instruction_detail -- 작업 지시서 상세
├── work_instruction_detail_log
└── work_instruction_log

production_record        -- 생산 실적
production_task          -- 생산 작업
production_issue         -- 생산 이슈
work_request             -- 작업 요청

work_orders (작업지시 - 050 마이그레이션)

CREATE TABLE work_orders (
  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),
  
  -- 작업지시 정보
  wo_number VARCHAR(500),           -- WO-20250130-001
  product_code VARCHAR(500),
  product_name VARCHAR(500),
  spec VARCHAR(500),
  order_qty VARCHAR(500),
  completed_qty VARCHAR(500),
  start_date VARCHAR(500),
  due_date VARCHAR(500),
  status VARCHAR(500),              -- normal/urgent
  progress_status VARCHAR(500),     -- pending/in-progress/completed
  equipment VARCHAR(500),
  routing VARCHAR(500),
  work_team VARCHAR(500),           -- DAY/NIGHT
  worker VARCHAR(500),
  shift VARCHAR(500),               -- DAY/NIGHT
  remark VARCHAR(500)
);

CREATE INDEX idx_work_orders_company_code ON work_orders(company_code);
CREATE INDEX idx_work_orders_wo_number ON work_orders(wo_number);

7.5 품질/검사 관리

inspection_standard      -- 검사 기준
item_inspection_info     -- 품목 검사 정보
inspection_equipment_mng -- 검사 설비 관리
├── inspection_equipment_mng_log
defect_standard_mng      -- 불량 기준 관리
├── defect_standard_mng_log
check_report_mng         -- 검사 성적서 관리
safety_inspections       -- 안전 점검
└── safety_inspections_log

7.6 물류/운송 관리

vehicles                 -- 차량 정보
├── vehicle_locations    -- 차량 위치
├── vehicle_location_history -- 차량 위치 이력
├── vehicle_trip_summary -- 차량 운행 요약
drivers                  -- 운전자 정보
transport_logs           -- 운송 로그
transport_statistics     -- 운송 통계
transport_vehicle_locations -- 차량 위치

carrier_mng              -- 운송사 관리
├── carrier_mng_log
├── carrier_contract_mng -- 운송사 계약
├── carrier_contract_mng_log
├── carrier_vehicle_mng  -- 운송사 차량
└── carrier_vehicle_mng_log

delivery_route_mng       -- 배송 경로 관리
├── delivery_route_mng_log
delivery_destination     -- 배송지
delivery_status          -- 배송 상태
delivery_history         -- 배송 이력
├── delivery_history_defect -- 배송 불량
delivery_part_price      -- 배송 부품 가격

DTG 관리 (디지털 타코그래프)

dtg_management           -- DTG 관리
├── dtg_management_log
dtg_contracts            -- DTG 계약
dtg_maintenance_history  -- DTG 정비 이력
dtg_monthly_settlements  -- DTG 월별 정산

7.7 PLM/설계 관리

part_mng                 -- 부품 관리 (메인)
├── part_mng_history
part_mgmt                -- 부품 관리 (서브)
part_bom_qty             -- 부품 BOM 수량
part_bom_report          -- 부품 BOM 리포트
part_distribution_list   -- 부품 배포 목록

item_info                -- 품목 정보
item_routing_version     -- 품목 라우팅 버전
item_routing_detail      -- 품목 라우팅 상세

product_mng              -- 제품 관리
product_mgmt             -- 제품 관리 (메인)
├── product_mgmt_model   -- 제품 모델
├── product_mgmt_price_history -- 제품 가격 이력
├── product_mgmt_upg_master -- 제품 업그레이드 마스터
└── product_mgmt_upg_detail -- 제품 업그레이드 상세

product_kind_spec        -- 제품 종류 사양
product_kind_spec_main   -- 제품 종류 사양 메인
product_spec             -- 제품 사양
product_group_mng        -- 제품 그룹 관리

mold_dev_request_info    -- 금형 개발 요청
structural_review_proposal -- 구조 검토 제안

7.8 프로젝트 관리 (PMS)

pms_pjt_info             -- 프로젝트 정보
├── pms_pjt_concept_info -- 프로젝트 개념 정보
├── pms_pjt_year_goal    -- 프로젝트 연도 목표
pms_wbs_task             -- WBS 작업
├── pms_wbs_task_info    -- WBS 작업 정보
├── pms_wbs_task_confirm -- WBS 작업 확인
├── pms_wbs_task_standard -- WBS 작업 표준
└── pms_wbs_template     -- WBS 템플릿

pms_rel_pjt_concept_milestone -- 프로젝트 개념-마일스톤 관계
pms_rel_pjt_concept_prod      -- 프로젝트 개념-제품 관계
pms_rel_pjt_prod              -- 프로젝트-제품 관계
pms_rel_prod_ref_dept         -- 제품-참조부서 관계

pms_invest_cost_mng      -- 투자 비용 관리
project_mgmt             -- 프로젝트 관리
problem_mng              -- 문제 관리
planning_issue           -- 계획 이슈

7.9 회계/원가 관리

tax_invoice              -- 세금계산서
├── tax_invoice_item     -- 세금계산서 항목
fund_mgmt                -- 자금 관리
expense_master           -- 비용 마스터
├── expense_detail       -- 비용 상세

profit_loss              -- 손익 계산
├── profit_loss_total    -- 손익 합계
├── profit_loss_coefficient -- 손익 계수
├── profit_loss_machine  -- 손익 기계
├── profit_loss_weight   -- 손익 무게
├── profit_loss_depth    -- 손익 깊이
├── profit_loss_pretime  -- 손익 사전 시간
├── profit_loss_coolingtime -- 손익 냉각 시간
├── profit_loss_lossrate -- 손익 손실률
└── profit_loss_srrate   -- 손익 SR률

material_cost            -- 자재 비용
injection_cost           -- 사출 비용
logistics_cost_mng       -- 물류 비용 관리
└── logistics_cost_mng_log

input_cost_goal          -- 투입 비용 목표
input_resource           -- 투입 자원

7.10 고객/협력사 관리

customer_mng             -- 고객 관리
customer_item            -- 고객 품목
├── customer_item_alias  -- 고객 품목 별칭
├── customer_item_mapping -- 고객 품목 매핑
└── customer_item_price  -- 고객 품목 가격

customer_service_mgmt    -- 고객 서비스 관리
├── customer_service_part -- 고객 서비스 부품
└── customer_service_workingtime -- 고객 서비스 작업시간

oem_mng                  -- OEM 관리
├── oem_factory_mng      -- OEM 공장 관리
└── oem_milestone_mng    -- OEM 마일스톤 관리

7.11 설비/장비 관리

equipment_mng            -- 설비 관리
├── equipment_mng_log
equipment_consumable     -- 설비 소모품
├── equipment_consumable_log
equipment_inspection_item -- 설비 검사 항목
└── equipment_inspection_item_log

process_equipment        -- 공정 설비
process_mng              -- 공정 관리
maintenance_schedules    -- 정비 일정

7.12 기타

approval                 -- 결재
comments                 -- 댓글
inboxtask                -- 수신함 작업
time_sheet               -- 작업 시간
attach_file_info         -- 첨부 파일
file_down_log            -- 파일 다운로드 로그
login_access_log         -- 로그인 접근 로그

8. 플로우 및 데이터 통합

8.1 플로우 정의

flow_definition (플로우 정의)

CREATE TABLE flow_definition (
  flow_id SERIAL PRIMARY KEY,
  flow_name VARCHAR(200) NOT NULL,
  flow_code VARCHAR(100) NOT NULL,
  flow_type VARCHAR(50),           -- data_transfer, approval, batch 등
  description TEXT,
  trigger_type VARCHAR(50),        -- manual, schedule, event
  trigger_config JSONB,
  is_active VARCHAR(1) DEFAULT 'Y',
  company_code VARCHAR(20),
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW(),
  created_by VARCHAR(50),
  updated_by VARCHAR(50),
  
  UNIQUE(flow_code, company_code)
);

flow_step (플로우 단계)

CREATE TABLE flow_step (
  step_id SERIAL PRIMARY KEY,
  flow_id INTEGER REFERENCES flow_definition(flow_id) ON DELETE CASCADE,
  step_name VARCHAR(200) NOT NULL,
  step_type VARCHAR(50) NOT NULL,  -- query, transform, api_call, condition 등
  step_order INTEGER NOT NULL,
  step_config JSONB NOT NULL,
  error_handling_config JSONB,
  is_active VARCHAR(1) DEFAULT 'Y',
  company_code VARCHAR(20),
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW()
);

flow_step_connection (플로우 단계 연결)

CREATE TABLE flow_step_connection (
  connection_id SERIAL PRIMARY KEY,
  flow_id INTEGER REFERENCES flow_definition(flow_id) ON DELETE CASCADE,
  source_step_id INTEGER REFERENCES flow_step(step_id) ON DELETE CASCADE,
  target_step_id INTEGER REFERENCES flow_step(step_id) ON DELETE CASCADE,
  condition_expression TEXT,       -- 조건부 실행
  connection_type VARCHAR(20) DEFAULT 'sequential', -- sequential, parallel, conditional
  company_code VARCHAR(20),
  created_date TIMESTAMPTZ DEFAULT NOW()
);

8.2 데이터플로우

dataflow_diagrams (데이터플로우 다이어그램)

CREATE TABLE dataflow_diagrams (
  diagram_id SERIAL PRIMARY KEY,
  diagram_name VARCHAR(200) NOT NULL,
  diagram_type VARCHAR(50),
  diagram_json JSONB NOT NULL,     -- 다이어그램 시각화 정보
  description TEXT,
  is_active VARCHAR(1) DEFAULT 'Y',
  company_code VARCHAR(20),
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW(),
  created_by VARCHAR(50),
  updated_by VARCHAR(50)
);

flow_data_mapping (플로우 데이터 매핑)

CREATE TABLE flow_data_mapping (
  mapping_id SERIAL PRIMARY KEY,
  flow_id INTEGER REFERENCES flow_definition(flow_id) ON DELETE CASCADE,
  source_type VARCHAR(20),         -- table, api, flow
  source_identifier VARCHAR(200),  -- 테이블명 또는 API 엔드포인트
  source_field VARCHAR(100),
  target_type VARCHAR(20),
  target_identifier VARCHAR(200),
  target_field VARCHAR(100),
  transformation_rule TEXT,        -- 변환 규칙 (JavaScript 표현식)
  company_code VARCHAR(20),
  created_date TIMESTAMPTZ DEFAULT NOW()
);

flow_data_status (플로우 데이터 상태)

CREATE TABLE flow_data_status (
  status_id SERIAL PRIMARY KEY,
  flow_id INTEGER REFERENCES flow_definition(flow_id),
  execution_id VARCHAR(100),
  source_table VARCHAR(100),
  source_record_id VARCHAR(500),
  target_table VARCHAR(100),
  target_record_id VARCHAR(500),
  status VARCHAR(20),              -- pending, processing, completed, failed
  error_message TEXT,
  processed_at TIMESTAMPTZ,
  company_code VARCHAR(20),
  created_date TIMESTAMPTZ DEFAULT NOW()
);

8.3 외부 연동

external_db_connections (외부 DB 연결)

CREATE TABLE external_db_connections (
  id SERIAL PRIMARY KEY,
  connection_name VARCHAR(200) NOT NULL,
  connection_code VARCHAR(100) NOT NULL,
  db_type VARCHAR(50) NOT NULL,    -- postgresql, mysql, mssql, oracle
  host VARCHAR(255) NOT NULL,
  port INTEGER NOT NULL,
  database_name VARCHAR(100) NOT NULL,
  username VARCHAR(100),
  password_encrypted TEXT,
  ssl_enabled BOOLEAN DEFAULT false,
  connection_options JSONB,
  is_active VARCHAR(1) DEFAULT 'Y',
  company_code VARCHAR(20),
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW(),
  created_by VARCHAR(50),
  
  UNIQUE(connection_code, company_code)
);

external_rest_api_connections (외부 REST API 연결)

CREATE TABLE external_rest_api_connections (
  id SERIAL PRIMARY KEY,
  connection_name VARCHAR(200) NOT NULL,
  connection_code VARCHAR(100) NOT NULL,
  base_url VARCHAR(500) NOT NULL,
  auth_type VARCHAR(50),           -- none, basic, bearer, api_key
  auth_config JSONB,
  default_headers JSONB,
  timeout_seconds INTEGER DEFAULT 30,
  retry_count INTEGER DEFAULT 0,
  is_active VARCHAR(1) DEFAULT 'Y',
  company_code VARCHAR(20),
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW(),
  
  UNIQUE(connection_code, company_code)
);

external_call_configs (외부 호출 설정)

CREATE TABLE external_call_configs (
  id SERIAL PRIMARY KEY,
  config_name VARCHAR(200) NOT NULL,
  config_code VARCHAR(100) NOT NULL,
  connection_id INTEGER,           -- external_rest_api_connections 참조
  http_method VARCHAR(10),         -- GET, POST, PUT, DELETE
  endpoint_path VARCHAR(500),
  request_mapping JSONB,           -- 요청 데이터 매핑
  response_mapping JSONB,          -- 응답 데이터 매핑
  error_handling JSONB,
  is_active VARCHAR(1) DEFAULT 'Y',
  company_code VARCHAR(20),
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW()
);

8.4 배치 작업

batch_jobs (배치 작업 정의)

CREATE TABLE batch_jobs (
  job_id SERIAL PRIMARY KEY,
  job_name VARCHAR(200) NOT NULL,
  job_code VARCHAR(100) NOT NULL,
  job_type VARCHAR(50),            -- data_collection, aggregation, sync 등
  source_type VARCHAR(50),         -- database, api, file
  source_config JSONB,
  target_config JSONB,
  schedule_config JSONB,
  is_active VARCHAR(1) DEFAULT 'Y',
  company_code VARCHAR(20),
  created_date TIMESTAMPTZ DEFAULT NOW(),
  updated_date TIMESTAMPTZ DEFAULT NOW(),
  
  UNIQUE(job_code, company_code)
);

batch_execution_logs (배치 실행 로그)

CREATE TABLE batch_execution_logs (
  execution_id SERIAL PRIMARY KEY,
  job_id INTEGER REFERENCES batch_jobs(job_id),
  execution_status VARCHAR(20),    -- running, completed, failed
  start_time TIMESTAMPTZ,
  end_time TIMESTAMPTZ,
  records_processed INTEGER,
  records_failed INTEGER,
  error_message TEXT,
  execution_details JSONB,
  company_code VARCHAR(20),
  created_date TIMESTAMPTZ DEFAULT NOW()
);

9. 인덱스 전략

9.1 필수 인덱스

모든 테이블에 적용:

-- company_code 인덱스 (멀티테넌시 성능)
CREATE INDEX idx_{table_name}_company_code ON {table_name}(company_code);

-- 복합 인덱스 (company_code + 주요 검색 컬럼)
CREATE INDEX idx_{table_name}_company_{column} 
ON {table_name}(company_code, {column});

9.2 화면 관련 인덱스

-- screen_definitions
CREATE INDEX idx_screen_definitions_company_code ON screen_definitions(company_code);
CREATE INDEX idx_screen_definitions_table_name ON screen_definitions(table_name);
CREATE INDEX idx_screen_definitions_is_active ON screen_definitions(is_active);
CREATE UNIQUE INDEX idx_screen_definitions_code_company 
ON screen_definitions(screen_code, company_code);

-- screen_groups
CREATE INDEX idx_screen_groups_company_code ON screen_groups(company_code);
CREATE INDEX idx_screen_groups_parent_id ON screen_groups(parent_group_id);
CREATE INDEX idx_screen_groups_hierarchy_path ON screen_groups(hierarchy_path);

-- screen_field_joins
CREATE INDEX idx_screen_field_joins_screen_id ON screen_field_joins(screen_id);
CREATE INDEX idx_screen_field_joins_save_table ON screen_field_joins(save_table);
CREATE INDEX idx_screen_field_joins_join_table ON screen_field_joins(join_table);

9.3 메타데이터 인덱스

-- table_type_columns
CREATE UNIQUE INDEX idx_table_type_columns_unique 
ON table_type_columns(table_name, column_name, company_code);

-- column_labels
CREATE INDEX idx_column_labels_table ON column_labels(table_name);

9.4 비즈니스 테이블 인덱스 예시

-- sales_order_mng
CREATE INDEX idx_sales_order_company_code ON sales_order_mng(company_code);
CREATE INDEX idx_sales_order_customer ON sales_order_mng(customer_code);
CREATE INDEX idx_sales_order_date ON sales_order_mng(order_date DESC);
CREATE INDEX idx_sales_order_status ON sales_order_mng(order_status);

-- work_orders
CREATE INDEX idx_work_orders_company_code ON work_orders(company_code);
CREATE INDEX idx_work_orders_wo_number ON work_orders(wo_number);
CREATE INDEX idx_work_orders_start_date ON work_orders(start_date);
CREATE INDEX idx_work_orders_product_code ON work_orders(product_code);

9.5 플로우 관련 인덱스

-- flow_definition
CREATE UNIQUE INDEX idx_flow_definition_code_company 
ON flow_definition(flow_code, company_code);

-- flow_step
CREATE INDEX idx_flow_step_flow_id ON flow_step(flow_id);
CREATE INDEX idx_flow_step_order ON flow_step(flow_id, step_order);

-- flow_data_status
CREATE INDEX idx_flow_data_status_flow_execution 
ON flow_data_status(flow_id, execution_id);
CREATE INDEX idx_flow_data_status_source 
ON flow_data_status(source_table, source_record_id);

10. 동적 테이블 생성 패턴

WACE ERP의 핵심 기능 중 하나는 런타임에 테이블을 동적으로 생성할 수 있다는 것입니다.

10.1 표준 컬럼 구조

모든 동적 생성 테이블의 기본 컬럼:

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))
  {user_column_1} VARCHAR(500),
  {user_column_2} VARCHAR(500),
  ...
);

-- 필수 인덱스
CREATE INDEX idx_{table_name}_company_code ON {table_name}(company_code);

10.2 메타데이터 등록 프로세스

동적 테이블 생성 시 반드시 수행해야 하는 작업:

1단계: 테이블 생성

CREATE TABLE {table_name} (
  -- 위의 표준 구조 참조
);

2단계: table_labels 등록

INSERT INTO table_labels (table_name, table_label, description, created_date, updated_date)
VALUES ('{table_name}', '{한글명}', '{설명}', NOW(), NOW())
ON CONFLICT (table_name)
DO UPDATE SET
  table_label = EXCLUDED.table_label,
  description = EXCLUDED.description,
  updated_date = NOW();

3단계: table_type_columns 등록

-- 기본 컬럼 등록 (display_order: -5 ~ -1)
INSERT INTO table_type_columns (
  table_name, column_name, company_code, input_type, detail_settings,
  is_nullable, display_order, created_date, updated_date
) VALUES
  ('{table_name}', 'id', '{company_code}', 'text', '{}', 'Y', -5, NOW(), NOW()),
  ('{table_name}', 'created_date', '{company_code}', 'date', '{}', 'Y', -4, NOW(), NOW()),
  ('{table_name}', 'updated_date', '{company_code}', 'date', '{}', 'Y', -3, NOW(), NOW()),
  ('{table_name}', 'writer', '{company_code}', 'text', '{}', 'Y', -2, NOW(), NOW()),
  ('{table_name}', 'company_code', '{company_code}', 'text', '{}', 'Y', -1, NOW(), NOW())
ON CONFLICT (table_name, column_name, company_code)
DO UPDATE SET
  input_type = EXCLUDED.input_type,
  display_order = EXCLUDED.display_order,
  updated_date = NOW();

-- 사용자 정의 컬럼 등록 (display_order: 0부터 시작)
INSERT INTO table_type_columns (
  table_name, column_name, company_code, input_type, detail_settings,
  is_nullable, display_order, created_date, updated_date
) VALUES
  ('{table_name}', '{column_1}', '{company_code}', 'text', '{}', 'Y', 0, NOW(), NOW()),
  ('{table_name}', '{column_2}', '{company_code}', 'number', '{}', 'Y', 1, NOW(), NOW()),
  ...

4단계: column_labels 등록 (레거시 호환용)

INSERT INTO column_labels (
  table_name, column_name, column_label, input_type, detail_settings,
  description, display_order, is_visible, created_date, updated_date
) VALUES
  ('{table_name}', 'id', 'ID', 'text', '{}', '기본키', -5, true, NOW(), NOW()),
  ...
ON CONFLICT (table_name, column_name)
DO UPDATE SET
  column_label = EXCLUDED.column_label,
  input_type = EXCLUDED.input_type,
  updated_date = NOW();

10.3 마이그레이션 예시

050_create_work_orders_table.sql:

-- ============================================
-- 1. 테이블 생성
-- ============================================
CREATE TABLE work_orders (
  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),
  
  wo_number VARCHAR(500),
  product_code VARCHAR(500),
  product_name VARCHAR(500),
  ...
);

CREATE INDEX idx_work_orders_company_code ON work_orders(company_code);
CREATE INDEX idx_work_orders_wo_number ON work_orders(wo_number);

-- ============================================
-- 2. table_labels 등록
-- ============================================
INSERT INTO table_labels (table_name, table_label, description, created_date, updated_date)
VALUES ('work_orders', '작업지시', '작업지시 관리 테이블', NOW(), NOW())
ON CONFLICT (table_name) DO UPDATE SET ...;

-- ============================================
-- 3. table_type_columns 등록
-- ============================================
INSERT INTO table_type_columns (...) VALUES (...);

-- ============================================
-- 4. column_labels 등록
-- ============================================
INSERT INTO column_labels (...) VALUES (...);

-- ============================================
-- 5. 코멘트 추가
-- ============================================
COMMENT ON TABLE work_orders IS '작업지시 관리 테이블';
COMMENT ON COLUMN work_orders.wo_number IS '작업지시번호 (WO-YYYYMMDD-XXX)';

11. 마이그레이션 히스토리

11.1 마이그레이션 파일 목록

db/migrations/
├── 037_add_parent_group_to_screen_groups.sql    -- 화면 그룹 계층 구조
├── 050_create_work_orders_table.sql             -- 작업지시 테이블
├── 051_insert_work_order_screen_definition.sql  -- 작업지시 화면 정의
├── 052_insert_work_order_screen_layout.sql      -- 작업지시 화면 레이아웃
├── 054_create_screen_management_enhancement.sql -- 화면 관리 기능 확장
└── plm_schema_20260120.sql                      -- 전체 스키마 덤프

11.2 주요 마이그레이션 내용

037: 화면 그룹 계층 구조

  • screen_groups에 계층 구조 지원 추가
  • parent_group_id, group_level, hierarchy_path 컬럼 추가
  • 대/중/소 분류 지원

050~052: 작업지시 시스템

  • work_orders 테이블 생성
  • 메타데이터 등록 (table_labels, table_type_columns, column_labels)
  • 화면 정의 및 레이아웃 생성

054: 화면 관리 기능 확장

  • screen_groups: 화면 그룹
  • screen_group_screens: 화면-그룹 연결
  • screen_field_joins: 화면 필드 조인 설정
  • screen_data_flows: 화면 간 데이터 흐름
  • screen_table_relations: 화면-테이블 관계

11.3 마이그레이션 실행 가이드

마이그레이션 문서:

  • RUN_027_MIGRATION.md
  • RUN_043_MIGRATION.md
  • RUN_044_MIGRATION.md
  • RUN_046_MIGRATION.md
  • RUN_063_064_MIGRATION.md
  • RUN_065_MIGRATION.md
  • RUN_078_MIGRATION.md

12. 데이터베이스 함수 및 트리거

12.1 주요 함수

화면 관련

-- 화면 생성 시 메뉴 자동 생성
CREATE FUNCTION auto_create_menu_for_screen() RETURNS TRIGGER;

-- 화면 삭제 시 메뉴 비활성화
CREATE FUNCTION auto_deactivate_menu_for_screen() RETURNS TRIGGER;

통계 집계

-- 일일 운송 통계 집계
CREATE FUNCTION aggregate_daily_transport_statistics(target_date DATE) RETURNS INTEGER;

거리 계산

-- Haversine 거리 계산
CREATE FUNCTION calculate_distance(lat1 NUMERIC, lng1 NUMERIC, lat2 NUMERIC, lng2 NUMERIC) 
RETURNS NUMERIC;

-- 이전 위치로부터 거리 계산
CREATE FUNCTION calculate_distance_from_prev() RETURNS TRIGGER;

비즈니스 로직

-- 수주 잔량 계산
CREATE FUNCTION calculate_order_balance() RETURNS TRIGGER;

-- 세금계산서 합계 계산
CREATE FUNCTION calculate_tax_invoice_total() RETURNS TRIGGER;

-- 영업에서 프로젝트 자동 생성
CREATE FUNCTION auto_create_project_from_sales(p_sales_no VARCHAR) RETURNS VARCHAR;

로그 관리

-- 테이블 변경 로그 트리거 함수
CREATE FUNCTION carrier_contract_mng_log_trigger_func() RETURNS TRIGGER;
CREATE FUNCTION carrier_mng_log_trigger_func() RETURNS TRIGGER;
-- ... 각 테이블별 로그 트리거 함수

12.2 주요 트리거

-- 화면 생성 시 메뉴 자동 생성
CREATE TRIGGER trg_auto_create_menu_for_screen
AFTER INSERT ON screen_definitions
FOR EACH ROW
EXECUTE FUNCTION auto_create_menu_for_screen();

-- 화면 삭제 시 메뉴 비활성화
CREATE TRIGGER trg_auto_deactivate_menu_for_screen
AFTER UPDATE ON screen_definitions
FOR EACH ROW
EXECUTE FUNCTION auto_deactivate_menu_for_screen();

-- 차량 위치 이력 거리 계산
CREATE TRIGGER trg_calculate_distance_from_prev
BEFORE INSERT ON vehicle_location_history
FOR EACH ROW
EXECUTE FUNCTION calculate_distance_from_prev();

13. 뷰 (Views)

13.1 시스템 뷰

-- 권한 그룹 요약
CREATE VIEW v_authority_group_summary AS
SELECT 
  am.objid,
  am.auth_name,
  am.auth_code,
  am.company_code,
  (SELECT COUNT(*) FROM authority_sub_user WHERE master_objid = am.objid) AS member_count,
  (SELECT COUNT(*) FROM rel_menu_auth WHERE auth_objid = am.objid) AS menu_count
FROM authority_master am;

14. 데이터베이스 보안 및 암호화

14.1 암호화 컬럼

-- external_db_connections
password_encrypted TEXT  -- AES 암호화된 비밀번호

-- external_rest_api_connections
auth_config JSONB        -- 암호화된 인증 정보

14.2 접근 제어

  • PostgreSQL 롤 기반 접근 제어
  • 회사별 데이터 격리 (company_code)
  • 사용자별 권한 관리 (authority_master, rel_menu_auth)

15. 성능 최적화 전략

15.1 인덱스 최적화

  • company_code 인덱스: 모든 테이블에 필수
  • 복합 인덱스: 자주 함께 조회되는 컬럼 조합
  • 부분 인덱스: 특정 조건의 데이터만 인덱싱

15.2 쿼리 최적화

  • 서브쿼리 최소화: JOIN으로 대체
  • EXPLAIN ANALYZE 활용
  • 인덱스 힌트 사용

15.3 캐싱 전략

  • 참조 데이터 캐싱: referenceCacheService.ts
  • Redis 캐싱: 자주 조회되는 메타데이터

15.4 파티셔닝

  • 대용량 이력 테이블 파티셔닝 고려
  • 날짜 기반 파티셔닝 (vehicle_location_history 등)

16. 백업 및 복구

16.1 백업 전략

# 전체 스키마 백업
pg_dump -h host -U user -d database > plm_schema_YYYYMMDD.sql

# 데이터 포함 백업
pg_dump -h host -U user -d database --data-only > data_YYYYMMDD.sql

# 특정 테이블 백업
pg_dump -h host -U user -d database -t table_name > table_backup.sql

16.2 마이그레이션 롤백

  • DDL 작업 전 백업 필수
  • 트랜잭션 기반 마이그레이션
  • 롤백 스크립트 준비

17. 모니터링 및 로깅

17.1 시스템 로그 테이블

login_access_log         -- 로그인 접근 로그
ddl_execution_log        -- DDL 실행 로그
batch_execution_logs     -- 배치 실행 로그
flow_audit_log           -- 플로우 감사 로그
flow_integration_log     -- 플로우 통합 로그
external_call_logs       -- 외부 호출 로그
mail_log                 -- 메일 발송 로그
file_down_log            -- 파일 다운로드 로그

17.2 변경 이력 테이블

패턴: {원본테이블}_log 또는 {원본테이블}_history

user_info_history
dept_info_history
authority_master_history
comm_code_history
carrier_mng_log
supplier_mng_log
equipment_mng_log
...

18. 결론

18.1 핵심 아키텍처 특징

  1. 멀티테넌시: company_code로 완벽한 데이터 격리
  2. 메타데이터 드리븐: 동적 화면/테이블 생성
  3. Low-Code 플랫폼: 코드 없이 화면 구축
  4. 플로우 기반: 시각적 데이터 흐름 설계
  5. 외부 연동: DB/API 통합 지원
  6. 이력 관리: 완벽한 변경 이력 추적

18.2 확장성

  • 수평 확장: 멀티테넌시로 무한한 회사 추가 가능
  • 수직 확장: 동적 테이블/컬럼 추가
  • 기능 확장: 플로우/배치 작업으로 비즈니스 로직 추가

18.3 유지보수성

  • 표준화된 구조: 모든 테이블이 동일한 패턴
  • 자동화: 트리거/함수로 반복 작업 자동화
  • 문서화: 메타데이터 테이블 자체가 문서

부록 A: 백엔드 서비스 매핑

주요 서비스와 테이블 매핑

// backend-node/src/services/

screenManagementService.ts       screen_definitions, screen_layouts
tableManagementService.ts        table_labels, table_type_columns, column_labels
menuService.ts                   menu_info, menu_screen_groups
categoryTreeService.ts           table_column_category_values
flowDefinitionService.ts         flow_definition, flow_step
flowExecutionService.ts          flow_data_status, flow_audit_log
dataflowService.ts               dataflow_diagrams, screen_data_flows
externalDbConnectionService.ts   external_db_connections
externalRestApiConnectionService.ts  external_rest_api_connections
batchService.ts                  batch_jobs, batch_execution_logs
authService.ts                   user_info, auth_tokens
roleService.ts                   authority_master, rel_menu_auth

부록 B: SQL 쿼리 예시

멀티테넌시 표준 쿼리

-- ✅ 단일 테이블 조회
SELECT * FROM sales_order_mng
WHERE company_code = $1
  AND company_code != '*'
  AND order_date >= $2
ORDER BY order_date DESC
LIMIT 100;

-- ✅ JOIN 쿼리
SELECT 
  so.order_no,
  so.order_date,
  c.customer_name,
  p.product_name,
  so.quantity,
  so.unit_price
FROM sales_order_mng so
LEFT JOIN customer_mng c 
  ON so.customer_code = c.customer_code
  AND so.company_code = c.company_code
LEFT JOIN product_mng p 
  ON so.product_code = p.product_code
  AND so.company_code = p.company_code
WHERE so.company_code = $1
  AND so.company_code != '*'
  AND so.order_date BETWEEN $2 AND $3;

-- ✅ 집계 쿼리
SELECT 
  customer_code,
  COUNT(*) as order_count,
  SUM(total_amount) as total_sales
FROM sales_order_mng
WHERE company_code = $1
  AND company_code != '*'
  AND order_date >= DATE_TRUNC('month', CURRENT_DATE)
GROUP BY customer_code
HAVING COUNT(*) >= 5
ORDER BY total_sales DESC;

부록 C: 참고 문서

docs/
├── DDD1542/
│   ├── DB_STRUCTURE_DIAGRAM.md            -- DB 구조 다이어그램
│   ├── DB_INEFFICIENCY_ANALYSIS.md        -- DB 비효율성 분석
│   ├── COMPONENT_URL_SYSTEM_IMPLEMENTATION.md
│   ├── V2_마이그레이션_학습노트_DDD1542.md
│   └── 본서버_개발서버_마이그레이션_가이드.md
├── backend-architecture-analysis.md       -- 백엔드 아키텍처 분석
└── screen-implementation-guide/           -- 화면 구현 가이드

문서 작성자: Cursor AI (DB Specialist Agent)
문서 버전: 1.0
마지막 업데이트: 2026-01-20
스키마 버전: plm_schema_20260120.sql