diff --git a/frontend/components/screen/InteractiveDataTable.tsx b/frontend/components/screen/InteractiveDataTable.tsx index 8a31756c..c9b24892 100644 --- a/frontend/components/screen/InteractiveDataTable.tsx +++ b/frontend/components/screen/InteractiveDataTable.tsx @@ -1921,7 +1921,7 @@ export const InteractiveDataTable: React.FC = ({ {visibleColumns.length > 0 ? ( <>
- +
{/* 체크박스 컬럼 (삭제 기능이 활성화된 경우) */} @@ -1935,15 +1935,25 @@ export const InteractiveDataTable: React.FC = ({ )} {visibleColumns.map((column: DataTableColumn, columnIndex) => { const columnWidth = columnWidths[column.id]; - const defaultWidth = `${((column.gridColumns || 2) / totalGridColumns) * 100}%`; return ( { + // 첫 렌더링 시 실제 너비를 측정해서 상태에 저장 + if (el && !columnWidth) { + const measuredWidth = el.offsetWidth; + if (measuredWidth > 0) { + setColumnWidths(prev => ({ + ...prev, + [column.id]: measuredWidth + })); + } + } + }} className="relative bg-gradient-to-r from-gray-50 to-slate-50 px-4 font-semibold text-gray-700 select-none" style={{ - width: columnWidth ? `${columnWidth}px` : defaultWidth, - minWidth: '80px', + width: columnWidth ? `${columnWidth}px` : undefined, userSelect: 'none' }} > @@ -1956,10 +1966,13 @@ export const InteractiveDataTable: React.FC = ({ onClick={(e) => e.stopPropagation()} onMouseDown={(e) => { e.preventDefault(); - e.stopPropagation(); // 상위 컴포넌트 드래그 이벤트 방지 + e.stopPropagation(); + + const thElement = e.currentTarget.parentElement as HTMLTableCellElement; + if (!thElement) return; const startX = e.clientX; - const startWidth = columnWidth || (e.currentTarget.parentElement?.offsetWidth || 100); + const startWidth = columnWidth || thElement.offsetWidth; // 드래그 중 텍스트 선택 방지 document.body.style.userSelect = 'none'; @@ -1967,12 +1980,23 @@ export const InteractiveDataTable: React.FC = ({ const handleMouseMove = (moveEvent: MouseEvent) => { moveEvent.preventDefault(); + const diff = moveEvent.clientX - startX; const newWidth = Math.max(80, startWidth + diff); - setColumnWidths(prev => ({ ...prev, [column.id]: newWidth })); + + // 직접 DOM 스타일 변경 (리렌더링 없음) + if (thElement) { + thElement.style.width = `${newWidth}px`; + } }; const handleMouseUp = () => { + // 최종 너비를 state에 저장 + if (thElement) { + const finalWidth = Math.max(80, thElement.offsetWidth); + setColumnWidths(prev => ({ ...prev, [column.id]: finalWidth })); + } + // 텍스트 선택 복원 document.body.style.userSelect = ''; document.body.style.cursor = ''; diff --git a/frontend/lib/registry/components/table-list/TableListComponent.tsx b/frontend/lib/registry/components/table-list/TableListComponent.tsx index 4fa655e2..6a753734 100644 --- a/frontend/lib/registry/components/table-list/TableListComponent.tsx +++ b/frontend/lib/registry/components/table-list/TableListComponent.tsx @@ -1023,19 +1023,30 @@ export const TableListComponent: React.FC = ({ {visibleColumns.map((column, columnIndex) => { const columnWidth = columnWidths[column.columnName]; - const defaultWidth = `${100 / visibleColumns.length}%`; return (
(columnRefs.current[column.columnName] = el)} + ref={(el) => { + columnRefs.current[column.columnName] = el; + // 첫 렌더링 시 실제 너비를 측정해서 상태에 저장 + if (el && !columnWidth) { + const measuredWidth = el.offsetWidth; + if (measuredWidth > 0) { + setColumnWidths(prev => ({ + ...prev, + [column.columnName]: measuredWidth + })); + } + } + }} className={cn( "relative h-10 px-2 py-2 text-xs font-semibold text-foreground overflow-hidden text-ellipsis bg-background select-none sm:h-12 sm:px-6 sm:py-3 sm:text-sm sm:whitespace-nowrap", column.sortable && "cursor-pointer" )} style={{ textAlign: column.align || "left", - width: columnWidth ? `${columnWidth}px` : defaultWidth, + width: columnWidth ? `${columnWidth}px` : undefined, userSelect: 'none' }} onClick={() => column.sortable && handleSort(column.columnName)}