# 다음 구현 필요 컴포넌트 개발 계획 > **작성일**: 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) ```typescript 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; } ``` ### 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) ```typescript /** * 줌 레벨 */ 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; } /** * 리소스 (행) */ 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; /** 리소스 컬럼 너비 */ 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 핵심 알고리즘 #### 날짜 → 픽셀 위치 변환 ```typescript 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); } } ``` #### 충돌 감지 ```typescript 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 이유 1. **v2-table-grouped 먼저**: - `v2-table-list` 기반 확장으로 난이도 낮음 - 생산계획 외 다른 화면(BOM, 수주 등)에서도 활용 가능 - 타임라인 개발 중에도 테스트용으로 사용 가능 2. **v2-timeline-scheduler 나중**: - 복잡도가 높아 집중 개발 필요 - 드래그/리사이즈 등 인터랙션 테스트 필요 - 생산계획관리 전용 컴포넌트 ### 3.3 체크리스트 #### v2-table-grouped ✅ 구현 완료 (2026-01-30) - [x] 타입 정의 완료 - [x] 기본 구조 생성 - [x] useGroupedData 훅 구현 - [x] GroupHeader 컴포넌트 - [x] 메인 컴포넌트 구현 - [x] 그룹 체크박스 연동 - [x] 그룹 요약 (합계/개수) - [x] 설정 패널 구현 - [x] 레지스트리 등록 - [x] 문서화 (README.md) #### v2-timeline-scheduler ✅ 구현 완료 (2026-01-30) - [x] 타입 정의 완료 - [x] 기본 구조 생성 - [x] TimelineHeader (날짜) - [x] TimelineGrid (배경) - [x] ResourceColumn (리소스) - [x] ScheduleBar 기본 렌더링 - [x] 드래그 이동 (기본) - [x] 리사이즈 (기본) - [x] 줌 레벨 전환 - [x] 날짜 네비게이션 - [ ] 충돌 감지 (향후) - [ ] 가상 스크롤 (향후) - [x] 설정 패널 구현 - [x] API 연동 - [x] 레지스트리 등록 - [ ] 테스트 완료 - [x] 문서화 (README.md) --- ## 4. 참고 자료 ### 기존 V2 컴포넌트 참고 - `v2-table-list`: 테이블 렌더링, 체크박스, 페이지네이션 - `v2-pivot-grid`: 복잡한 그리드 렌더링, 가상 스크롤 - `v2-split-panel-layout`: 커스텀 모드 컴포넌트 배치 ### 외부 라이브러리 검토 | 라이브러리 | 용도 | 고려 사항 | |----------|------|----------| | `@tanstack/react-virtual` | 가상 스크롤 | 이미 사용 중, 확장 용이 | | `date-fns` | 날짜 계산 | 이미 사용 중 | | `react-dnd` | 드래그앤드롭 | 검토 필요, 현재 네이티브 구현 | ### 관련 문서 - [생산계획관리 화면 설계](../03_production/production-plan.md) - [V2 컴포넌트 분석 가이드](../../V2_컴포넌트_분석_가이드.md) - [컴포넌트 개발 가이드](../../../frontend/docs/component-development-guide.md) --- **작성자**: Claude AI **최종 수정**: 2026-01-30