245 lines
8.3 KiB
TypeScript
245 lines
8.3 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { tokenSync } from "@/lib/sessionManager";
|
|
import { apiClient } from "@/lib/api/client";
|
|
|
|
export default function DebugLayoutPage() {
|
|
const [debugInfo, setDebugInfo] = useState<any>({});
|
|
const [apiTestResult, setApiTestResult] = useState<any>(null);
|
|
|
|
useEffect(() => {
|
|
const token = localStorage.getItem("authToken");
|
|
|
|
const info = {
|
|
hasToken: !!token,
|
|
tokenLength: token ? token.length : 0,
|
|
tokenStart: token ? token.substring(0, 30) + "..." : "없음",
|
|
currentUrl: window.location.href,
|
|
pathname: window.location.pathname,
|
|
timestamp: new Date().toISOString(),
|
|
sessionToken: !!sessionStorage.getItem("authToken"),
|
|
tokenValid: token ? tokenSync.validateToken(token) : false,
|
|
};
|
|
|
|
setDebugInfo(info);
|
|
console.log("=== DebugLayoutPage 토큰 정보 ===", info);
|
|
}, []);
|
|
|
|
const handleTokenSync = () => {
|
|
const result = tokenSync.forceSync();
|
|
alert(`토큰 동기화: ${result ? "성공" : "실패"}`);
|
|
window.location.reload();
|
|
};
|
|
|
|
const handleTokenRestore = () => {
|
|
const result = tokenSync.restoreFromSession();
|
|
alert(`토큰 복원: ${result ? "성공" : "실패"}`);
|
|
window.location.reload();
|
|
};
|
|
|
|
const handleApiTest = async () => {
|
|
try {
|
|
console.log("🧪 API 테스트 시작");
|
|
setApiTestResult({ status: "loading", message: "API 호출 중..." });
|
|
|
|
// 간단한 API 호출 테스트
|
|
const response = await apiClient.get("/auth/status");
|
|
|
|
setApiTestResult({
|
|
status: "success",
|
|
message: "API 호출 성공",
|
|
data: response.data,
|
|
statusCode: response.status,
|
|
});
|
|
|
|
console.log("✅ API 테스트 성공:", response.data);
|
|
} catch (error: any) {
|
|
setApiTestResult({
|
|
status: "error",
|
|
message: "API 호출 실패",
|
|
error: error.message,
|
|
statusCode: error.response?.status,
|
|
data: error.response?.data,
|
|
});
|
|
|
|
console.error("❌ API 테스트 실패:", error);
|
|
}
|
|
};
|
|
|
|
const handleUserApiTest = async () => {
|
|
try {
|
|
console.log("🧪 사용자 API 테스트 시작");
|
|
setApiTestResult({ status: "loading", message: "사용자 API 호출 중..." });
|
|
|
|
// 사용자 목록 API 호출 테스트
|
|
const response = await apiClient.get("/admin/users", {
|
|
params: { page: 1, countPerPage: 5 },
|
|
});
|
|
|
|
setApiTestResult({
|
|
status: "success",
|
|
message: "사용자 API 호출 성공",
|
|
data: response.data,
|
|
statusCode: response.status,
|
|
});
|
|
|
|
console.log("✅ 사용자 API 테스트 성공:", response.data);
|
|
} catch (error: any) {
|
|
setApiTestResult({
|
|
status: "error",
|
|
message: "사용자 API 호출 실패",
|
|
error: error.message,
|
|
statusCode: error.response?.status,
|
|
data: error.response?.data,
|
|
});
|
|
|
|
console.error("❌ 사용자 API 테스트 실패:", error);
|
|
}
|
|
};
|
|
|
|
const handleHealthCheck = async () => {
|
|
try {
|
|
console.log("🏥 헬스 체크 시작");
|
|
setApiTestResult({ status: "loading", message: "서버 상태 확인 중..." });
|
|
|
|
// 백엔드 서버 헬스 체크
|
|
const response = await fetch("http://localhost:8080/health");
|
|
const data = await response.json();
|
|
|
|
setApiTestResult({
|
|
status: "success",
|
|
message: "서버 상태 확인 성공",
|
|
data: data,
|
|
statusCode: response.status,
|
|
});
|
|
|
|
console.log("✅ 헬스 체크 성공:", data);
|
|
} catch (error: any) {
|
|
setApiTestResult({
|
|
status: "error",
|
|
message: "서버 상태 확인 실패",
|
|
error: error.message,
|
|
statusCode: error.status,
|
|
data: null,
|
|
});
|
|
|
|
console.error("❌ 헬스 체크 실패:", error);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="p-6">
|
|
<h1 className="mb-4 text-2xl font-bold">관리자 레이아웃 디버깅</h1>
|
|
|
|
<div className="space-y-4">
|
|
<div className="rounded bg-green-100 p-4">
|
|
<h2 className="mb-2 font-semibold">토큰 상태</h2>
|
|
<p>토큰 존재: {debugInfo.hasToken ? "✅ 예" : "❌ 아니오"}</p>
|
|
<p>토큰 길이: {debugInfo.tokenLength}</p>
|
|
<p>토큰 시작: {debugInfo.tokenStart}</p>
|
|
<p>토큰 유효성: {debugInfo.tokenValid ? "✅ 유효" : "❌ 무효"}</p>
|
|
<p>SessionStorage 토큰: {debugInfo.sessionToken ? "✅ 존재" : "❌ 없음"}</p>
|
|
</div>
|
|
|
|
<div className="rounded bg-blue-100 p-4">
|
|
<h2 className="mb-2 font-semibold">페이지 정보</h2>
|
|
<p>현재 URL: {debugInfo.currentUrl}</p>
|
|
<p>Pathname: {debugInfo.pathname}</p>
|
|
<p>시간: {debugInfo.timestamp}</p>
|
|
</div>
|
|
|
|
<div className="rounded bg-yellow-100 p-4">
|
|
<h2 className="mb-2 font-semibold">토큰 관리</h2>
|
|
<div className="space-x-2">
|
|
<button
|
|
onClick={() => {
|
|
const token = localStorage.getItem("authToken");
|
|
alert(`토큰: ${token ? "존재" : "없음"}\n길이: ${token ? token.length : 0}`);
|
|
}}
|
|
className="rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-600"
|
|
>
|
|
토큰 확인
|
|
</button>
|
|
<button onClick={handleTokenSync} className="rounded bg-green-500 px-4 py-2 text-white hover:bg-green-600">
|
|
토큰 동기화
|
|
</button>
|
|
<button
|
|
onClick={handleTokenRestore}
|
|
className="rounded bg-purple-500 px-4 py-2 text-white hover:bg-purple-600"
|
|
>
|
|
토큰 복원
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="rounded bg-orange-100 p-4">
|
|
<h2 className="mb-2 font-semibold">API 테스트</h2>
|
|
<div className="mb-4 space-x-2">
|
|
<button onClick={handleApiTest} className="rounded bg-orange-500 px-4 py-2 text-white hover:bg-orange-600">
|
|
인증 상태 API 테스트
|
|
</button>
|
|
<button onClick={handleUserApiTest} className="rounded bg-red-500 px-4 py-2 text-white hover:bg-red-600">
|
|
사용자 API 테스트
|
|
</button>
|
|
<button
|
|
onClick={handleHealthCheck}
|
|
className="rounded bg-purple-500 px-4 py-2 text-white hover:bg-purple-600"
|
|
>
|
|
서버 상태 확인
|
|
</button>
|
|
</div>
|
|
|
|
{apiTestResult && (
|
|
<div
|
|
className={`rounded p-3 ${
|
|
apiTestResult.status === "success"
|
|
? "bg-green-200"
|
|
: apiTestResult.status === "error"
|
|
? "bg-red-200"
|
|
: "bg-yellow-200"
|
|
}`}
|
|
>
|
|
<h3 className="font-semibold">{apiTestResult.message}</h3>
|
|
{apiTestResult.statusCode && <p>상태 코드: {apiTestResult.statusCode}</p>}
|
|
{apiTestResult.error && <p>오류: {apiTestResult.error}</p>}
|
|
{apiTestResult.data && (
|
|
<details className="mt-2">
|
|
<summary className="cursor-pointer">응답 데이터</summary>
|
|
<pre className="mt-2 overflow-auto rounded bg-white p-2 text-xs">
|
|
{JSON.stringify(apiTestResult.data, null, 2)}
|
|
</pre>
|
|
</details>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="rounded bg-purple-100 p-4">
|
|
<h2 className="mb-2 font-semibold">메뉴 이동 테스트</h2>
|
|
<div className="space-x-2">
|
|
<button
|
|
onClick={() => (window.location.href = "/admin/menu")}
|
|
className="rounded bg-purple-500 px-4 py-2 text-white hover:bg-purple-600"
|
|
>
|
|
메뉴 관리
|
|
</button>
|
|
<button
|
|
onClick={() => (window.location.href = "/admin/userMng")}
|
|
className="rounded bg-purple-500 px-4 py-2 text-white hover:bg-purple-600"
|
|
>
|
|
사용자 관리
|
|
</button>
|
|
<button
|
|
onClick={() => (window.location.href = "/admin")}
|
|
className="rounded bg-purple-500 px-4 py-2 text-white hover:bg-purple-600"
|
|
>
|
|
메인 페이지
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|