diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3d86d64..c5f134d 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -5,6 +5,7 @@ import Header from '@/shared/components/header/Header'; import FooterWrapper from '@/shared/components/footer/FooterWrapper'; import ScrollTopBtnWrapper from '@/shared/components/scroll-top/ScrollTopBtnWrapper'; import KaKaoScript from './api/kakao/KaKaoScript'; +import IdleHandler from '@/domains/login/components/IdleHandler'; export const metadata: Metadata = { title: { default: 'SSOUL', template: 'SSOUL | %s' }, @@ -21,6 +22,7 @@ export default function RootLayout({
+
{children}
diff --git a/src/domains/login/components/IdleHandler.tsx b/src/domains/login/components/IdleHandler.tsx new file mode 100644 index 0000000..4edbf6c --- /dev/null +++ b/src/domains/login/components/IdleHandler.tsx @@ -0,0 +1,9 @@ +'use client'; + +import { useIdleLogout } from '../hook/useIdleLogout'; + +function IdleHandler() { + useIdleLogout(); + return null; +} +export default IdleHandler; diff --git a/src/domains/login/hook/useIdleLogout.ts b/src/domains/login/hook/useIdleLogout.ts new file mode 100644 index 0000000..c2cfd49 --- /dev/null +++ b/src/domains/login/hook/useIdleLogout.ts @@ -0,0 +1,40 @@ +'use client'; + +import { useCallback, useEffect, useRef } from 'react'; +import { useLogout } from './useLogout'; +import { useToast } from '@/shared/hook/useToast'; +import { useAuthStore } from '@/domains/shared/store/auth'; + +const IDLE_TIMEOUT = 4 * 60 * 60 * 1000; + +export const useIdleLogout = () => { + const handleLogout = useLogout(); + const timerRef = useRef(null); + const warningTimerRef = useRef(null); + const { toastInfo } = useToast(); + const { isLoggedIn } = useAuthStore(); + + const resetTimer = useCallback(() => { + if (!isLoggedIn) return; + if (timerRef.current) clearTimeout(timerRef.current); + if (warningTimerRef.current) clearTimeout(warningTimerRef.current); + + timerRef.current = setTimeout(() => { + toastInfo('5초 뒤 자동 로그아웃 예정 \n 움직이면 자동 로그아웃 취소됩니다.'); + warningTimerRef.current = setTimeout(() => handleLogout(), 5000); + }, IDLE_TIMEOUT); + }, [isLoggedIn, handleLogout, toastInfo]); + + useEffect(() => { + const events = ['mousemove', 'keydown', 'mousedown', 'touchstart']; + events.forEach((e) => window.addEventListener(e, resetTimer)); + + resetTimer(); + + return () => { + if (timerRef.current) clearTimeout(timerRef.current); + if (warningTimerRef.current) clearTimeout(warningTimerRef.current); + events.forEach((e) => window.removeEventListener(e, resetTimer)); + }; + }, [resetTimer]); +};