diff --git a/frontend/components/screen/InteractiveDataTable.tsx b/frontend/components/screen/InteractiveDataTable.tsx index c9b24892..5d31da83 100644 --- a/frontend/components/screen/InteractiveDataTable.tsx +++ b/frontend/components/screen/InteractiveDataTable.tsx @@ -107,6 +107,8 @@ export const InteractiveDataTable: React.FC = ({ const [total, setTotal] = useState(0); const [selectedRows, setSelectedRows] = useState>(new Set()); const [columnWidths, setColumnWidths] = useState>({}); + const hasInitializedWidthsRef = useRef(false); + const columnRefs = useRef>({}); // SaveModal 상태 (등록/수정 통합) const [showSaveModal, setShowSaveModal] = useState(false); @@ -409,6 +411,35 @@ export const InteractiveDataTable: React.FC = ({ // 페이지 크기 설정 const pageSize = component.pagination?.pageSize || 10; + // 초기 컬럼 너비 측정 (한 번만) + useEffect(() => { + if (!hasInitializedWidthsRef.current && visibleColumns.length > 0) { + // 약간의 지연을 두고 DOM이 완전히 렌더링된 후 측정 + const timer = setTimeout(() => { + const newWidths: Record = {}; + let hasAnyWidth = false; + + visibleColumns.forEach((column) => { + const thElement = columnRefs.current[column.id]; + if (thElement) { + const measuredWidth = thElement.offsetWidth; + if (measuredWidth > 0) { + newWidths[column.id] = measuredWidth; + hasAnyWidth = true; + } + } + }); + + if (hasAnyWidth) { + setColumnWidths(newWidths); + hasInitializedWidthsRef.current = true; + } + }, 100); + + return () => clearTimeout(timer); + } + }, [visibleColumns]); + // 데이터 로드 함수 const loadData = useCallback( async (page: number = 1, searchParams: Record = {}) => { @@ -1939,18 +1970,7 @@ export const InteractiveDataTable: React.FC = ({ return ( { - // 첫 렌더링 시 실제 너비를 측정해서 상태에 저장 - if (el && !columnWidth) { - const measuredWidth = el.offsetWidth; - if (measuredWidth > 0) { - setColumnWidths(prev => ({ - ...prev, - [column.id]: measuredWidth - })); - } - } - }} + ref={(el) => (columnRefs.current[column.id] = el)} 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` : undefined, @@ -1968,7 +1988,7 @@ export const InteractiveDataTable: React.FC = ({ e.preventDefault(); e.stopPropagation(); - const thElement = e.currentTarget.parentElement as HTMLTableCellElement; + const thElement = columnRefs.current[column.id]; if (!thElement) return; const startX = e.clientX; diff --git a/frontend/lib/registry/components/table-list/TableListComponent.tsx b/frontend/lib/registry/components/table-list/TableListComponent.tsx index 6a753734..10e17fa5 100644 --- a/frontend/lib/registry/components/table-list/TableListComponent.tsx +++ b/frontend/lib/registry/components/table-list/TableListComponent.tsx @@ -247,6 +247,7 @@ export const TableListComponent: React.FC = ({ const [columnWidths, setColumnWidths] = useState>({}); const columnRefs = useRef>({}); const [isAllSelected, setIsAllSelected] = useState(false); + const hasInitializedWidths = useRef(false); // 필터 설정 관련 상태 const [isFilterSettingOpen, setIsFilterSettingOpen] = useState(false); @@ -794,6 +795,35 @@ export const TableListComponent: React.FC = ({ } }, [tableConfig.refreshInterval, isDesignMode]); + // 초기 컬럼 너비 측정 (한 번만) + useEffect(() => { + if (!hasInitializedWidths.current && visibleColumns.length > 0) { + // 약간의 지연을 두고 DOM이 완전히 렌더링된 후 측정 + const timer = setTimeout(() => { + const newWidths: Record = {}; + let hasAnyWidth = false; + + visibleColumns.forEach((column) => { + const thElement = columnRefs.current[column.columnName]; + if (thElement) { + const measuredWidth = thElement.offsetWidth; + if (measuredWidth > 0) { + newWidths[column.columnName] = measuredWidth; + hasAnyWidth = true; + } + } + }); + + if (hasAnyWidth) { + setColumnWidths(newWidths); + hasInitializedWidths.current = true; + } + }, 100); + + return () => clearTimeout(timer); + } + }, [visibleColumns]); + // ======================================== // 페이지네이션 JSX // ======================================== @@ -1027,19 +1057,7 @@ export const TableListComponent: React.FC = ({ return ( { - columnRefs.current[column.columnName] = el; - // 첫 렌더링 시 실제 너비를 측정해서 상태에 저장 - if (el && !columnWidth) { - const measuredWidth = el.offsetWidth; - if (measuredWidth > 0) { - setColumnWidths(prev => ({ - ...prev, - [column.columnName]: measuredWidth - })); - } - } - }} + ref={(el) => (columnRefs.current[column.columnName] = el)} 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"