Files
vexplor/코드_채번_규칙_컴포넌트_구현_계획서.md
kjs 6901baab8e 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%
- 결과: 파란 테두리와 내부 콘텐츠가 동일한 크기로 정확히 표시
2025-11-04 16:17:19 +09:00

495 lines
13 KiB
Markdown

# 코드 채번 규칙 컴포넌트 구현 계획서
## 문서 정보
- **작성일**: 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. 다음 개선 사항 (선택사항)
- [ ] 규칙 순서 드래그앤드롭으로 변경
- [ ] 규칙 복제 기능
- [ ] 규칙 템플릿 제공 (자주 사용하는 패턴)
- [ ] 코드 검증 로직
- [ ] 테이블 생성 시 자동 채번 컬럼 추가 통합
- [ ] 화면관리에서 입력 폼에 자동 코드 생성 버튼 추가