주요 변경사항: - 격자 설정을 편집 탭에서 항상 표시 (해상도 설정 하단) - 그리드 컬럼 수 동적 조정 가능 (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% - 결과: 파란 테두리와 내부 콘텐츠가 동일한 크기로 정확히 표시
13 KiB
13 KiB
코드 채번 규칙 컴포넌트 구현 계획서
문서 정보
- 작성일: 2025-11-03
- 목적: Shadcn/ui 가이드라인 기반 코드 채번 규칙 컴포넌트 구현
- 우선순위: 중간
- 디자인 원칙: 심플하고 깔끔한 UI, 중첩 박스 금지, 일관된 컬러 시스템
1. 기능 요구사항
1.1 핵심 기능
- 코드 채번 규칙 생성/수정/삭제
- 동적 규칙 파트 추가/삭제 (최대 6개)
- 실시간 코드 미리보기
- 규칙 순서 조정
- 데이터베이스 저장 및 불러오기
1.2 UI 요구사항
- 좌측: 코드 목록 (선택적)
- 우측: 규칙 설정 영역
- 상단: 코드 미리보기 + 규칙명
- 중앙: 규칙 카드 리스트
- 하단: 규칙 추가 + 저장 버튼
2. 디자인 시스템 (Shadcn/ui 기반)
2.1 색상 사용 규칙
// 배경
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 간격 시스템
// 카드 간 간격
gap-6 // 24px (카드 사이)
// 카드 내부 패딩
p-6 // 24px (CardContent)
// 폼 필드 간격
space-y-4 // 16px (입력 필드들)
space-y-3 // 12px (모바일)
// 섹션 간격
space-y-6 // 24px (큰 섹션)
2.3 타이포그래피
// 페이지 제목
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 반응형 설정
// 모바일 우선 + 데스크톱 최적화
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 중첩 박스 금지 원칙
❌ 잘못된 예시:
<Card>
<CardContent>
<div className="border rounded-lg p-4"> {/* 중첩 박스! */}
<div className="border rounded p-2"> {/* 또 중첩! */}
내용
</div>
</div>
</CardContent>
</Card>
✅ 올바른 예시:
<Card>
<CardHeader>
<CardTitle>제목</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{/* 직접 컨텐츠 배치 */}
<div>내용 1</div>
<div>내용 2</div>
</CardContent>
</Card>
3. 데이터 구조
3.1 타입 정의
// 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 데이터베이스 스키마
-- 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: 타입 정의 및 스키마 생성 ✅
- 타입 정의 파일 생성
- 데이터베이스 마이그레이션 실행
- 샘플 데이터 삽입
Phase 2: 백엔드 API 구현
- Controller 생성
- Service 레이어 구현
- API 테스트
Phase 3: 프론트엔드 기본 컴포넌트
- NumberingRuleDesigner (메인)
- NumberingRulePreview (미리보기)
- NumberingRuleCard (단일 규칙 카드)
Phase 4: 상세 설정 패널
- PartTypeSelector (파트 유형 선택)
- AutoConfigPanel (자동 생성 설정)
- ManualConfigPanel (직접 입력 설정)
Phase 5: 화면관리 통합
- ComponentType에 "numbering-rule" 추가
- RealtimePreview 렌더링 추가
- 템플릿 등록
- 속성 패널 구현
Phase 6: 테스트 및 최적화
- 기능 테스트
- 반응형 테스트
- 성능 최적화
- 문서화
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 화면관리에서 사용하기
- 화면관리 페이지로 이동
- 좌측 템플릿 패널에서 관리자 카테고리 선택
- 코드 채번 규칙 템플릿을 캔버스로 드래그
- 규칙 파트 추가 및 설정
- 저장
6.2 API 사용하기
규칙 목록 조회
GET /api/numbering-rules
규칙 생성
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": "-"
}
코드 생성
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. 다음 개선 사항 (선택사항)
- 규칙 순서 드래그앤드롭으로 변경
- 규칙 복제 기능
- 규칙 템플릿 제공 (자주 사용하는 패턴)
- 코드 검증 로직
- 테이블 생성 시 자동 채번 컬럼 추가 통합
- 화면관리에서 입력 폼에 자동 코드 생성 버튼 추가