ERP-node/frontend/contexts/AuthContext.tsx

129 lines
4.0 KiB
TypeScript
Raw Normal View History

2025-08-21 09:41:46 +09:00
"use client";
import React, { createContext, useContext, useEffect, useState } from "react";
import { useAuth } from "@/hooks/useAuth";
import { SessionManager, initSessionManager, cleanupSessionManager, formatTime } from "@/lib/sessionManager";
interface AuthContextType {
sessionManager: SessionManager | null;
showSessionWarning: boolean;
warningTime: number;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
interface AuthProviderProps {
children: React.ReactNode;
}
/**
*
* WebView,
*/
function isMobileEnvironment(): boolean {
if (typeof window === "undefined") return false;
const userAgent = navigator.userAgent.toLowerCase();
// 모바일 기기 감지
const isMobileDevice = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent);
// WebView 감지 (앱 내 브라우저)
const isWebView =
/wv/.test(userAgent) || // Android WebView
/webview/.test(userAgent) ||
(window as unknown as { webkit?: unknown }).webkit !== undefined || // iOS WKWebView
/fb_iab|fban|fbav/.test(userAgent) || // Facebook 앱 내 브라우저
/instagram/.test(userAgent) || // Instagram 앱 내 브라우저
/kakaotalk/.test(userAgent) || // 카카오톡 앱 내 브라우저
/naver/.test(userAgent); // 네이버 앱 내 브라우저
return isMobileDevice || isWebView;
}
2025-08-21 09:41:46 +09:00
/**
*
*
*/
export function AuthProvider({ children }: AuthProviderProps) {
const { isLoggedIn, logout } = useAuth();
const [sessionManager, setSessionManager] = useState<SessionManager | null>(null);
const [showSessionWarning, setShowSessionWarning] = useState(false);
const [warningTime, setWarningTime] = useState(0);
// 세션 매니저 초기화 및 정리
useEffect(() => {
if (isLoggedIn) {
// 모바일 환경 여부에 따라 타임아웃 시간 조정
const isMobile = isMobileEnvironment();
// 모바일: 24시간 (JWT 토큰 만료 시간과 동일), 데스크톱: 30분
const maxInactiveTime = isMobile ? 86400000 : 1800000;
// 모바일: 1시간 전 경고, 데스크톱: 5분 전 경고
const warningTimeConfig = isMobile ? 3600000 : 300000;
2025-08-21 09:41:46 +09:00
// 세션 매니저 초기화
const manager = initSessionManager(
{
checkInterval: 60000, // 1분마다 체크
warningTime: warningTimeConfig,
maxInactiveTime: maxInactiveTime,
2025-08-21 09:41:46 +09:00
},
{
onWarning: (remainingTime: number) => {
console.log(`세션 만료 경고: ${formatTime(remainingTime)} 남음`);
setWarningTime(remainingTime);
setShowSessionWarning(true);
},
onExpiry: () => {
console.log("세션이 만료되어 자동 로그아웃됩니다");
setShowSessionWarning(false);
logout();
},
onActivity: () => {
// 활동 감지 시 경고 숨김
if (showSessionWarning) {
setShowSessionWarning(false);
}
},
},
);
setSessionManager(manager);
manager.start();
return () => {
manager.stop();
cleanupSessionManager();
setSessionManager(null);
};
} else {
// 로그인되지 않은 경우 세션 매니저 정리
cleanupSessionManager();
setSessionManager(null);
setShowSessionWarning(false);
}
}, [isLoggedIn, logout, showSessionWarning]);
const contextValue: AuthContextType = {
sessionManager,
showSessionWarning,
warningTime,
};
return <AuthContext.Provider value={contextValue}>{children}</AuthContext.Provider>;
}
/**
*
*/
export function useAuthContext() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useAuthContext must be used within an AuthProvider");
}
return context;
}
export default AuthProvider;