From 21f48d0e2723e7decfd66b4da74b38776d5db0bb Mon Sep 17 00:00:00 2001 From: yoon Date: Tue, 4 Feb 2025 11:10:31 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=96=88?= =?UTF-8?q?=EC=9D=84=20=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8,=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EA=B0=80=EC=9E=85=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99X?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/router/index.js | 54 +++++++++++++++++++++++++++++++++----- src/stores/useAuthStore.js | 43 ++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 src/stores/useAuthStore.js diff --git a/src/router/index.js b/src/router/index.js index c72c9ad..3d06bf2 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,9 +1,12 @@ import { createRouter, createWebHistory } from 'vue-router' +import { useAuthStore } from '@s/useAuthStore'; + // 초기 렌더링 속도를 위해 지연 로딩 사용 const routes = [ { path: '/', + name: "Home", component: () => import('@v/MainView.vue'), // meta: { requiresAuth: true } }, @@ -38,18 +41,20 @@ const routes = [ }, { path: '/login', + name: 'Login', component: () => import('@v/user/TheLogin.vue'), - meta: { layout: 'NoLayout' }, + meta: { layout: 'NoLayout', requiresGuest: true }, + }, + { + path: '/register', + name: 'Register', + component: () => import('@v/user/TheRegister.vue'), + meta: { layout: 'NoLayout', requiresGuest: true }, }, { path: '/vacation', component: () => import('@v/vacation/VacationManagement.vue'), }, - { - path: '/register', - component: () => import('@v/user/TheRegister.vue'), - meta: { layout: 'NoLayout' }, - }, { path: '/voteboard', component: () => import('@v/voteboard/TheVoteBoard.vue'), @@ -80,4 +85,41 @@ const router = createRouter({ routes: routes, }) +router.beforeEach(async (to, from, next) => { + const authStore = useAuthStore(); + await authStore.checkAuthStatus(); // 로그인 상태 확인 + + if (to.meta.requiresAuth && !authStore.isAuthenticated) { + // 로그인이 필요한 페이지인데 로그인되지 않은 경우 → 로그인 페이지로 이동 + next({ name: 'Login' }); + } else if (to.meta.requiresGuest && authStore.isAuthenticated) { + // 비로그인 사용자만 접근 가능한 페이지인데 로그인된 경우 → 홈으로 이동 + next({ name: 'Home' }); + } else { + next(); + } +}); + + +router.beforeEach(async (to, from, next) => { + const authStore = useAuthStore() + + // 최초 앱 로드 시 인증 상태 체크 + await authStore.checkAuthStatus() + + // 현재 라우트에 인증이 필요한지 확인 + const requiresAuth = to.meta.requiresAuth === true + + if (requiresAuth && !authStore.isAuthenticated) { + // 인증되지 않은 사용자를 로그인 페이지로 리다이렉트 + // 원래 가려던 페이지를 쿼리 파라미터로 전달 + next({ + name: 'Login', + query: { redirect: to.fullPath } + }) + } else { + next() + } +}) + export default router diff --git a/src/stores/useAuthStore.js b/src/stores/useAuthStore.js new file mode 100644 index 0000000..b944993 --- /dev/null +++ b/src/stores/useAuthStore.js @@ -0,0 +1,43 @@ +import { ref, computed } from 'vue'; +import { defineStore } from 'pinia'; +import axios from "@api"; + +export const useAuthStore = defineStore('auth', () => { + const user = ref(null); + + // 로그인 여부 확인 + const isAuthenticated = computed(() => user.value !== null); + + // 로그인 상태 확인 + const checkAuthStatus = async () => { + const response = await axios.get('user/isLogin'); + if (response.data.status === "OK" && response.data.data) { + user.value = response.data.data; + } else { + user.value = null; + } + }; + + // 로그아웃 + const logout = async () => { + + const response = await axios.get('user/logout'); + + // 로그아웃 성공 시 사용자 상태 초기화 + if (response.data.status === "OK") { + user.value = null; + return true; + } else { + console.error("로그아웃 실패:", response.data.data); + return false; + } + + }; + + return { + user, + isAuthenticated, + checkAuthStatus, + logout + }; +});