17 KiB
17 KiB
화면 개발 표준 가이드
목적: 어떤 개발자/AI가 화면을 개발하든 동일한 결과물이 나오도록 하는 표준 가이드 대상: 개발자, AI 에이전트 (Cursor 등) 버전: 1.0.0
1. 개요
이 문서는 WACE 솔루션에서 화면을 개발할 때 반드시 따라야 하는 표준입니다. 비즈니스 로직을 어떻게 설명하든, 최종 결과물은 이 가이드대로 생성되어야 합니다.
핵심 원칙
- V2 컴포넌트만 사용:
v2-접두사가 붙은 컴포넌트만 사용 - UI와 로직 분리: UI는
screen_layouts_v2, 비즈니스 로직은dataflow_diagrams - 멀티테넌시 필수: 모든 쿼리에
company_code필터링
2. 사용 가능한 V2 컴포넌트 목록 (23개)
입력 컴포넌트
| ID | 이름 | 용도 |
|---|---|---|
v2-input |
입력 | 텍스트, 숫자, 비밀번호, 이메일 등 |
v2-select |
선택 | 드롭다운, 콤보박스, 라디오, 체크박스 |
v2-date |
날짜 | 날짜, 시간, 날짜범위 |
표시 컴포넌트
| ID | 이름 | 용도 |
|---|---|---|
v2-text-display |
텍스트 표시 | 라벨, 제목 |
v2-card-display |
카드 디스플레이 | 테이블 데이터를 카드 형태로 표시 |
v2-aggregation-widget |
집계 위젯 | 합계, 평균, 개수 등 |
테이블/데이터 컴포넌트
| ID | 이름 | 용도 |
|---|---|---|
v2-table-list |
테이블 리스트 | 데이터 조회/편집 테이블 |
v2-table-search-widget |
검색 필터 | 테이블 검색/필터 |
v2-pivot-grid |
피벗 그리드 | 다차원 분석 |
레이아웃 컴포넌트
| ID | 이름 | 용도 |
|---|---|---|
v2-split-panel-layout |
분할 패널 | 마스터-디테일 좌우 분할 |
v2-tabs-widget |
탭 위젯 | 탭 전환 |
v2-section-card |
섹션 카드 | 제목+테두리 그룹화 |
v2-section-paper |
섹션 페이퍼 | 배경색 그룹화 |
v2-divider-line |
구분선 | 영역 구분 |
v2-repeat-container |
리피터 컨테이너 | 데이터 반복 렌더링 |
v2-repeater |
리피터 | 반복 컨트롤 |
v2-repeat-screen-modal |
반복 화면 모달 | 모달 반복 |
액션/특수 컴포넌트
| ID | 이름 | 용도 |
|---|---|---|
v2-button-primary |
기본 버튼 | 저장, 삭제 등 액션 |
v2-numbering-rule |
채번규칙 | 자동 코드 생성 |
v2-category-manager |
카테고리 관리자 | 카테고리 관리 |
v2-location-swap-selector |
위치 교환 | 위치 선택/교환 |
v2-rack-structure |
랙 구조 | 창고 랙 시각화 |
v2-media |
미디어 | 이미지/동영상 표시 |
3. 화면 패턴 (5가지)
패턴 A: 기본 마스터 화면
사용 조건: 단일 테이블 CRUD
컴포넌트 구성:
v2-table-search-widget (검색)
v2-table-list (테이블)
v2-button-primary (저장/삭제)
레이아웃:
┌─────────────────────────────────────────────────┐
│ [검색필드들] [조회] [엑셀] │ ← v2-table-search-widget
├─────────────────────────────────────────────────┤
│ 제목 [신규] [삭제] │
│ ─────────────────────────────────────────────── │
│ □ | 코드 | 이름 | 상태 | 등록일 | │ ← v2-table-list
└─────────────────────────────────────────────────┘
패턴 B: 마스터-디테일 화면
사용 조건: 마스터 테이블 선택 → 디테일 테이블 표시
컴포넌트 구성:
v2-split-panel-layout (분할)
├─ 좌측: v2-table-list (마스터)
└─ 우측: v2-table-list (디테일)
레이아웃:
┌──────────────────┬──────────────────────────────┐
│ 마스터 리스트 │ 디테일 리스트 │
│ ─────────────── │ │
│ □ A001 항목1 │ [디테일 테이블] │
│ □ A002 항목2 ← │ │
└──────────────────┴──────────────────────────────┘
v2-split-panel-layout
필수 설정:
{
"leftPanel": {
"tableName": "마스터_테이블명"
},
"rightPanel": {
"tableName": "디테일_테이블명",
"relation": {
"type": "detail",
"foreignKey": "master_id"
}
},
"splitRatio": 30
}
패턴 C: 마스터-디테일 + 탭
사용 조건: 마스터 선택 → 여러 탭으로 상세 정보 표시
컴포넌트 구성:
v2-split-panel-layout (분할)
├─ 좌측: v2-table-list (마스터)
└─ 우측: v2-tabs-widget (탭)
├─ 탭1: v2-table-list
├─ 탭2: v2-table-list
└─ 탭3: 폼 컴포넌트들
패턴 D: 카드 뷰
사용 조건: 이미지+정보 카드 형태 표시
컴포넌트 구성:
v2-table-search-widget (검색)
v2-card-display (카드)
필수 설정:
{
"cardsPerRow": 3,
"columnMapping": {
"title": "name",
"subtitle": "code",
"image": "image_url",
"status": "status"
}
}
패턴 E: 피벗 분석
사용 조건: 다차원 집계/분석
컴포넌트 구성:
v2-pivot-grid (피벗)
필수 설정:
{
"fields": [
{ "field": "region", "area": "row" },
{ "field": "year", "area": "column" },
{ "field": "amount", "area": "data", "summaryType": "sum" }
]
}
4. 데이터베이스 구조
화면 정의 테이블
-- screen_definitions: 화면 기본 정보
INSERT INTO screen_definitions (
screen_id,
screen_name,
screen_code,
description,
table_name,
company_code
) VALUES (...);
-- screen_layouts_v2: UI 레이아웃 (JSON)
INSERT INTO screen_layouts_v2 (
screen_id,
company_code,
layout_data -- JSON: 컴포넌트 배치 정보
) VALUES (...);
-- screen_menu_assignments: 메뉴 연결
INSERT INTO screen_menu_assignments (
screen_id,
menu_objid,
company_code
) VALUES (...);
제어관리 테이블
-- dataflow_diagrams: 비즈니스 로직
INSERT INTO dataflow_diagrams (
diagram_name,
company_code,
control, -- JSON: 조건 설정
plan -- JSON: 실행 계획
) VALUES (...);
5. UI 설정 vs 비즈니스 로직 설정
UI 설정 (화면 디자이너에서 처리)
| 항목 | 저장 위치 |
|---|---|
| 컴포넌트 배치 | screen_layouts_v2.layout_data |
| 테이블명 | layout_data 내 tableName |
| 컬럼 표시/숨김 | layout_data 내 columns |
| 검색 필드 | layout_data 내 searchFields |
| 기본 저장/삭제 | 버튼 config.action.type |
비즈니스 로직 (제어관리에서 처리)
| 항목 | 저장 위치 |
|---|---|
| 조건부 실행 | dataflow_diagrams.control |
| 다중 테이블 저장 | dataflow_diagrams.plan |
| 버튼 전/후 트리거 | dataflow_diagrams.control.triggerType |
| 필드 매핑 | dataflow_diagrams.plan.mappings |
6. 비즈니스 로직 설정 표준 형식
기본 구조
{
"control": {
"actionType": "update",
"triggerType": "after",
"conditions": [
{
"id": "조건ID",
"type": "condition",
"field": "status",
"operator": "=",
"value": "대기",
"dataType": "string"
}
]
},
"plan": {
"mappings": [
{
"id": "매핑ID",
"sourceField": "소스필드",
"targetField": "타겟필드",
"targetTable": "타겟테이블",
"valueType": "field"
}
]
}
}
조건 연산자
| 연산자 | 설명 |
|---|---|
= |
같음 |
!= |
다름 |
> |
큼 |
< |
작음 |
>= |
크거나 같음 |
<= |
작거나 같음 |
LIKE |
포함 |
IN |
목록에 포함 |
IS NULL |
NULL 값 |
액션 타입
| 타입 | 설명 |
|---|---|
insert |
새 데이터 삽입 |
update |
기존 데이터 수정 |
delete |
데이터 삭제 |
트리거 타입
| 타입 | 설명 |
|---|---|
before |
버튼 클릭 전 실행 |
after |
버튼 클릭 후 실행 |
7. 화면 개발 순서
Step 1: 요구사항 분석
1. 어떤 테이블을 사용하는가?
2. 테이블 간 관계는? (FK)
3. 어떤 패턴인가? (A/B/C/D/E)
4. 어떤 버튼이 필요한가?
5. 각 버튼의 비즈니스 로직은?
Step 2: screen_definitions INSERT
INSERT INTO screen_definitions (
screen_name,
screen_code,
description,
table_name,
company_code,
created_at
) VALUES (
'화면명',
'SCREEN_CODE',
'화면 설명',
'메인테이블명',
'회사코드',
NOW()
) RETURNING screen_id;
Step 3: screen_layouts_v2 INSERT
INSERT INTO screen_layouts_v2 (
screen_id,
company_code,
layout_data
) VALUES (
위에서_받은_screen_id,
'회사코드',
'{"components": [...], "layout": {...}}'::jsonb
);
Step 4: dataflow_diagrams INSERT (비즈니스 로직 있는 경우)
INSERT INTO dataflow_diagrams (
diagram_name,
company_code,
control,
plan
) VALUES (
'화면명_제어',
'회사코드',
'{"조건설정"}'::jsonb,
'{"실행계획"}'::jsonb
);
Step 5: screen_menu_assignments INSERT
INSERT INTO screen_menu_assignments (
screen_id,
menu_objid,
company_code
) VALUES (
screen_id,
메뉴ID,
'회사코드'
);
8. 예시: 수주관리 화면
요구사항
화면명: 수주관리
패턴: B (마스터-디테일)
테이블:
- 마스터: order_master
- 디테일: order_detail
버튼:
- [저장]: order_master에 저장
- [확정]:
- 조건: status = '대기'
- 동작: status를 '확정'으로 변경
- 추가: order_history에 이력 저장
screen_definitions
INSERT INTO screen_definitions (
screen_name, screen_code, description, table_name, company_code
) VALUES (
'수주관리', 'ORDER_MNG', '수주를 관리하는 화면', 'order_master', 'COMPANY_A'
);
screen_layouts_v2 (layout_data)
{
"components": [
{
"id": "search-1",
"componentType": "v2-table-search-widget",
"position": {"x": 0, "y": 0},
"size": {"width": 1920, "height": 80}
},
{
"id": "split-1",
"componentType": "v2-split-panel-layout",
"position": {"x": 0, "y": 80},
"size": {"width": 1920, "height": 800},
"componentConfig": {
"leftPanel": {
"tableName": "order_master"
},
"rightPanel": {
"tableName": "order_detail",
"relation": {
"type": "detail",
"foreignKey": "order_id"
}
},
"splitRatio": 30
}
},
{
"id": "btn-save",
"componentType": "v2-button-primary",
"componentConfig": {
"text": "저장",
"action": {"type": "save"}
}
},
{
"id": "btn-confirm",
"componentType": "v2-button-primary",
"componentConfig": {
"text": "확정",
"enableDataflowControl": true,
"dataflowDiagramId": 123
}
}
]
}
dataflow_diagrams (확정 버튼 로직)
{
"control": {
"actionType": "update",
"triggerType": "after",
"conditions": [
{
"id": "cond-1",
"type": "condition",
"field": "status",
"operator": "=",
"value": "대기",
"dataType": "string"
}
]
},
"plan": {
"actions": [
{
"id": "action-1",
"actionType": "update",
"targetTable": "order_master",
"fieldMappings": [
{"targetField": "status", "defaultValue": "확정"}
]
},
{
"id": "action-2",
"actionType": "insert",
"targetTable": "order_history",
"fieldMappings": [
{"sourceField": "order_no", "targetField": "order_no"},
{"sourceField": "customer_name", "targetField": "customer_name"},
{"defaultValue": "#NOW", "targetField": "confirmed_at"}
]
}
]
}
}
9. 지원하지 않는 UI (별도 개발 필요)
| UI 유형 | 상태 | 대안 |
|---|---|---|
| 트리 뷰 | ❌ 미지원 | 테이블로 대체 or v2-tree-view 개발 필요 |
| 그룹화 테이블 | ❌ 미지원 | 일반 테이블로 대체 or v2-grouped-table 개발 필요 |
| 간트 차트 | ❌ 미지원 | 별도 개발 필요 |
| 드래그앤드롭 | ❌ 미지원 | 순서 컬럼으로 대체 |
10. 체크리스트
화면 생성 시
□ screen_definitions INSERT 완료
□ screen_layouts_v2 INSERT 완료
□ screen_menu_assignments INSERT 완료 (메뉴 연결 필요 시)
□ company_code 필터링 적용
□ 사용한 컴포넌트가 모두 v2- 접두사인지 확인
비즈니스 로직 설정 시
□ 기본 액션 (저장/삭제)만 → 화면 디자이너에서 설정
□ 조건부/다중테이블 → dataflow_diagrams INSERT
□ 버튼 config에 dataflowDiagramId 연결
□ control.conditions 설정
□ plan.actions 또는 plan.mappings 설정
11. 비즈니스 로직 요청 양식 (필수)
경고: 양식대로 안 쓰면 처리 안 함. 병신아 제대로 써. 대충 쓰면 대충 만들어지고, 안 쓰면 안 만들어줌.
11.1 양식 템플릿
=== 비즈니스 로직 요청서 ===
【화면 정보】
- 화면명:
- 회사코드:
- 메뉴ID (있으면):
【테이블 정보】
- 메인 테이블:
- 디테일 테이블 (있으면):
- 관계 FK (있으면):
【버튼 목록】
버튼1:
- 버튼명:
- 동작 유형: (저장/삭제/수정/조회/기타)
- 조건 (있으면):
- 대상 테이블:
- 추가 동작 (있으면):
버튼2:
- 버튼명:
- ...
【추가 요구사항】
-
11.2 작성 예시 (올바른 예시)
=== 비즈니스 로직 요청서 ===
【화면 정보】
- 화면명: 수주관리
- 회사코드: ssalmeog
- 메뉴ID: 55566
【테이블 정보】
- 메인 테이블: order_master
- 디테일 테이블: order_detail
- 관계 FK: order_id
【버튼 목록】
버튼1:
- 버튼명: 저장
- 동작 유형: 저장
- 조건: 없음
- 대상 테이블: order_master, order_detail
- 추가 동작: 없음
버튼2:
- 버튼명: 확정
- 동작 유형: 수정
- 조건: status = '대기'
- 대상 테이블: order_master
- 추가 동작:
1. status를 '확정'으로 변경
2. order_history에 이력 INSERT (order_no, customer_name, confirmed_at=현재시간)
버튼3:
- 버튼명: 삭제
- 동작 유형: 삭제
- 조건: status != '확정'
- 대상 테이블: order_master, order_detail (cascade)
- 추가 동작: 없음
【추가 요구사항】
- 확정된 수주는 수정/삭제 불가
- 수주번호 자동채번 (ORDER-YYYYMMDD-0001)
11.3 잘못된 예시 (이렇게 쓰면 안 됨)
❌ "수주관리 화면 만들어줘"
→ 테이블이 뭔데? 버튼은? 로직은?
❌ "저장 버튼 누르면 저장해줘"
→ 어떤 테이블에? 조건은?
❌ "확정하면 재고 처리해줘"
→ 어떤 테이블? 증가? 감소? 얼마나?
❌ "이전 화면이랑 비슷하게"
→ 이전 화면이 뭔데?
11.4 복잡한 로직 추가 양식
조건이 여러 개이거나 복잡한 경우:
【복잡한 버튼 로직】
버튼명: 출고확정
실행 조건:
조건1: status = '출고대기' AND
조건2: qty > 0 AND
조건3: warehouse_id IS NOT NULL
실행 동작 (순서대로):
1. shipment_master.status → '출고완료'
2. inventory에서 qty만큼 감소 (WHERE item_code = 현재행.item_code)
3. shipment_history에 INSERT:
- shipment_no ← 현재행.shipment_no
- shipped_qty ← 현재행.qty
- shipped_at ← 현재시간
- shipped_by ← 현재사용자
실패 시:
- 재고 부족: "재고가 부족합니다" 메시지
- 조건 불충족: "출고대기 상태만 확정 가능합니다" 메시지
12. 참고 경로
| 항목 | 경로/테이블 |
|---|---|
| 제어관리 페이지 | /admin/systemMng/dataflow |
| 화면 정의 테이블 | screen_definitions |
| 레이아웃 테이블 | screen_layouts_v2 |
| 제어관리 테이블 | dataflow_diagrams |
| 메뉴 연결 테이블 | screen_menu_assignments |