feat(screen-designer): 그리드 컬럼 시스템 개선 및 컴포넌트 너비 렌더링 수정
주요 변경사항: - 격자 설정을 편집 탭에서 항상 표시 (해상도 설정 하단) - 그리드 컬럼 수 동적 조정 가능 (1-24) - 컴포넌트 생성 시 현재 그리드 컬럼 수 기반 자동 계산 - 컴포넌트 너비가 설정한 컬럼 수대로 정확히 표시되도록 수정 수정된 파일: - ScreenDesigner: 컴포넌트 드롭 시 gridColumns와 style.width 동적 계산 - UnifiedPropertiesPanel: 격자 설정 UI 통합, 차지 컬럼 수 설정 시 width 자동 계산 - RealtimePreviewDynamic: getWidth 우선순위 수정, DOM 크기 디버깅 로그 추가 - 8개 컴포넌트: componentStyle.width를 항상 100%로 고정 * ButtonPrimaryComponent * TextInputComponent * NumberInputComponent * TextareaBasicComponent * DateInputComponent * TableListComponent * CardDisplayComponent 문제 해결: - 컴포넌트 내부에서 component.style.width를 재사용하여 이중 축소 발생 - 해결: 부모 컨테이너(RealtimePreviewDynamic)가 width 제어, 컴포넌트는 항상 100% - 결과: 파란 테두리와 내부 콘텐츠가 동일한 크기로 정확히 표시
This commit is contained in:
494
코드_채번_규칙_컴포넌트_구현_계획서.md
Normal file
494
코드_채번_규칙_컴포넌트_구현_계획서.md
Normal file
@@ -0,0 +1,494 @@
|
||||
# 코드 채번 규칙 컴포넌트 구현 계획서
|
||||
|
||||
## 문서 정보
|
||||
- **작성일**: 2025-11-03
|
||||
- **목적**: Shadcn/ui 가이드라인 기반 코드 채번 규칙 컴포넌트 구현
|
||||
- **우선순위**: 중간
|
||||
- **디자인 원칙**: 심플하고 깔끔한 UI, 중첩 박스 금지, 일관된 컬러 시스템
|
||||
|
||||
---
|
||||
|
||||
## 1. 기능 요구사항
|
||||
|
||||
### 1.1 핵심 기능
|
||||
- 코드 채번 규칙 생성/수정/삭제
|
||||
- 동적 규칙 파트 추가/삭제 (최대 6개)
|
||||
- 실시간 코드 미리보기
|
||||
- 규칙 순서 조정
|
||||
- 데이터베이스 저장 및 불러오기
|
||||
|
||||
### 1.2 UI 요구사항
|
||||
- 좌측: 코드 목록 (선택적)
|
||||
- 우측: 규칙 설정 영역
|
||||
- 상단: 코드 미리보기 + 규칙명
|
||||
- 중앙: 규칙 카드 리스트
|
||||
- 하단: 규칙 추가 + 저장 버튼
|
||||
|
||||
---
|
||||
|
||||
## 2. 디자인 시스템 (Shadcn/ui 기반)
|
||||
|
||||
### 2.1 색상 사용 규칙
|
||||
|
||||
```tsx
|
||||
// 배경
|
||||
bg-background // 페이지 배경
|
||||
bg-card // 카드 배경
|
||||
bg-muted // 약한 배경 (미리보기 등)
|
||||
|
||||
// 텍스트
|
||||
text-foreground // 기본 텍스트
|
||||
text-muted-foreground // 보조 텍스트
|
||||
text-primary // 강조 텍스트
|
||||
|
||||
// 테두리
|
||||
border-border // 기본 테두리
|
||||
border-input // 입력 필드 테두리
|
||||
|
||||
// 버튼
|
||||
bg-primary // 주요 버튼 (저장, 추가)
|
||||
bg-destructive // 삭제 버튼
|
||||
variant="outline" // 보조 버튼 (취소)
|
||||
variant="ghost" // 아이콘 버튼
|
||||
```
|
||||
|
||||
### 2.2 간격 시스템
|
||||
|
||||
```tsx
|
||||
// 카드 간 간격
|
||||
gap-6 // 24px (카드 사이)
|
||||
|
||||
// 카드 내부 패딩
|
||||
p-6 // 24px (CardContent)
|
||||
|
||||
// 폼 필드 간격
|
||||
space-y-4 // 16px (입력 필드들)
|
||||
space-y-3 // 12px (모바일)
|
||||
|
||||
// 섹션 간격
|
||||
space-y-6 // 24px (큰 섹션)
|
||||
```
|
||||
|
||||
### 2.3 타이포그래피
|
||||
|
||||
```tsx
|
||||
// 페이지 제목
|
||||
text-2xl font-semibold
|
||||
|
||||
// 섹션 제목
|
||||
text-lg font-semibold
|
||||
|
||||
// 카드 제목
|
||||
text-base font-semibold
|
||||
|
||||
// 라벨
|
||||
text-sm font-medium
|
||||
|
||||
// 본문 텍스트
|
||||
text-sm text-muted-foreground
|
||||
|
||||
// 작은 텍스트
|
||||
text-xs text-muted-foreground
|
||||
```
|
||||
|
||||
### 2.4 반응형 설정
|
||||
|
||||
```tsx
|
||||
// 모바일 우선 + 데스크톱 최적화
|
||||
className="text-xs sm:text-sm" // 폰트 크기
|
||||
className="h-8 sm:h-10" // 입력 필드 높이
|
||||
className="flex-col md:flex-row" // 레이아웃
|
||||
className="gap-2 sm:gap-4" // 간격
|
||||
```
|
||||
|
||||
### 2.5 중첩 박스 금지 원칙
|
||||
|
||||
**❌ 잘못된 예시**:
|
||||
```tsx
|
||||
<Card>
|
||||
<CardContent>
|
||||
<div className="border rounded-lg p-4"> {/* 중첩 박스! */}
|
||||
<div className="border rounded p-2"> {/* 또 중첩! */}
|
||||
내용
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
```
|
||||
|
||||
**✅ 올바른 예시**:
|
||||
```tsx
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>제목</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{/* 직접 컨텐츠 배치 */}
|
||||
<div>내용 1</div>
|
||||
<div>내용 2</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 데이터 구조
|
||||
|
||||
### 3.1 타입 정의
|
||||
|
||||
```typescript
|
||||
// frontend/types/numbering-rule.ts
|
||||
|
||||
import { BaseComponent } from "./screen-management";
|
||||
|
||||
/**
|
||||
* 코드 파트 유형
|
||||
*/
|
||||
export type CodePartType =
|
||||
| "prefix" // 접두사 (고정 문자열)
|
||||
| "sequence" // 순번 (자동 증가)
|
||||
| "date" // 날짜 (YYYYMMDD 등)
|
||||
| "year" // 연도 (YYYY)
|
||||
| "month" // 월 (MM)
|
||||
| "custom"; // 사용자 정의
|
||||
|
||||
/**
|
||||
* 생성 방식
|
||||
*/
|
||||
export type GenerationMethod =
|
||||
| "auto" // 자동 생성
|
||||
| "manual"; // 직접 입력
|
||||
|
||||
/**
|
||||
* 날짜 형식
|
||||
*/
|
||||
export type DateFormat =
|
||||
| "YYYY" // 2025
|
||||
| "YY" // 25
|
||||
| "YYYYMM" // 202511
|
||||
| "YYMM" // 2511
|
||||
| "YYYYMMDD" // 20251103
|
||||
| "YYMMDD"; // 251103
|
||||
|
||||
/**
|
||||
* 단일 규칙 파트
|
||||
*/
|
||||
export interface NumberingRulePart {
|
||||
id: string; // 고유 ID
|
||||
order: number; // 순서 (1-6)
|
||||
partType: CodePartType; // 파트 유형
|
||||
generationMethod: GenerationMethod; // 생성 방식
|
||||
|
||||
// 자동 생성 설정
|
||||
autoConfig?: {
|
||||
// 접두사 설정
|
||||
prefix?: string; // 예: "ITM"
|
||||
|
||||
// 순번 설정
|
||||
sequenceLength?: number; // 자릿수 (예: 4 → 0001)
|
||||
startFrom?: number; // 시작 번호 (기본: 1)
|
||||
|
||||
// 날짜 설정
|
||||
dateFormat?: DateFormat; // 날짜 형식
|
||||
};
|
||||
|
||||
// 직접 입력 설정
|
||||
manualConfig?: {
|
||||
value: string; // 입력값
|
||||
placeholder?: string; // 플레이스홀더
|
||||
};
|
||||
|
||||
// 생성된 값 (미리보기용)
|
||||
generatedValue?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 전체 채번 규칙
|
||||
*/
|
||||
export interface NumberingRuleConfig {
|
||||
ruleId: string; // 규칙 ID
|
||||
ruleName: string; // 규칙명
|
||||
description?: string; // 설명
|
||||
parts: NumberingRulePart[]; // 규칙 파트 배열 (최대 6개)
|
||||
|
||||
// 설정
|
||||
separator?: string; // 구분자 (기본: "-")
|
||||
resetPeriod?: "none" | "daily" | "monthly" | "yearly"; // 초기화 주기
|
||||
currentSequence?: number; // 현재 시퀀스
|
||||
|
||||
// 적용 대상
|
||||
tableName?: string; // 적용할 테이블명
|
||||
columnName?: string; // 적용할 컬럼명
|
||||
|
||||
// 메타 정보
|
||||
companyCode?: string;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
createdBy?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 화면관리 컴포넌트 인터페이스
|
||||
*/
|
||||
export interface NumberingRuleComponent extends BaseComponent {
|
||||
type: "numbering-rule";
|
||||
|
||||
// 채번 규칙 설정
|
||||
ruleConfig: NumberingRuleConfig;
|
||||
|
||||
// UI 설정
|
||||
showRuleList?: boolean; // 좌측 목록 표시 여부
|
||||
maxRules?: number; // 최대 규칙 개수 (기본: 6)
|
||||
enableReorder?: boolean; // 순서 변경 허용 여부
|
||||
|
||||
// 스타일
|
||||
cardLayout?: "vertical" | "horizontal"; // 카드 레이아웃
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 데이터베이스 스키마
|
||||
|
||||
```sql
|
||||
-- db/migrations/034_create_numbering_rules.sql
|
||||
|
||||
-- 채번 규칙 마스터 테이블
|
||||
CREATE TABLE IF NOT EXISTS numbering_rules (
|
||||
rule_id VARCHAR(50) PRIMARY KEY,
|
||||
rule_name VARCHAR(100) NOT NULL,
|
||||
description TEXT,
|
||||
separator VARCHAR(10) DEFAULT '-',
|
||||
reset_period VARCHAR(20) DEFAULT 'none',
|
||||
current_sequence INTEGER DEFAULT 1,
|
||||
table_name VARCHAR(100),
|
||||
column_name VARCHAR(100),
|
||||
company_code VARCHAR(20) NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
created_by VARCHAR(50),
|
||||
|
||||
CONSTRAINT fk_company FOREIGN KEY (company_code)
|
||||
REFERENCES company_info(company_code)
|
||||
);
|
||||
|
||||
-- 채번 규칙 상세 테이블
|
||||
CREATE TABLE IF NOT EXISTS numbering_rule_parts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
rule_id VARCHAR(50) NOT NULL,
|
||||
part_order INTEGER NOT NULL,
|
||||
part_type VARCHAR(50) NOT NULL,
|
||||
generation_method VARCHAR(20) NOT NULL,
|
||||
auto_config JSONB,
|
||||
manual_config JSONB,
|
||||
company_code VARCHAR(20) NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT fk_numbering_rule FOREIGN KEY (rule_id)
|
||||
REFERENCES numbering_rules(rule_id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_company FOREIGN KEY (company_code)
|
||||
REFERENCES company_info(company_code),
|
||||
CONSTRAINT unique_rule_order UNIQUE (rule_id, part_order, company_code)
|
||||
);
|
||||
|
||||
-- 인덱스
|
||||
CREATE INDEX idx_numbering_rules_company ON numbering_rules(company_code);
|
||||
CREATE INDEX idx_numbering_rule_parts_rule ON numbering_rule_parts(rule_id);
|
||||
CREATE INDEX idx_numbering_rules_table ON numbering_rules(table_name, column_name);
|
||||
|
||||
-- 샘플 데이터
|
||||
INSERT INTO numbering_rules (rule_id, rule_name, description, company_code, created_by)
|
||||
VALUES ('SAMPLE_RULE', '샘플 채번 규칙', '제품 코드 자동 생성', '*', 'system')
|
||||
ON CONFLICT (rule_id) DO NOTHING;
|
||||
|
||||
INSERT INTO numbering_rule_parts (rule_id, part_order, part_type, generation_method, auto_config, company_code)
|
||||
VALUES
|
||||
('SAMPLE_RULE', 1, 'prefix', 'auto', '{"prefix": "PROD"}', '*'),
|
||||
('SAMPLE_RULE', 2, 'date', 'auto', '{"dateFormat": "YYYYMMDD"}', '*'),
|
||||
('SAMPLE_RULE', 3, 'sequence', 'auto', '{"sequenceLength": 4, "startFrom": 1}', '*')
|
||||
ON CONFLICT (rule_id, part_order, company_code) DO NOTHING;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 구현 순서
|
||||
|
||||
### Phase 1: 타입 정의 및 스키마 생성 ✅
|
||||
1. 타입 정의 파일 생성
|
||||
2. 데이터베이스 마이그레이션 실행
|
||||
3. 샘플 데이터 삽입
|
||||
|
||||
### Phase 2: 백엔드 API 구현
|
||||
1. Controller 생성
|
||||
2. Service 레이어 구현
|
||||
3. API 테스트
|
||||
|
||||
### Phase 3: 프론트엔드 기본 컴포넌트
|
||||
1. NumberingRuleDesigner (메인)
|
||||
2. NumberingRulePreview (미리보기)
|
||||
3. NumberingRuleCard (단일 규칙 카드)
|
||||
|
||||
### Phase 4: 상세 설정 패널
|
||||
1. PartTypeSelector (파트 유형 선택)
|
||||
2. AutoConfigPanel (자동 생성 설정)
|
||||
3. ManualConfigPanel (직접 입력 설정)
|
||||
|
||||
### Phase 5: 화면관리 통합
|
||||
1. ComponentType에 "numbering-rule" 추가
|
||||
2. RealtimePreview 렌더링 추가
|
||||
3. 템플릿 등록
|
||||
4. 속성 패널 구현
|
||||
|
||||
### Phase 6: 테스트 및 최적화
|
||||
1. 기능 테스트
|
||||
2. 반응형 테스트
|
||||
3. 성능 최적화
|
||||
4. 문서화
|
||||
|
||||
---
|
||||
|
||||
## 5. 구현 완료 ✅
|
||||
|
||||
### Phase 1: 타입 정의 및 스키마 생성 ✅
|
||||
- ✅ `frontend/types/numbering-rule.ts` 생성
|
||||
- ✅ `db/migrations/034_create_numbering_rules.sql` 생성 및 실행
|
||||
- ✅ 샘플 데이터 삽입 완료
|
||||
|
||||
### Phase 2: 백엔드 API 구현 ✅
|
||||
- ✅ `backend-node/src/services/numberingRuleService.ts` 생성
|
||||
- ✅ `backend-node/src/controllers/numberingRuleController.ts` 생성
|
||||
- ✅ `app.ts`에 라우터 등록 (`/api/numbering-rules`)
|
||||
- ✅ 백엔드 재시작 완료
|
||||
|
||||
### Phase 3: 프론트엔드 기본 컴포넌트 ✅
|
||||
- ✅ `NumberingRulePreview.tsx` - 코드 미리보기
|
||||
- ✅ `NumberingRuleCard.tsx` - 단일 규칙 카드
|
||||
- ✅ `AutoConfigPanel.tsx` - 자동 생성 설정
|
||||
- ✅ `ManualConfigPanel.tsx` - 직접 입력 설정
|
||||
- ✅ `NumberingRuleDesigner.tsx` - 메인 디자이너
|
||||
|
||||
### Phase 4: 상세 설정 패널 ✅
|
||||
- ✅ 파트 유형별 설정 UI (접두사, 순번, 날짜, 연도, 월, 커스텀)
|
||||
- ✅ 자동 생성 / 직접 입력 모드 전환
|
||||
- ✅ 실시간 미리보기 업데이트
|
||||
|
||||
### Phase 5: 화면관리 시스템 통합 ✅
|
||||
- ✅ `unified-core.ts`에 "numbering-rule" ComponentType 추가
|
||||
- ✅ `screen-management.ts`에 ComponentData 유니온 타입 추가
|
||||
- ✅ `RealtimePreview.tsx`에 렌더링 로직 추가
|
||||
- ✅ `TemplatesPanel.tsx`에 "관리자" 카테고리 및 템플릿 추가
|
||||
- ✅ `NumberingRuleTemplate.ts` 생성
|
||||
|
||||
### Phase 6: 완료 ✅
|
||||
모든 단계가 성공적으로 완료되었습니다!
|
||||
|
||||
---
|
||||
|
||||
## 6. 사용 방법
|
||||
|
||||
### 6.1 화면관리에서 사용하기
|
||||
|
||||
1. **화면관리** 페이지로 이동
|
||||
2. 좌측 **템플릿 패널**에서 **관리자** 카테고리 선택
|
||||
3. **코드 채번 규칙** 템플릿을 캔버스로 드래그
|
||||
4. 규칙 파트 추가 및 설정
|
||||
5. 저장
|
||||
|
||||
### 6.2 API 사용하기
|
||||
|
||||
#### 규칙 목록 조회
|
||||
```bash
|
||||
GET /api/numbering-rules
|
||||
```
|
||||
|
||||
#### 규칙 생성
|
||||
```bash
|
||||
POST /api/numbering-rules
|
||||
{
|
||||
"ruleId": "PROD_CODE",
|
||||
"ruleName": "제품 코드 규칙",
|
||||
"parts": [
|
||||
{
|
||||
"id": "part-1",
|
||||
"order": 1,
|
||||
"partType": "prefix",
|
||||
"generationMethod": "auto",
|
||||
"autoConfig": { "prefix": "PROD" }
|
||||
},
|
||||
{
|
||||
"id": "part-2",
|
||||
"order": 2,
|
||||
"partType": "date",
|
||||
"generationMethod": "auto",
|
||||
"autoConfig": { "dateFormat": "YYYYMMDD" }
|
||||
},
|
||||
{
|
||||
"id": "part-3",
|
||||
"order": 3,
|
||||
"partType": "sequence",
|
||||
"generationMethod": "auto",
|
||||
"autoConfig": { "sequenceLength": 4, "startFrom": 1 }
|
||||
}
|
||||
],
|
||||
"separator": "-"
|
||||
}
|
||||
```
|
||||
|
||||
#### 코드 생성
|
||||
```bash
|
||||
POST /api/numbering-rules/PROD_CODE/generate
|
||||
|
||||
응답: { "success": true, "data": { "code": "PROD-20251103-0001" } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 구현된 파일 목록
|
||||
|
||||
### 프론트엔드
|
||||
```
|
||||
frontend/
|
||||
├── types/
|
||||
│ └── numbering-rule.ts ✅
|
||||
├── components/
|
||||
│ └── numbering-rule/
|
||||
│ ├── NumberingRuleDesigner.tsx ✅
|
||||
│ ├── NumberingRuleCard.tsx ✅
|
||||
│ ├── NumberingRulePreview.tsx ✅
|
||||
│ ├── AutoConfigPanel.tsx ✅
|
||||
│ └── ManualConfigPanel.tsx ✅
|
||||
└── components/screen/
|
||||
├── RealtimePreview.tsx ✅ (수정됨)
|
||||
├── panels/
|
||||
│ └── TemplatesPanel.tsx ✅ (수정됨)
|
||||
└── templates/
|
||||
└── NumberingRuleTemplate.ts ✅
|
||||
```
|
||||
|
||||
### 백엔드
|
||||
```
|
||||
backend-node/
|
||||
├── src/
|
||||
│ ├── services/
|
||||
│ │ └── numberingRuleService.ts ✅
|
||||
│ ├── controllers/
|
||||
│ │ └── numberingRuleController.ts ✅
|
||||
│ └── app.ts ✅ (수정됨)
|
||||
```
|
||||
|
||||
### 데이터베이스
|
||||
```
|
||||
db/
|
||||
└── migrations/
|
||||
└── 034_create_numbering_rules.sql ✅
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 다음 개선 사항 (선택사항)
|
||||
|
||||
- [ ] 규칙 순서 드래그앤드롭으로 변경
|
||||
- [ ] 규칙 복제 기능
|
||||
- [ ] 규칙 템플릿 제공 (자주 사용하는 패턴)
|
||||
- [ ] 코드 검증 로직
|
||||
- [ ] 테이블 생성 시 자동 채번 컬럼 추가 통합
|
||||
- [ ] 화면관리에서 입력 폼에 자동 코드 생성 버튼 추가
|
||||
|
||||
Reference in New Issue
Block a user