From 04116b9bfbab2aa80a2d6fa1798e692bb681bfac Mon Sep 17 00:00:00 2001
From: S-Gihun <89789115+S-Gihun@users.noreply.github.com>
Date: Fri, 21 Feb 2025 01:07:51 +0900
Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20feat:=20AuthWrapper=20=ED=86=B5?=
=?UTF-8?q?=ED=95=B4=20=EA=B6=8C=ED=95=9C=20=EC=97=86=EC=9D=B4=20=EB=8B=A4?=
=?UTF-8?q?=EB=A5=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A0=91=EA=B7=BC=20?=
=?UTF-8?q?=EC=A0=9C=ED=95=9C=20#96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/components/Auth/AuthWrapper.tsx | 30 +++++++++++
umc-master/src/router/routes.tsx | 54 ++++++++++++-------
2 files changed, 64 insertions(+), 20 deletions(-)
create mode 100644 umc-master/src/components/Auth/AuthWrapper.tsx
diff --git a/umc-master/src/components/Auth/AuthWrapper.tsx b/umc-master/src/components/Auth/AuthWrapper.tsx
new file mode 100644
index 0000000..933ab93
--- /dev/null
+++ b/umc-master/src/components/Auth/AuthWrapper.tsx
@@ -0,0 +1,30 @@
+import { useEffect } from 'react';
+import { useNavigate, useLocation } from 'react-router-dom';
+import { useTokenStore } from '@store/tokenStore';
+import RoutePaths from '@router/routePaths';
+
+interface AuthWrapperProps {
+ children: React.ReactNode;
+}
+
+const AuthWrapper = ({ children }: AuthWrapperProps) => {
+ const navigate = useNavigate();
+ const location = useLocation();
+ const { accessToken } = useTokenStore.getState();
+
+ useEffect(() => {
+ // 로그인 페이지가 아니고 토큰이 없는 경우 리다이렉트
+ if (!accessToken && location.pathname !== RoutePaths.LANDING) {
+ navigate(RoutePaths.LOGIN, { replace: true });
+ }
+ }, [accessToken, location.pathname, navigate]);
+
+ // 토큰이 없고 로그인 페이지가 아닌 경우 아무것도 렌더링하지 않음
+ if (!accessToken && location.pathname !== RoutePaths.LOGIN) {
+ return null;
+ }
+
+ return <>{children}>;
+};
+
+export default AuthWrapper;
diff --git a/umc-master/src/router/routes.tsx b/umc-master/src/router/routes.tsx
index d87d993..854b969 100644
--- a/umc-master/src/router/routes.tsx
+++ b/umc-master/src/router/routes.tsx
@@ -20,6 +20,39 @@ import ChatPage from '@pages/chat/ChatPage';
import ErrorPage from '@pages/error/ErrorPage';
import MyChallengePage from '@pages/mychallenge/MyChallenge';
import ChallengeDetailPage from '@pages/challenge/ChallengeDetailPage';
+import AuthWrapper from '@components/Auth/AuthWrapper';
+
+// 인증이 필요한 라우트들을 배열로 정의
+const protectedRoutes = [
+ { path: RoutePaths.MYPAGE, element: },
+ { path: RoutePaths.MAIN, element: },
+ { path: RoutePaths.SAVE_TIP, element: },
+ { path: RoutePaths.SEARCH, element: },
+ { path: RoutePaths.SAVE_TIP_DETAIL, element: },
+ { path: RoutePaths.CREATE_POST, element: },
+ { path: RoutePaths.COMMUNITY, element: },
+ { path: RoutePaths.MAGAZINE, element: },
+ { path: RoutePaths.MAGAZINE_DETAIL, element: },
+ { path: RoutePaths.CHALLENGE, element: },
+ { path: RoutePaths.MYCHALLENGE, element: },
+ { path: RoutePaths.CHALLENGE_DETAIL, element: },
+ { path: RoutePaths.CHAT, element: },
+];
+
+// 인증이 필요없는 public 라우트들
+const publicRoutes = [
+ { index: true, element: },
+ { path: RoutePaths.LOGIN, element: },
+ { path: RoutePaths.SIGNUP, element: },
+ { path: RoutePaths.FINDPRIVACY, element: },
+ { path: RoutePaths.KAKAO_CALLBACK, element: },
+];
+
+// protected 라우트들을 AuthWrapper로 감싸기
+const wrappedProtectedRoutes = protectedRoutes.map((route) => ({
+ ...route,
+ element: {route.element},
+}));
const router = createBrowserRouter([
{
@@ -28,26 +61,7 @@ const router = createBrowserRouter([
children: [
{
errorElement: ,
- children: [
- { index: true, element: },
- { path: RoutePaths.LOGIN, element: },
- { path: RoutePaths.SIGNUP, element: },
- { path: RoutePaths.FINDPRIVACY, element: },
- { path: RoutePaths.MYPAGE, element: },
- { path: RoutePaths.MAIN, element: },
- { path: RoutePaths.SEARCH, element: },
- { path: RoutePaths.SAVE_TIP, element: },
- { path: RoutePaths.SAVE_TIP_DETAIL, element: },
- { path: RoutePaths.CREATE_POST, element: },
- { path: RoutePaths.COMMUNITY, element: },
- { path: RoutePaths.MAGAZINE, element: },
- { path: RoutePaths.MAGAZINE_DETAIL, element: },
- { path: RoutePaths.KAKAO_CALLBACK, element: },
- { path: RoutePaths.CHALLENGE, element: },
- { path: RoutePaths.MYCHALLENGE, element: },
- { path: RoutePaths.CHALLENGE_DETAIL, element: },
- { path: RoutePaths.CHAT, element: },
- ],
+ children: [...publicRoutes, ...wrappedProtectedRoutes],
},
],
},
From 261c50f5fdc4be30c962a809b8bebee4e7760da1 Mon Sep 17 00:00:00 2001
From: S-Gihun <89789115+S-Gihun@users.noreply.github.com>
Date: Fri, 21 Feb 2025 01:08:42 +0900
Subject: [PATCH 2/3] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20=EC=8B=A4?=
=?UTF-8?q?=EC=A0=9C=20accessToken=20=EC=9C=BC=EB=A1=9C=20=EC=A0=91?=
=?UTF-8?q?=EA=B7=BC=20#96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
umc-master/src/apis/axios-instance.ts | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/umc-master/src/apis/axios-instance.ts b/umc-master/src/apis/axios-instance.ts
index 6afb7ac..5add23a 100644
--- a/umc-master/src/apis/axios-instance.ts
+++ b/umc-master/src/apis/axios-instance.ts
@@ -1,11 +1,12 @@
-import RoutePaths from '@router/routePaths';
import { useTokenStore } from '@store/tokenStore';
import axios, { AxiosInstance } from 'axios';
+const { accessToken } = useTokenStore.getState();
+
const axiosInstance: AxiosInstance = axios.create({
headers: {
accept: 'application/json',
- Authorization: `Bearer ${import.meta.env.VITE_ACCESS_TOKEN}`,
+ Authorization: `Bearer ${accessToken}`,
},
baseURL: import.meta.env.VITE_BASE_URL,
});
@@ -69,11 +70,6 @@ axiosInstance.interceptors.response.use(
console.error('토큰 갱신 실패:', refreshError);
useTokenStore.getState().clearTokens();
- // 로그인 페이지로 리다이렉트
- if (window.location.pathname !== RoutePaths.LOGIN) {
- window.location.href = RoutePaths.LOGIN;
- }
-
return Promise.reject(refreshError);
}
}
From 9c511be1fe32d6118fca26d00b9514cf8a37876b Mon Sep 17 00:00:00 2001
From: S-Gihun <89789115+S-Gihun@users.noreply.github.com>
Date: Fri, 21 Feb 2025 01:12:38 +0900
Subject: [PATCH 3/3] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20refreshTok?=
=?UTF-8?q?en=20Default=20=EA=B0=92=20null=20=EC=84=A4=EC=A0=95=20#96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
umc-master/src/store/tokenStore.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/umc-master/src/store/tokenStore.ts b/umc-master/src/store/tokenStore.ts
index 3f894cc..b06adaf 100644
--- a/umc-master/src/store/tokenStore.ts
+++ b/umc-master/src/store/tokenStore.ts
@@ -9,7 +9,7 @@ interface TokenStore {
export const useTokenStore = create((set) => ({
accessToken: null,
- refreshToken: `${import.meta.env.VITE_REFRESH_TOKEN}` /* 로그인 기능 완성 후 수정 예정임 */,
+ refreshToken: null /* 로그인 기능 완성 후 수정 예정임 */,
setTokens: (tokens) => {
// console.log('Setting Tokens:', tokens);
set(() => ({