ERP-node/docs/screen-implementation-guide/00_analysis/next-component-development-...

19 KiB

다음 구현 필요 컴포넌트 개발 계획

작성일: 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 이유

  1. v2-table-grouped 먼저:

    • v2-table-list 기반 확장으로 난이도 낮음
    • 생산계획 외 다른 화면(BOM, 수주 등)에서도 활용 가능
    • 타임라인 개발 중에도 테스트용으로 사용 가능
  2. v2-timeline-scheduler 나중:

    • 복잡도가 높아 집중 개발 필요
    • 드래그/리사이즈 등 인터랙션 테스트 필요
    • 생산계획관리 전용 컴포넌트

3.3 체크리스트

v2-table-grouped

  • 타입 정의 완료
  • 기본 구조 생성
  • useGroupedData 훅 구현
  • GroupHeader 컴포넌트
  • 메인 컴포넌트 구현
  • 그룹 체크박스 연동
  • 그룹 요약 (합계/개수)
  • 설정 패널 구현
  • 레지스트리 등록
  • 테스트 완료
  • 문서화

v2-timeline-scheduler

  • 타입 정의 완료
  • 기본 구조 생성
  • TimelineHeader (날짜)
  • TimelineGrid (배경)
  • ResourceColumn (리소스)
  • ScheduleBar 기본 렌더링
  • 드래그 이동
  • 리사이즈
  • 줌 레벨 전환
  • 날짜 네비게이션
  • 충돌 감지
  • 가상 스크롤
  • 설정 패널 구현
  • API 연동
  • 레지스트리 등록
  • 테스트 완료
  • 문서화

4. 참고 자료

기존 V2 컴포넌트 참고

  • v2-table-list: 테이블 렌더링, 체크박스, 페이지네이션
  • v2-pivot-grid: 복잡한 그리드 렌더링, 가상 스크롤
  • v2-split-panel-layout: 커스텀 모드 컴포넌트 배치

외부 라이브러리 검토

라이브러리 용도 고려 사항
@tanstack/react-virtual 가상 스크롤 이미 사용 중, 확장 용이
date-fns 날짜 계산 이미 사용 중
react-dnd 드래그앤드롭 검토 필요, 현재 네이티브 구현

관련 문서


작성자: Claude AI 최종 수정: 2026-01-30