다음 구현 필요 컴포넌트 개발 계획
작성일: 2026-01-30
상태: 계획 수립 완료
우선순위: v2-table-grouped (1순위) → v2-timeline-scheduler (2순위)
개요
생산계획관리 화면의 정식 버전 구현을 위해 필요한 2개의 신규 컴포넌트 개발 계획입니다.
| 컴포넌트 |
용도 |
난이도 |
예상 작업량 |
v2-table-grouped |
그룹화 테이블 (접기/펼치기) |
중 |
2-3일 |
v2-timeline-scheduler |
타임라인/간트차트 스케줄러 |
상 |
5-7일 |
1. v2-table-grouped (그룹화 테이블)
1.1 컴포넌트 개요
| 항목 |
내용 |
| 컴포넌트 ID |
v2-table-grouped |
| 카테고리 |
DISPLAY |
| 용도 |
데이터를 특정 컬럼 기준으로 그룹화하여 접기/펼치기 기능 제공 |
| 기반 컴포넌트 |
v2-table-list 확장 |
| 참고 UI |
Excel 그룹화, VS Code 파일 그룹화 |
1.2 핵심 기능
| 기능 |
설명 |
우선순위 |
| 그룹화 |
지정된 컬럼 기준으로 데이터 그룹핑 |
필수 |
| 접기/펼치기 |
그룹 행 클릭 시 하위 항목 토글 |
필수 |
| 그룹 요약 |
그룹별 합계/개수 표시 |
필수 |
| 다중 그룹 |
여러 컬럼 기준 중첩 그룹화 |
선택 |
| 그룹 선택 |
그룹 체크박스로 하위 전체 선택 |
필수 |
| 전체 펼치기/접기 |
모든 그룹 일괄 토글 |
필수 |
1.3 UI 목업
┌─────────────────────────────────────────────────────────────────┐
│ [전체 펼치기] [전체 접기] [3개 그룹] │
├─────────────────────────────────────────────────────────────────┤
│ ▼ □ 품목A (P001) 수량: 150 3건 │
│ ├─ □ 2026-01-15 생산계획001 50개 설비A │
│ ├─ □ 2026-01-16 생산계획002 50개 설비B │
│ └─ □ 2026-01-17 생산계획003 50개 설비A │
├─────────────────────────────────────────────────────────────────┤
│ ► □ 품목B (P002) 수량: 200 2건 │ ← 접힌 상태
├─────────────────────────────────────────────────────────────────┤
│ ▼ □ 품목C (P003) 수량: 100 1건 │
│ └─ □ 2026-01-18 생산계획004 100개 설비C │
└─────────────────────────────────────────────────────────────────┘
1.4 타입 정의 (types.ts)
import { ColumnConfig } from "../v2-table-list/types";
/**
* 그룹화 설정
*/
export interface GroupConfig {
/** 그룹화 기준 컬럼 */
groupByColumn: string;
/** 그룹 표시 형식 (예: "{item_name} ({item_code})") */
groupLabelFormat?: string;
/** 그룹 요약 설정 */
summary?: {
/** 합계 컬럼 */
sumColumns?: string[];
/** 개수 표시 여부 */
showCount?: boolean;
};
/** 초기 펼침 상태 */
defaultExpanded?: boolean;
/** 중첩 그룹 (다중 그룹화) */
nestedGroup?: GroupConfig;
}
/**
* 그룹화 테이블 설정
*/
export interface TableGroupedConfig {
/** 테이블명 */
selectedTable?: string;
/** 커스텀 테이블 사용 */
useCustomTable?: boolean;
customTableName?: string;
/** 그룹화 설정 */
groupConfig: GroupConfig;
/** 컬럼 설정 (v2-table-list와 동일) */
columns?: ColumnConfig[];
/** 체크박스 표시 */
showCheckbox?: boolean;
/** 체크박스 모드 */
checkboxMode?: "single" | "multi";
/** 페이지네이션 (그룹 단위) */
pagination?: {
enabled: boolean;
pageSize: number;
};
/** 정렬 설정 */
defaultSort?: {
column: string;
direction: "asc" | "desc";
};
}
/**
* 그룹 상태
*/
export interface GroupState {
/** 그룹 키 (groupByColumn 값) */
groupKey: string;
/** 펼침 여부 */
expanded: boolean;
/** 그룹 내 데이터 */
items: any[];
/** 그룹 요약 데이터 */
summary?: Record<string, number>;
}
1.5 파일 구조
frontend/lib/registry/components/v2-table-grouped/
├── index.ts # Definition (V2TableGroupedDefinition)
├── types.ts # 타입 정의
├── config.ts # 기본 설정값
├── TableGroupedComponent.tsx # 메인 컴포넌트
├── TableGroupedConfigPanel.tsx # 설정 패널
├── TableGroupedRenderer.tsx # 레지스트리 등록
├── components/
│ ├── GroupHeader.tsx # 그룹 헤더 (펼치기/접기)
│ ├── GroupSummary.tsx # 그룹 요약
│ └── GroupCheckbox.tsx # 그룹 체크박스
├── hooks/
│ └── useGroupedData.ts # 그룹화 로직 훅
└── README.md
1.6 구현 단계
| 단계 |
작업 내용 |
예상 시간 |
| 1 |
타입 정의 및 기본 구조 생성 |
2시간 |
| 2 |
useGroupedData 훅 구현 (데이터 그룹화 로직) |
4시간 |
| 3 |
GroupHeader 컴포넌트 (펼치기/접기 UI) |
2시간 |
| 4 |
TableGroupedComponent 메인 구현 |
6시간 |
| 5 |
그룹 체크박스 연동 |
2시간 |
| 6 |
그룹 요약 (합계/개수) |
2시간 |
| 7 |
TableGroupedConfigPanel 설정 패널 |
4시간 |
| 8 |
테스트 및 문서화 |
2시간 |
총 예상: 24시간 (약 3일)
1.7 v2-table-list와의 차이점
| 항목 |
v2-table-list |
v2-table-grouped |
| 데이터 구조 |
플랫 리스트 |
계층 구조 (그룹 > 아이템) |
| 렌더링 |
행 단위 |
그룹 헤더 + 상세 행 |
| 선택 |
개별 행 |
그룹 단위 / 개별 단위 |
| 요약 |
전체 합계 (선택) |
그룹별 요약 |
| 페이지네이션 |
행 단위 |
그룹 단위 |
2. v2-timeline-scheduler (타임라인 스케줄러)
2.1 컴포넌트 개요
| 항목 |
내용 |
| 컴포넌트 ID |
v2-timeline-scheduler |
| 카테고리 |
DISPLAY |
| 용도 |
간트차트 형태의 일정/계획 시각화 및 편집 |
| 참고 UI |
MS Project, Jira Timeline, dhtmlxGantt |
| 외부 라이브러리 |
고려 중: @tanstack/react-virtual (가상 스크롤) |
2.2 핵심 기능
| 기능 |
설명 |
우선순위 |
| 타임라인 그리드 |
날짜 기준 그리드 표시 (일/주/월) |
필수 |
| 스케줄 바 |
시작~종료 기간 바 렌더링 |
필수 |
| 리소스 행 |
설비/작업자별 행 구분 |
필수 |
| 드래그 이동 |
스케줄 바 드래그로 날짜 변경 |
필수 |
| 리사이즈 |
바 양쪽 핸들로 기간 조정 |
필수 |
| 줌 레벨 |
일/주/월 단위 전환 |
필수 |
| 충돌 표시 |
같은 리소스 시간 겹침 경고 |
선택 |
| 진행률 표시 |
바 내부 진행률 표시 |
선택 |
| 마일스톤 |
단일 일정 마커 |
선택 |
2.3 UI 목업
┌──────────────────────────────────────────────────────────────────────────────┐
│ [◀ 이전] [오늘] [다음 ▶] 2026년 1월 [일] [주] [월] [+ 추가] │
├────────────┬─────────────────────────────────────────────────────────────────┤
│ │ 15(수) │ 16(목) │ 17(금) │ 18(토) │ 19(일) │ 20(월) │ 21(화) │
├────────────┼─────────────────────────────────────────────────────────────────┤
│ 설비A │ ████████████████ │
│ │ [생산계획001] │ │
├────────────┼─────────────────────────────────────────────────────────────────┤
│ 설비B │ █████████████████████████ │
│ │ [생산계획002 ] │
├────────────┼─────────────────────────────────────────────────────────────────┤
│ 설비C │ ████████████████ │
│ │ [생산계획003] │
└────────────┴─────────────────────────────────────────────────────────────────┘
범례: ██ 진행중 ██ 완료 ██ 지연 ◆ 마일스톤
2.4 타입 정의 (types.ts)
/**
* 줌 레벨
*/
export type ZoomLevel = "day" | "week" | "month";
/**
* 스케줄 상태
*/
export type ScheduleStatus = "planned" | "in_progress" | "completed" | "delayed" | "cancelled";
/**
* 스케줄 항목
*/
export interface ScheduleItem {
/** 고유 ID */
id: string;
/** 리소스 ID (설비/작업자) */
resourceId: string;
/** 표시 제목 */
title: string;
/** 시작 일시 */
startDate: string; // ISO 8601 format
/** 종료 일시 */
endDate: string;
/** 상태 */
status: ScheduleStatus;
/** 진행률 (0-100) */
progress?: number;
/** 색상 (CSS color) */
color?: string;
/** 추가 데이터 */
data?: Record<string, any>;
}
/**
* 리소스 (행)
*/
export interface Resource {
/** 리소스 ID */
id: string;
/** 표시명 */
name: string;
/** 그룹 (선택) */
group?: string;
/** 아이콘 (선택) */
icon?: string;
/** 용량 (선택, 충돌 계산용) */
capacity?: number;
}
/**
* 타임라인 설정
*/
export interface TimelineSchedulerConfig {
/** 테이블명 (스케줄 데이터) */
selectedTable?: string;
/** 리소스 테이블명 */
resourceTable?: string;
/** 필드 매핑 */
fieldMapping: {
id: string;
resourceId: string;
title: string;
startDate: string;
endDate: string;
status?: string;
progress?: string;
color?: string;
};
/** 리소스 필드 매핑 */
resourceFieldMapping?: {
id: string;
name: string;
group?: string;
};
/** 초기 줌 레벨 */
defaultZoomLevel?: ZoomLevel;
/** 초기 표시 날짜 */
initialDate?: string;
/** 편집 가능 여부 */
editable?: boolean;
/** 드래그 이동 허용 */
allowDrag?: boolean;
/** 리사이즈 허용 */
allowResize?: boolean;
/** 충돌 체크 */
checkConflicts?: boolean;
/** 상태별 색상 */
statusColors?: Record<ScheduleStatus, string>;
/** 리소스 컬럼 너비 */
resourceColumnWidth?: number;
/** 행 높이 */
rowHeight?: number;
/** 셀 너비 (줌 레벨별) */
cellWidth?: {
day: number;
week: number;
month: number;
};
/** 툴바 표시 */
showToolbar?: boolean;
/** 범례 표시 */
showLegend?: boolean;
}
/**
* 이벤트 핸들러
*/
export interface TimelineEvents {
/** 스케줄 클릭 */
onScheduleClick?: (schedule: ScheduleItem) => void;
/** 스케줄 더블클릭 */
onScheduleDoubleClick?: (schedule: ScheduleItem) => void;
/** 드래그 완료 */
onScheduleDrag?: (schedule: ScheduleItem, newStart: Date, newEnd: Date) => void;
/** 리사이즈 완료 */
onScheduleResize?: (schedule: ScheduleItem, newStart: Date, newEnd: Date) => void;
/** 빈 영역 클릭 (새 스케줄 추가용) */
onEmptyClick?: (resourceId: string, date: Date) => void;
}
2.5 파일 구조
frontend/lib/registry/components/v2-timeline-scheduler/
├── index.ts # Definition (V2TimelineSchedulerDefinition)
├── types.ts # 타입 정의
├── config.ts # 기본 설정값
├── TimelineSchedulerComponent.tsx # 메인 컴포넌트
├── TimelineSchedulerConfigPanel.tsx # 설정 패널
├── TimelineSchedulerRenderer.tsx # 레지스트리 등록
├── components/
│ ├── TimelineHeader.tsx # 날짜 헤더
│ ├── TimelineGrid.tsx # 그리드 배경
│ ├── ResourceColumn.tsx # 리소스 컬럼 (좌측)
│ ├── ScheduleBar.tsx # 스케줄 바 (드래그/리사이즈)
│ ├── TimelineToolbar.tsx # 툴바 (줌, 네비게이션)
│ ├── TimelineLegend.tsx # 범례
│ └── ConflictIndicator.tsx # 충돌 표시
├── hooks/
│ ├── useTimelineState.ts # 타임라인 상태 관리
│ ├── useScheduleDrag.ts # 드래그 로직
│ ├── useScheduleResize.ts # 리사이즈 로직
│ └── useDateCalculation.ts # 날짜/위치 계산
├── utils/
│ ├── dateUtils.ts # 날짜 유틸리티
│ └── conflictDetection.ts # 충돌 감지
└── README.md
2.6 구현 단계
| 단계 |
작업 내용 |
예상 시간 |
| 1 |
타입 정의 및 기본 구조 생성 |
3시간 |
| 2 |
TimelineHeader (날짜 헤더, 줌 레벨) |
4시간 |
| 3 |
TimelineGrid (그리드 배경) |
3시간 |
| 4 |
ResourceColumn (리소스 목록) |
2시간 |
| 5 |
ScheduleBar 기본 렌더링 |
4시간 |
| 6 |
드래그 이동 구현 |
6시간 |
| 7 |
리사이즈 구현 |
4시간 |
| 8 |
줌 레벨 전환 (일/주/월) |
3시간 |
| 9 |
날짜 네비게이션 |
2시간 |
| 10 |
충돌 감지 및 표시 |
4시간 |
| 11 |
가상 스크롤 (대용량 데이터) |
4시간 |
| 12 |
TimelineSchedulerConfigPanel |
4시간 |
| 13 |
API 연동 (저장/로드) |
4시간 |
| 14 |
테스트 및 문서화 |
3시간 |
총 예상: 50시간 (약 6-7일)
2.7 핵심 알고리즘
날짜 → 픽셀 위치 변환
function dateToPosition(date: Date, viewStart: Date, cellWidth: number, zoomLevel: ZoomLevel): number {
const diffMs = date.getTime() - viewStart.getTime();
switch (zoomLevel) {
case "day":
const diffDays = diffMs / (1000 * 60 * 60 * 24);
return diffDays * cellWidth;
case "week":
const diffWeeks = diffMs / (1000 * 60 * 60 * 24 * 7);
return diffWeeks * cellWidth;
case "month":
// 월 단위는 일수가 다르므로 별도 계산
return calculateMonthPosition(date, viewStart, cellWidth);
}
}
충돌 감지
function detectConflicts(schedules: ScheduleItem[], resourceId: string): ScheduleItem[][] {
const resourceSchedules = schedules
.filter(s => s.resourceId === resourceId)
.sort((a, b) => new Date(a.startDate).getTime() - new Date(b.startDate).getTime());
const conflicts: ScheduleItem[][] = [];
for (let i = 0; i < resourceSchedules.length; i++) {
const current = resourceSchedules[i];
const overlapping = resourceSchedules.filter(s =>
s.id !== current.id &&
new Date(s.startDate) < new Date(current.endDate) &&
new Date(s.endDate) > new Date(current.startDate)
);
if (overlapping.length > 0) {
conflicts.push([current, ...overlapping]);
}
}
return conflicts;
}
3. 구현 우선순위 및 일정
3.1 권장 순서
1단계: v2-table-grouped (2-3일)
↓
2단계: v2-timeline-scheduler (5-7일)
↓
3단계: 생산계획관리 정식 버전 화면 구성 (1-2일)
3.2 이유
-
v2-table-grouped 먼저:
v2-table-list 기반 확장으로 난이도 낮음
- 생산계획 외 다른 화면(BOM, 수주 등)에서도 활용 가능
- 타임라인 개발 중에도 테스트용으로 사용 가능
-
v2-timeline-scheduler 나중:
- 복잡도가 높아 집중 개발 필요
- 드래그/리사이즈 등 인터랙션 테스트 필요
- 생산계획관리 전용 컴포넌트
3.3 체크리스트
v2-table-grouped
v2-timeline-scheduler
4. 참고 자료
기존 V2 컴포넌트 참고
v2-table-list: 테이블 렌더링, 체크박스, 페이지네이션
v2-pivot-grid: 복잡한 그리드 렌더링, 가상 스크롤
v2-split-panel-layout: 커스텀 모드 컴포넌트 배치
외부 라이브러리 검토
| 라이브러리 |
용도 |
고려 사항 |
@tanstack/react-virtual |
가상 스크롤 |
이미 사용 중, 확장 용이 |
date-fns |
날짜 계산 |
이미 사용 중 |
react-dnd |
드래그앤드롭 |
검토 필요, 현재 네이티브 구현 |
관련 문서
작성자: Claude AI
최종 수정: 2026-01-30