관리자 메뉴 토큰문제 수정정
This commit is contained in:
244
frontend/app/(main)/admin/debug-layout/page.tsx
Normal file
244
frontend/app/(main)/admin/debug-layout/page.tsx
Normal file
@@ -0,0 +1,244 @@
|
||||
"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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user