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]);
+};