diff --git a/src/app/menu/page.tsx b/src/app/menu/page.tsx index 9a4ae8f..22a65e5 100644 --- a/src/app/menu/page.tsx +++ b/src/app/menu/page.tsx @@ -48,7 +48,7 @@ const MenuItemCard: React.FC = ({ const originalPhoto = photoData?.result?.content?.[0]; const imageUrl = food.thumbnailUrl && originalPhoto - ? `${process.env.NEXT_PUBLIC_IMAGE_URL}/${food.thumbnailUrl}?s=80x80&t=crop&q=70` + ? `${process.env.NEXT_PUBLIC_IMAGE_URL}/${food.thumbnailUrl}?s=300x300&t=crop&q=100` : null; const formatPrice = (price: number) => { diff --git a/src/components/auth/LoginGuard.tsx b/src/components/auth/LoginGuard.tsx index b6e3acc..c2c08f5 100644 --- a/src/components/auth/LoginGuard.tsx +++ b/src/components/auth/LoginGuard.tsx @@ -48,25 +48,168 @@ export function LoginGuard({ children }: LoginGuardProps) { window.location.reload(); }; - // 토큰이 없으면 네이티브 로그인 호출 - if (!isLoggedIn || !tokens) { + // 로딩 중이거나 토큰이 없으면 적절한 UI 표시 + if (userInfoLoading || (isLoggedIn === false && !tokens)) { + const loadingText = userInfoLoading + ? "로그인 상태를 확인하는 중..." + : "로그인 화면으로 이동 중..."; + return (
-

로그인 화면으로 이동 중...

+

{loadingText}

); } - // 토큰이 있으면 로딩 후 홈화면 - if (userInfoLoading) { + // 토큰이 없고 로딩이 끝났으면 로그인 필요 화면 표시 + if (!isLoggedIn || !tokens) { + // 기존 로그인 필요 화면으로 바로 이동 + return ( +
+ +
+
+ +
+

+ 로그인이 필요합니다 +

+

+ {isAvailable + ? "앱에서 로그인 후 다시 시도해주세요" + : "Chalpu 앱에서 로그인 후 이용해주세요"} +

+
+ + {/* 인증 에러 표시 */} + {userInfoError && ( +
+

+ 로그인 정보 확인 실패:{" "} + {userInfoError.message || "알 수 없는 오류"} +

+ +
+ )} + +
+
+

+ {isAvailable + ? "📱 앱에서 로그인을 완료한 후 웹뷰로 이동해주세요" + : "📱 Chalpu 앱을 다운로드하여 로그인해주세요"} +

+
+
+ + {process.env.NODE_ENV === "development" && ( +
+

개발 모드

+ + {/* 환경 정보 섹션 */} +
+

+ 🔍 환경 정보 +

+
+
+ 플랫폼: + + {isAvailable ? "📱 네이티브 앱" : "🌐 웹 브라우저"} + +
+
+ 유저 정보: + + {userInfoError + ? "❌ 실패" + : userInfo + ? "✅ 성공" + : "⏳ 로딩중"} + +
+
+ 에러: + + {userInfoError ? "❌ 있음" : "✅ 없음"} + +
+
+
+ +
+ + + {isAvailable && ( + + )} +
+

+ 앱에서 로그인 후 웹뷰로 이동하면 유저 정보가 자동으로 로드됩니다 +

+
+ )} +
+
+ ); + } + + // 토큰이 있는데 여전히 사용자 정보 로딩 중 + if (userInfoLoading && (isLoggedIn || tokens)) { return (
-

로그인 상태를 확인하는 중...

+

사용자 정보를 불러오는 중...

); diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts index ca66975..3d35e93 100644 --- a/src/hooks/useAuth.ts +++ b/src/hooks/useAuth.ts @@ -27,9 +27,12 @@ export const useAuth = () => { } catch (error) { console.error("토큰 초기화 실패:", error); clearTokens(); - } finally { - setLoading(false); } + + // 초기화 실패 시 안전장치: 3초 후 강제로 로딩 해제 + setTimeout(() => { + setLoading(false); + }, 3000); }, [ setLoading, clearTokens, diff --git a/src/store/useAuthStore.ts b/src/store/useAuthStore.ts index d23d2e4..2cc6a48 100644 --- a/src/store/useAuthStore.ts +++ b/src/store/useAuthStore.ts @@ -32,28 +32,33 @@ export const useAuthStore = create()( // 로컬스토리지에서 accessToken 확인 및 자동 로그인 initializeFromLocalStorage: () => { - const accessToken = localStorage.getItem("accessToken"); - if (accessToken) { - const tokenObject = { - accessToken: accessToken, - refreshToken: "", - expiresIn: 3600, - tokenType: "Bearer", - }; - set({ - tokens: tokenObject, - isLoggedIn: true, - isLoading: false, - }); - // 토큰 생성 시간이 없으면 현재 시간으로 설정 - if (!localStorage.getItem("auth-storage-timestamp")) { - localStorage.setItem( - "auth-storage-timestamp", - Date.now().toString() - ); + try { + const accessToken = localStorage.getItem("accessToken"); + if (accessToken) { + const tokenObject = { + accessToken: accessToken, + refreshToken: "", + expiresIn: 3600, + tokenType: "Bearer", + }; + set({ + tokens: tokenObject, + isLoggedIn: true, + isLoading: false, + }); + // 토큰 생성 시간이 없으면 현재 시간으로 설정 + if (!localStorage.getItem("auth-storage-timestamp")) { + localStorage.setItem( + "auth-storage-timestamp", + Date.now().toString() + ); + } + } else { + set({ isLoading: false, isLoggedIn: false, tokens: null }); } - } else { - set({ isLoading: false }); + } catch (error) { + console.error('토큰 초기화 실패:', error); + set({ isLoading: false, isLoggedIn: false, tokens: null }); } }, @@ -80,6 +85,8 @@ export const useAuthStore = create()( onRehydrateStorage: () => (state) => { if (state) { state.setLoading(false); + // 초기 설치시 토큰 초기화 확실히 수행 + setTimeout(() => state.initializeFromLocalStorage(), 0); } }, }