From 3d94ee42425862868e3eff9a930a3a37f1442558 Mon Sep 17 00:00:00 2001 From: YermIm Date: Fri, 14 Aug 2026 02:17:34 +0900 Subject: [PATCH 1/4] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=9C=20=EC=9D=B4=EC=A0=84=20=EA=B3=84=EC=A0=95=20workspace?= =?UTF-8?q?=20=EC=83=81=ED=83=9C=20=EB=B0=8F=20=EC=BF=BC=EB=A6=AC=20?= =?UTF-8?q?=EC=BA=90=EC=8B=9C=20=EC=B4=88=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/auth/useAuth.ts | 7 +++++++ src/pages/auth/RedirectPage.tsx | 4 ++++ src/store/useWorkspaceStore.ts | 2 ++ 3 files changed, 13 insertions(+) diff --git a/src/hooks/auth/useAuth.ts b/src/hooks/auth/useAuth.ts index 10204a99..f2effb8d 100644 --- a/src/hooks/auth/useAuth.ts +++ b/src/hooks/auth/useAuth.ts @@ -1,3 +1,5 @@ +import { useQueryClient } from "@tanstack/react-query"; + import { useCoreMutation } from "@/hooks/customQuery"; import { @@ -11,15 +13,20 @@ import { verifySMS, } from "@/api/auth/auth"; import useAuthStore from "@/store/useAuthStore"; +import useWorkspaceStore from "@/store/useWorkspaceStore"; export const useAuth = () => { const { login: loginAction } = useAuthStore(); + const queryClient = useQueryClient(); const useLogin = useCoreMutation(login, { userOnSuccess: (response, vars) => { + queryClient.clear(); + useWorkspaceStore.getState().reset(); loginAction(vars.email, response.data.accessToken); }, }); + const useSignUp = useCoreMutation(signUp); const useSendCode = useCoreMutation(sendEmail); const useCheckCode = useCoreMutation(verifyEmail); diff --git a/src/pages/auth/RedirectPage.tsx b/src/pages/auth/RedirectPage.tsx index b9a7e41c..6671f560 100644 --- a/src/pages/auth/RedirectPage.tsx +++ b/src/pages/auth/RedirectPage.tsx @@ -8,7 +8,9 @@ import { getSafeReturnUrl, } from "@/utils/auth/returnUrl"; +import { queryClient } from "@/lib/queryClient"; import useAuthStore from "@/store/useAuthStore"; +import useWorkspaceStore from "@/store/useWorkspaceStore"; export default function RedirectPage() { const navigate = useNavigate(); @@ -37,6 +39,8 @@ export default function RedirectPage() { if (accessToken) { deleteCookie("access_token"); + queryClient.clear(); + useWorkspaceStore.getState().reset(); setAccessToken(accessToken); toast.success("소셜 로그인되었습니다."); diff --git a/src/store/useWorkspaceStore.ts b/src/store/useWorkspaceStore.ts index 8d8288f0..c5671389 100644 --- a/src/store/useWorkspaceStore.ts +++ b/src/store/useWorkspaceStore.ts @@ -7,6 +7,7 @@ interface IWorkspaceState { myRole: TMemberRole | null; setSelectedOrgId: (orgId: number) => void; setMyRole: (role: TMemberRole | null) => void; + reset: () => void; } const useWorkspaceStore = create((set) => ({ @@ -14,6 +15,7 @@ const useWorkspaceStore = create((set) => ({ myRole: null, setSelectedOrgId: (orgId) => set({ selectedOrgId: orgId }), setMyRole: (role) => set({ myRole: role }), + reset: () => set({ selectedOrgId: null, myRole: null }), })); export default useWorkspaceStore; From 751b3b10a76c125d7f85514240016a581a96f42b Mon Sep 17 00:00:00 2001 From: YermIm Date: Fri, 14 Aug 2026 02:35:20 +0900 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20MainLayout=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20sel?= =?UTF-8?q?ectedOrgId=20=EC=9E=AC=EC=84=A0=ED=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/main/MainLayout.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/layout/main/MainLayout.tsx b/src/layout/main/MainLayout.tsx index 5b850984..57d5c374 100644 --- a/src/layout/main/MainLayout.tsx +++ b/src/layout/main/MainLayout.tsx @@ -68,19 +68,22 @@ export default function MainLayout() { useEffect(() => { if (!workspaces?.length || !savedWorkspaceQuery.isFetched) return; - // orgId는 있는데 myRole만 null/불일치인 경우(새로고침 등) 역할 동기화 + // 현재 유저 목록에 있는 orgId만 유지 (+ role 동기화) + // 목록에 없으면 return하지 않고 아래 saved/current 초기화로 계속 if (selectedOrgId !== null) { const workspace = workspaces.find((w) => w.orgId === selectedOrgId); - if (workspace && myRole !== workspace.myRole) { - setMyRole(workspace.myRole); + if (workspace) { + if (myRole !== workspace.myRole) { + setMyRole(workspace.myRole); + } + return; } - return; } const savedId = savedData?.orgId; const isExist = workspaces.some((w) => w.orgId === savedId); - // 1. 현재 워크스페이스 조회 API 데이터 (저장된 워크스페이스가 있는 경우) + // 1. 저장된 워크스페이스가 현재 유저 목록에 있으면 선택 if (savedId !== undefined && isExist) { const workspace = workspaces.find((w) => w.orgId === savedId); setSelectedOrgId(savedId); From 345e3bea59f3abf729c00e7a90b07b3f8bba0824 Mon Sep 17 00:00:00 2001 From: YermIm Date: Fri, 14 Aug 2026 02:47:13 +0900 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83?= =?UTF-8?q?=20=EC=8B=9C=20workspace=20=EC=B4=88=EA=B8=B0=ED=99=94=20?= =?UTF-8?q?=EB=B0=8F=20hard=20redirect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/auth/useDeleteMyAccount.ts | 6 +++--- src/hooks/auth/useLogout.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hooks/auth/useDeleteMyAccount.ts b/src/hooks/auth/useDeleteMyAccount.ts index 555a643c..75b5118d 100644 --- a/src/hooks/auth/useDeleteMyAccount.ts +++ b/src/hooks/auth/useDeleteMyAccount.ts @@ -1,4 +1,3 @@ -import { useNavigate } from "react-router-dom"; import { useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; @@ -8,9 +7,9 @@ import { useCoreMutation } from "@/hooks/customQuery"; import { deleteMyAccount } from "@/api/auth/auth"; import useAuthStore from "@/store/useAuthStore"; +import useWorkspaceStore from "@/store/useWorkspaceStore"; export function useDeleteMyAccount() { - const nav = useNavigate(); const queryClient = useQueryClient(); const logout = useAuthStore((s) => s.logout); @@ -20,8 +19,9 @@ export function useDeleteMyAccount() { "회원 탈퇴가 완료되었습니다. 30일 후 계정이 완전히 삭제됩니다", ); queryClient.clear(); + useWorkspaceStore.getState().reset(); logout(); - nav("/", { replace: true }); + window.location.replace("/"); }, userOnError: (error) => { const apiError = error as IApiErrorResponse; diff --git a/src/hooks/auth/useLogout.ts b/src/hooks/auth/useLogout.ts index aa58c752..6236b153 100644 --- a/src/hooks/auth/useLogout.ts +++ b/src/hooks/auth/useLogout.ts @@ -1,4 +1,3 @@ -import { useNavigate } from "react-router-dom"; import { useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; @@ -8,9 +7,9 @@ import { useCoreMutation } from "@/hooks/customQuery"; import { postLogout } from "@/api/auth/auth"; import useAuthStore from "@/store/useAuthStore"; +import useWorkspaceStore from "@/store/useWorkspaceStore"; export function useLogout() { - const nav = useNavigate(); const logout = useAuthStore((s) => s.logout); const queryClient = useQueryClient(); @@ -18,8 +17,9 @@ export function useLogout() { userOnSuccess: () => { toast.success("로그아웃이 완료되었습니다"); queryClient.clear(); + useWorkspaceStore.getState().reset(); logout(); - nav("/", { replace: true }); + window.location.replace("/"); }, userOnError: (error) => { const apiError = error as IApiErrorResponse; From bc9a6f0aea71bedde703df11bd2b7ec67584cb14 Mon Sep 17 00:00:00 2001 From: YermIm Date: Fri, 14 Aug 2026 13:04:24 +0900 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=EB=B9=88=20=EC=9B=8C=ED=81=AC?= =?UTF-8?q?=EC=8A=A4=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EB=AA=A9=EB=A1=9D?= =?UTF-8?q?=EC=97=90=EC=84=9C=20selectedOrgId=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/main/MainLayout.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/layout/main/MainLayout.tsx b/src/layout/main/MainLayout.tsx index 57d5c374..d420afb2 100644 --- a/src/layout/main/MainLayout.tsx +++ b/src/layout/main/MainLayout.tsx @@ -44,6 +44,7 @@ export default function MainLayout() { const setSelectedOrgId = useWorkspaceStore((s) => s.setSelectedOrgId); const setMyRole = useWorkspaceStore((s) => s.setMyRole); + const resetWorkspace = useWorkspaceStore((s) => s.reset); const myRole = useWorkspaceStore((s) => s.myRole); const savedWorkspaceQuery = useCoreQuery( @@ -66,7 +67,15 @@ export default function MainLayout() { ); useEffect(() => { - if (!workspaces?.length || !savedWorkspaceQuery.isFetched) return; + // undefined: 로딩 중 / []: 워크스페이스 없음(유효한 결과) + if (!workspaces || !savedWorkspaceQuery.isFetched) return; + + if (workspaces.length === 0) { + if (selectedOrgId !== null || myRole !== null) { + resetWorkspace(); + } + return; + } // 현재 유저 목록에 있는 orgId만 유지 (+ role 동기화) // 목록에 없으면 return하지 않고 아래 saved/current 초기화로 계속 @@ -102,6 +111,7 @@ export default function MainLayout() { savedData, setSelectedOrgId, setMyRole, + resetWorkspace, selectedOrgId, myRole, ]);