From d29553900510c0c20b2225513b0b7b45ce02c5b7 Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Mon, 8 Dec 2025 20:33:57 +0900
Subject: (김준회) 견적: 테이블 상태관리: 로딩 중 상태관리 문제 처리
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/rfq-last/table/rfq-table.tsx | 91 ++++++++++++++++------------------------
 1 file changed, 37 insertions(+), 54 deletions(-)

(limited to 'lib/rfq-last/table/rfq-table.tsx')

diff --git a/lib/rfq-last/table/rfq-table.tsx b/lib/rfq-last/table/rfq-table.tsx
index e8dd299d..aa52b2e8 100644
--- a/lib/rfq-last/table/rfq-table.tsx
+++ b/lib/rfq-last/table/rfq-table.tsx
@@ -70,60 +70,18 @@ export function RfqTable({
   // 초기 데이터 설정
   const [tableData, setTableData] = React.useState(data);
   const [isDataLoading, setIsDataLoading] = React.useState(false);
+  const loadingRef = React.useRef(false); // 중복 요청 방지
+
+  // 데이터 새로고침 함수 (메모이제이션)
+  const refetchData = React.useCallback(async () => {
+    // 이미 로딩 중이면 중복 요청 방지
+    if (loadingRef.current) {
+      console.log("=== 이미 로딩 중, 요청 스킵 ===");
+      return;
+    }
 
-  // URL 필터 변경 감지 및 데이터 새로고침
-  React.useEffect(() => {
-    const refetchData = async () => {
-      try {
-        setIsDataLoading(true);
-        
-        const currentFilters = getSearchParam("filters");
-        const currentJoinOperator = getSearchParam("joinOperator", "and");
-        const currentPage = parseInt(getSearchParam("page", "1"));
-        const currentPerPage = parseInt(getSearchParam("perPage", "10"));
-        const currentSort = getSearchParam('sort') ? JSON.parse(getSearchParam('sort')!) : [{ id: "createdAt", desc: true }];
-        const currentSearch = getSearchParam("search", "");
-        
-        const searchParams = {
-          filters: currentFilters ? JSON.parse(currentFilters) : [],
-          joinOperator: currentJoinOperator as "and" | "or",
-          page: currentPage,
-          perPage: currentPerPage,
-          sort: currentSort,
-          search: currentSearch,
-          rfqCategory: rfqCategory,
-        };
-        
-        console.log("=== 새 데이터 요청 ===", searchParams);
-        
-        const newData = await getRfqs(searchParams);
-        setTableData(newData);
-        
-        console.log("=== 데이터 업데이트 완료 ===", newData.data.length, "건");
-      } catch (error) {
-        console.error("데이터 새로고침 오류:", error);
-      } finally {
-        setIsDataLoading(false);
-      }
-    };
-
-    const timeoutId = setTimeout(() => {
-      const hasChanges = getSearchParam("filters") || 
-                        getSearchParam("search") || 
-                        getSearchParam("page") !== "1" || 
-                        getSearchParam("perPage") !== "10" ||
-                        getSearchParam("sort");
-      
-      if (hasChanges) {
-        refetchData();
-      }
-    }, 300);
-
-    return () => clearTimeout(timeoutId);
-  }, [searchString, rfqCategory, getSearchParam]);
-
-  const refreshData = React.useCallback(async () => {
     try {
+      loadingRef.current = true;
       setIsDataLoading(true);
       
       const currentFilters = getSearchParam("filters");
@@ -143,16 +101,41 @@ export function RfqTable({
         rfqCategory: rfqCategory,
       };
       
+      console.log("=== 새 데이터 요청 ===", searchParams);
+      
       const newData = await getRfqs(searchParams);
       setTableData(newData);
       
-      console.log("=== 데이터 새로고침 완료 ===", newData.data.length, "건");
+      console.log("=== 데이터 업데이트 완료 ===", newData.data.length, "건");
     } catch (error) {
       console.error("데이터 새로고침 오류:", error);
     } finally {
       setIsDataLoading(false);
+      loadingRef.current = false;
     }
-  }, [rfqCategory, getSearchParam]);
+  }, [getSearchParam, rfqCategory]);
+
+  // URL 필터 변경 감지 및 데이터 새로고침
+  React.useEffect(() => {
+    const timeoutId = setTimeout(() => {
+      const hasChanges = getSearchParam("filters") || 
+                        getSearchParam("search") || 
+                        getSearchParam("page") !== "1" || 
+                        getSearchParam("perPage") !== "10" ||
+                        getSearchParam("sort");
+      
+      if (hasChanges) {
+        refetchData();
+      }
+    }, 300);
+
+    return () => clearTimeout(timeoutId);
+  }, [searchString, rfqCategory, refetchData, getSearchParam]);
+
+  // 수동 새로고침 함수 (refetchData 재사용)
+  const refreshData = React.useCallback(async () => {
+    await refetchData();
+  }, [refetchData]);
 
   // 컨테이너 위치 추적
   const containerRef = React.useRef<HTMLDivElement>(null);
-- 
cgit v1.2.3

