diff --git a/frontend/app/(main)/admin/dashboard/DashboardListClient.tsx b/frontend/app/(main)/admin/dashboard/DashboardListClient.tsx index 082e8661..e7680584 100644 --- a/frontend/app/(main)/admin/dashboard/DashboardListClient.tsx +++ b/frontend/app/(main)/admin/dashboard/DashboardListClient.tsx @@ -18,32 +18,26 @@ import { Pagination, PaginationInfo } from "@/components/common/Pagination"; import { DeleteConfirmModal } from "@/components/common/DeleteConfirmModal"; import { Plus, Search, Edit, Trash2, Copy, MoreVertical, AlertCircle, RefreshCw } from "lucide-react"; -interface DashboardListClientProps { - initialDashboards: Dashboard[]; - initialPagination: { - total: number; - page: number; - limit: number; - }; -} - /** * 대시보드 목록 클라이언트 컴포넌트 + * - CSR 방식으로 초기 데이터 로드 * - 대시보드 목록 조회 * - 대시보드 생성/수정/삭제/복사 */ -export default function DashboardListClient({ initialDashboards, initialPagination }: DashboardListClientProps) { +export default function DashboardListClient() { const router = useRouter(); const { toast } = useToast(); - const [dashboards, setDashboards] = useState(initialDashboards); - const [loading, setLoading] = useState(false); // 초기 로딩은 서버에서 완료 + + // 상태 관리 + const [dashboards, setDashboards] = useState([]); + const [loading, setLoading] = useState(true); // CSR이므로 초기 로딩 true const [error, setError] = useState(null); const [searchTerm, setSearchTerm] = useState(""); // 페이지네이션 상태 - const [currentPage, setCurrentPage] = useState(initialPagination.page); - const [pageSize, setPageSize] = useState(initialPagination.limit); - const [totalCount, setTotalCount] = useState(initialPagination.total); + const [currentPage, setCurrentPage] = useState(1); + const [pageSize, setPageSize] = useState(10); + const [totalCount, setTotalCount] = useState(0); // 모달 상태 const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); @@ -73,17 +67,8 @@ export default function DashboardListClient({ initialDashboards, initialPaginati } }; - // 초기 로드 여부 추적 - const [isInitialLoad, setIsInitialLoad] = useState(true); - + // 검색어/페이지 변경 시 fetch (초기 로딩 포함) useEffect(() => { - // 초기 로드는 건너뛰기 (서버에서 이미 데이터를 가져왔음) - if (isInitialLoad) { - setIsInitialLoad(false); - return; - } - - // 이후 검색어/페이지 변경 시에만 fetch loadDashboards(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [searchTerm, currentPage, pageSize]); @@ -91,7 +76,7 @@ export default function DashboardListClient({ initialDashboards, initialPaginati // 페이지네이션 정보 계산 const paginationInfo: PaginationInfo = { currentPage, - totalPages: Math.ceil(totalCount / pageSize), + totalPages: Math.ceil(totalCount / pageSize) || 1, totalItems: totalCount, itemsPerPage: pageSize, startItem: totalCount === 0 ? 0 : (currentPage - 1) * pageSize + 1, diff --git a/frontend/app/(main)/admin/dashboard/page.tsx b/frontend/app/(main)/admin/dashboard/page.tsx index 8d78600c..7d09bafc 100644 --- a/frontend/app/(main)/admin/dashboard/page.tsx +++ b/frontend/app/(main)/admin/dashboard/page.tsx @@ -1,73 +1,22 @@ import DashboardListClient from "@/app/(main)/admin/dashboard/DashboardListClient"; -import { cookies } from "next/headers"; /** - * 서버에서 초기 대시보드 목록 fetch + * 대시보드 관리 페이지 + * - 클라이언트 컴포넌트를 렌더링하는 래퍼 + * - 초기 로딩부터 CSR로 처리 */ -async function getInitialDashboards() { - try { - // 서버 사이드 전용: 백엔드 API 직접 호출 - // 도커 네트워크 내부에서는 서비스 이름 사용, 로컬에서는 127.0.0.1 - const backendUrl = process.env.SERVER_API_URL || "http://backend:8080"; - - // 쿠키에서 authToken 추출 - const cookieStore = await cookies(); - const authToken = cookieStore.get("authToken")?.value; - - if (!authToken) { - // 토큰이 없으면 빈 데이터 반환 (클라이언트에서 로드) - return { - dashboards: [], - pagination: { total: 0, page: 1, limit: 10 }, - }; - } - - const response = await fetch(`${backendUrl}/api/dashboards/my?page=1&limit=10`, { - cache: "no-store", // 항상 최신 데이터 - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${authToken}`, // Authorization 헤더로 전달 - }, - }); - - if (!response.ok) { - throw new Error(`Failed to fetch dashboards: ${response.status}`); - } - - const data = await response.json(); - return { - dashboards: data.data || [], - pagination: data.pagination || { total: 0, page: 1, limit: 10 }, - }; - } catch (error) { - console.error("Server-side fetch error:", error); - // 에러 발생 시 빈 데이터 반환 (클라이언트에서 재시도 가능) - return { - dashboards: [], - pagination: { total: 0, page: 1, limit: 10 }, - }; - } -} - -/** - * 대시보드 관리 페이지 (서버 컴포넌트) - * - 페이지 헤더 + 초기 데이터를 서버에서 렌더링 - * - 클라이언트 컴포넌트로 초기 데이터 전달 - */ -export default async function DashboardListPage() { - const initialData = await getInitialDashboards(); - +export default function DashboardListPage() { return (
- {/* 페이지 헤더 (서버에서 렌더링) */} + {/* 페이지 헤더 */}

대시보드 관리

대시보드를 생성하고 관리할 수 있습니다

- {/* 나머지 컨텐츠 (클라이언트 컴포넌트 + 서버 데이터) */} - + {/* 클라이언트 컴포넌트 */} +
);