From af30a175d4bb990519577363e17679c717b7ce2f Mon Sep 17 00:00:00 2001 From: yoonc01 Date: Sun, 14 Jun 2026 23:13:48 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EC=BB=A4=EB=AE=A4=EB=8B=88?= =?UTF-8?q?=ED=8B=B0=20=EA=B8=80=EC=93=B0=EA=B8=B0=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EB=A6=AC=EB=8B=A4=EC=9D=B4=EB=A0=89=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/apis/Auth/api.ts | 4 ++ apps/web/src/apis/Auth/postAppleAuth.ts | 9 +-- apps/web/src/apis/Auth/postEmailLogin.ts | 7 +- apps/web/src/apis/Auth/postKakaoAuth.ts | 9 +-- .../[boardCode]/CommunityPageContent.tsx | 16 ++++- .../community/[boardCode]/create/PostForm.tsx | 22 ++++++ apps/web/src/app/login/LoginContent.tsx | 19 ++++-- .../apple/callback/AppleLoginCallbackPage.tsx | 4 +- .../kakao/callback/KakaoLoginCallbackPage.tsx | 5 +- apps/web/src/app/login/page.tsx | 5 +- .../src/app/sign-up/email/EmailSignUpForm.tsx | 7 +- apps/web/src/app/sign-up/email/page.tsx | 5 +- .../components/login/signup/SignupSurvey.tsx | 8 ++- apps/web/src/utils/authRedirect.ts | 68 +++++++++++++++++++ apps/web/src/utils/authUtils.ts | 18 ++++- 15 files changed, 178 insertions(+), 28 deletions(-) create mode 100644 apps/web/src/utils/authRedirect.ts diff --git a/apps/web/src/apis/Auth/api.ts b/apps/web/src/apis/Auth/api.ts index 3f04e115..b42edbd3 100644 --- a/apps/web/src/apis/Auth/api.ts +++ b/apps/web/src/apis/Auth/api.ts @@ -41,6 +41,10 @@ export interface EmailLoginRequest { password: string; } +export type AuthRedirectOptions = { + redirectPath?: string; +}; + export interface EmailVerificationResponse { signUpToken: string; } diff --git a/apps/web/src/apis/Auth/postAppleAuth.ts b/apps/web/src/apis/Auth/postAppleAuth.ts index dc024c39..1259ed44 100644 --- a/apps/web/src/apis/Auth/postAppleAuth.ts +++ b/apps/web/src/apis/Auth/postAppleAuth.ts @@ -4,12 +4,13 @@ import type { AxiosError } from "axios"; import { useRouter } from "next/navigation"; import { showIconToast } from "@/lib/toast/showIconToast"; import useAuthStore from "@/lib/zustand/useAuthStore"; -import { type AppleAuthRequest, type AppleAuthResponse, authApi } from "./api"; +import { buildSignUpPath, getCommunityRedirectOrFallback } from "@/utils/authRedirect"; +import { type AppleAuthRequest, type AppleAuthResponse, type AuthRedirectOptions, authApi } from "./api"; /** * @description 애플 로그인을 위한 useMutation 커스텀 훅 */ -const usePostAppleAuth = () => { +const usePostAppleAuth = ({ redirectPath }: AuthRedirectOptions = {}) => { const router = useRouter(); return useMutation({ @@ -23,11 +24,11 @@ const usePostAppleAuth = () => { showIconToast("logo", "로그인에 성공했습니다."); setTimeout(() => { - router.push("/"); + router.push(getCommunityRedirectOrFallback(redirectPath)); }, 100); } else { // 새로운 회원일 시 - 회원가입 페이지로 이동 - router.push(`/sign-up?token=${data.signUpToken}`); + router.push(buildSignUpPath({ signUpToken: data.signUpToken, redirectPath })); } }, onError: () => { diff --git a/apps/web/src/apis/Auth/postEmailLogin.ts b/apps/web/src/apis/Auth/postEmailLogin.ts index 8d1317bb..d8e53c14 100644 --- a/apps/web/src/apis/Auth/postEmailLogin.ts +++ b/apps/web/src/apis/Auth/postEmailLogin.ts @@ -4,12 +4,13 @@ import type { AxiosError } from "axios"; import { useRouter } from "next/navigation"; import { showIconToast } from "@/lib/toast/showIconToast"; import useAuthStore from "@/lib/zustand/useAuthStore"; -import { authApi, type EmailLoginRequest, type EmailLoginResponse } from "./api"; +import { getCommunityRedirectOrFallback } from "@/utils/authRedirect"; +import { type AuthRedirectOptions, authApi, type EmailLoginRequest, type EmailLoginResponse } from "./api"; /** * @description 이메일 로그인을 위한 useMutation 커스텀 훅 */ -const usePostEmailAuth = () => { +const usePostEmailAuth = ({ redirectPath }: AuthRedirectOptions = {}) => { const { setAccessToken } = useAuthStore(); const router = useRouter(); @@ -27,7 +28,7 @@ const usePostEmailAuth = () => { // Zustand persist middleware가 localStorage에 저장할 시간을 보장 // 토큰 저장 후 리다이렉트하여 타이밍 이슈 방지 setTimeout(() => { - router.push("/"); + router.push(getCommunityRedirectOrFallback(redirectPath)); }, 100); }, }); diff --git a/apps/web/src/apis/Auth/postKakaoAuth.ts b/apps/web/src/apis/Auth/postKakaoAuth.ts index f8671416..05f5916a 100644 --- a/apps/web/src/apis/Auth/postKakaoAuth.ts +++ b/apps/web/src/apis/Auth/postKakaoAuth.ts @@ -4,12 +4,13 @@ import type { AxiosError } from "axios"; import { useRouter } from "next/navigation"; import { showIconToast } from "@/lib/toast/showIconToast"; import useAuthStore from "@/lib/zustand/useAuthStore"; -import { authApi, type KakaoAuthRequest, type KakaoAuthResponse } from "./api"; +import { buildSignUpPath, getCommunityRedirectOrFallback } from "@/utils/authRedirect"; +import { type AuthRedirectOptions, authApi, type KakaoAuthRequest, type KakaoAuthResponse } from "./api"; /** * @description 카카오 로그인을 위한 useMutation 커스텀 훅 */ -const usePostKakaoAuth = () => { +const usePostKakaoAuth = ({ redirectPath }: AuthRedirectOptions = {}) => { const { setAccessToken } = useAuthStore(); const router = useRouter(); @@ -23,11 +24,11 @@ const usePostKakaoAuth = () => { showIconToast("logo", "로그인에 성공했습니다."); setTimeout(() => { - router.push("/"); + router.push(getCommunityRedirectOrFallback(redirectPath)); }, 100); } else { // 새로운 회원일 시 - 회원가입 페이지로 이동 - router.push(`/sign-up?token=${data.signUpToken}`); + router.push(buildSignUpPath({ signUpToken: data.signUpToken, redirectPath })); } }, onError: () => { diff --git a/apps/web/src/app/community/[boardCode]/CommunityPageContent.tsx b/apps/web/src/app/community/[boardCode]/CommunityPageContent.tsx index 9d741f93..0243763c 100644 --- a/apps/web/src/app/community/[boardCode]/CommunityPageContent.tsx +++ b/apps/web/src/app/community/[boardCode]/CommunityPageContent.tsx @@ -6,7 +6,9 @@ import { useGetPostList } from "@/apis/community"; import { COMMUNITY_INITIAL_CATEGORY } from "@/apis/community/postListQuery"; import ButtonTab from "@/components/ui/ButtonTab"; import { COMMUNITY_BOARDS, COMMUNITY_CATEGORIES } from "@/constants/community"; +import useAuthStore from "@/lib/zustand/useAuthStore"; import useReportedPostsStore from "@/lib/zustand/useReportedPostsStore"; +import { buildLoginPathWithRedirect } from "@/utils/authRedirect"; import { CommunityPostListSkeleton } from "./CommunityPageSkeleton"; import CommunityRegionSelector from "./CommunityRegionSelector"; import PostCards from "./PostCards"; @@ -22,6 +24,10 @@ const CommunityPageContent = ({ boardCode }: CommunityPageContentProps) => { const reportedPostIds = useReportedPostsStore((state) => state.reportedPostIds); const blockedUserIds = useReportedPostsStore((state) => state.blockedUserIds); const blockedPostIds = useReportedPostsStore((state) => state.blockedPostIds); + const accessToken = useAuthStore((state) => state.accessToken); + const isAuthenticated = useAuthStore((state) => state.isAuthenticated); + const isInitialized = useAuthStore((state) => state.isInitialized); + const refreshStatus = useAuthStore((state) => state.refreshStatus); const { data: posts = [], isPending } = useGetPostList({ boardCode, @@ -57,7 +63,15 @@ const CommunityPageContent = ({ boardCode }: CommunityPageContentProps) => { }; const postWriteHandler = () => { - router.push(`/community/${boardCode}/create`); + const createPath = `/community/${boardCode}/create`; + + if (!isInitialized || refreshStatus === "refreshing") { + return; + } + + const nextPath = isAuthenticated && accessToken ? createPath : buildLoginPathWithRedirect(createPath); + + router.push(nextPath); }; const getBoardNameKo = (code: string) => { diff --git a/apps/web/src/app/community/[boardCode]/create/PostForm.tsx b/apps/web/src/app/community/[boardCode]/create/PostForm.tsx index e1232d2c..977e3e4c 100644 --- a/apps/web/src/app/community/[boardCode]/create/PostForm.tsx +++ b/apps/web/src/app/community/[boardCode]/create/PostForm.tsx @@ -5,8 +5,11 @@ import { useEffect, useRef, useState } from "react"; import { useCreatePost } from "@/apis/community"; import useCommunityImageUpload from "@/app/community/_hooks/useCommunityImageUpload"; import TopDetailNavigation from "@/components/layout/TopDetailNavigation"; +import CloudSpinnerPage from "@/components/ui/CloudSpinnerPage"; import { showIconToast } from "@/lib/toast/showIconToast"; +import useAuthStore from "@/lib/zustand/useAuthStore"; import { IconImage, IconPostCheckboxFilled, IconPostCheckboxOutlined } from "@/public/svgs"; +import { buildLoginPathWithRedirect } from "@/utils/authRedirect"; type PostFormProps = { boardCode: string; @@ -18,6 +21,10 @@ const PostForm = ({ boardCode }: PostFormProps) => { const [content, setContent] = useState(""); const router = useRouter(); const [isQuestion, setIsQuestion] = useState(false); + const accessToken = useAuthStore((state) => state.accessToken); + const isAuthenticated = useAuthStore((state) => state.isAuthenticated); + const isInitialized = useAuthStore((state) => state.isInitialized); + const refreshStatus = useAuthStore((state) => state.refreshStatus); const { maxImages, imageUploadRef, @@ -34,6 +41,17 @@ const PostForm = ({ boardCode }: PostFormProps) => { } = useCommunityImageUpload(); const createPostMutation = useCreatePost(); + const createPath = `/community/${boardCode}/create`; + + useEffect(() => { + if (!isInitialized || refreshStatus === "refreshing") { + return; + } + + if (!isAuthenticated || !accessToken) { + router.replace(buildLoginPathWithRedirect(createPath)); + } + }, [accessToken, createPath, isAuthenticated, isInitialized, refreshStatus, router]); useEffect(() => { const textarea = textareaRef.current; @@ -58,6 +76,10 @@ const PostForm = ({ boardCode }: PostFormProps) => { return () => {}; }, []); + if (!isInitialized || refreshStatus === "refreshing" || !isAuthenticated || !accessToken) { + return ; + } + const submitPost = async () => { const titleValue = titleRef.current?.querySelector("textarea")?.value.trim() || ""; const trimmedContent = content.trim(); diff --git a/apps/web/src/app/login/LoginContent.tsx b/apps/web/src/app/login/LoginContent.tsx index 4a8d1493..928fca07 100644 --- a/apps/web/src/app/login/LoginContent.tsx +++ b/apps/web/src/app/login/LoginContent.tsx @@ -2,12 +2,17 @@ import { zodResolver } from "@hookform/resolvers/zod"; import Link from "next/link"; -import { useRouter } from "next/navigation"; +import { useRouter, useSearchParams } from "next/navigation"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { usePostEmailAuth } from "@/apis/Auth"; import { IconSolidConnectionFullBlackLogo } from "@/public/svgs"; import { IconAppleLogo, IconEmailIcon, IconKakaoLogo } from "@/public/svgs/auth"; +import { + AUTH_REDIRECT_PARAM, + buildSignUpEmailPathWithRedirect, + getSafeCommunityRedirectPath, +} from "@/utils/authRedirect"; import { appleLogin, kakaoLogin } from "@/utils/authUtils"; import useInputHandler from "./_hooks/useInputHandler"; @@ -21,8 +26,10 @@ type LoginFormData = z.infer; const LoginContent = () => { const router = useRouter(); + const searchParams = useSearchParams(); + const redirectPath = getSafeCommunityRedirectPath(searchParams?.get(AUTH_REDIRECT_PARAM)) ?? undefined; - const { mutate: postEmailAuth, isPending } = usePostEmailAuth(); + const { mutate: postEmailAuth, isPending } = usePostEmailAuth({ redirectPath }); const { showPasswordField, handleEmailChange } = useInputHandler(); const { @@ -38,7 +45,7 @@ const LoginContent = () => { }); const onSubmit = async (data: LoginFormData) => { - postEmailAuth(data, {}); + postEmailAuth(data); }; const handleKeyDown = (e: React.KeyboardEvent) => { @@ -110,7 +117,7 @@ const LoginContent = () => {
); }; diff --git a/apps/web/src/app/sign-up/email/EmailSignUpForm.tsx b/apps/web/src/app/sign-up/email/EmailSignUpForm.tsx index f607753c..373c8af0 100644 --- a/apps/web/src/app/sign-up/email/EmailSignUpForm.tsx +++ b/apps/web/src/app/sign-up/email/EmailSignUpForm.tsx @@ -1,6 +1,6 @@ "use client"; -import { useRouter } from "next/navigation"; +import { useRouter, useSearchParams } from "next/navigation"; import { useEffect, useState } from "react"; import { usePostEmailSignUp } from "@/apis/Auth"; import BlockBtn from "@/components/button/BlockBtn"; @@ -9,9 +9,12 @@ import { Label } from "@/components/ui/Label"; import { Progress } from "@/components/ui/Progress"; import { showIconToast } from "@/lib/toast/showIconToast"; import { IconCheckBlue, IconExpRed, IconEyeOff, IconEyeOn } from "@/public/svgs/ui"; +import { AUTH_REDIRECT_PARAM, buildSignUpPath, getSafeCommunityRedirectPath } from "@/utils/authRedirect"; const EmailSignUpForm = () => { const router = useRouter(); + const searchParams = useSearchParams(); + const redirectPath = getSafeCommunityRedirectPath(searchParams?.get(AUTH_REDIRECT_PARAM)) ?? undefined; const [currentStep, setCurrentStep] = useState(0); const [email, setEmail] = useState(""); const [showPassword, setShowPassword] = useState(false); @@ -69,7 +72,7 @@ const EmailSignUpForm = () => { { email, password }, { onSuccess: (data) => { - router.push(`/sign-up?token=${data.signUpToken}`); + router.push(buildSignUpPath({ signUpToken: data.signUpToken, redirectPath })); }, }, ); diff --git a/apps/web/src/app/sign-up/email/page.tsx b/apps/web/src/app/sign-up/email/page.tsx index 6cf59550..a218765b 100644 --- a/apps/web/src/app/sign-up/email/page.tsx +++ b/apps/web/src/app/sign-up/email/page.tsx @@ -1,4 +1,5 @@ import type { Metadata } from "next"; +import { Suspense } from "react"; import TopDetailNavigation from "@/components/layout/TopDetailNavigation"; import { NO_INDEX_ROBOTS } from "@/utils/seo"; @@ -15,7 +16,9 @@ const EmailSignUpPage = () => { <>
- + Loading...
}> + +
); diff --git a/apps/web/src/components/login/signup/SignupSurvey.tsx b/apps/web/src/components/login/signup/SignupSurvey.tsx index 423ea611..9f7c4730 100644 --- a/apps/web/src/components/login/signup/SignupSurvey.tsx +++ b/apps/web/src/components/login/signup/SignupSurvey.tsx @@ -10,6 +10,11 @@ import useAuthStore from "@/lib/zustand/useAuthStore"; import type { PreparationStatus, SignUpRequest } from "@/types/auth"; import type { RegionKo } from "@/types/university"; +import { + AUTH_REDIRECT_PARAM, + getCommunityRedirectOrFallback, + getSafeCommunityRedirectPath, +} from "@/utils/authRedirect"; import SignupPolicyScreen from "./SignupPolicyScreen"; import SignupPrepareScreen from "./SignupPrepareScreen"; import SignupProfileScreen from "./SignupProfileScreen"; @@ -26,6 +31,7 @@ const SignupSurvey = ({ baseNickname, baseEmail, baseProfileImageUrl }: SignupSu const searchParams = useSearchParams(); const signUpToken = searchParams?.get("token"); + const redirectPath = getSafeCommunityRedirectPath(searchParams?.get(AUTH_REDIRECT_PARAM)) ?? undefined; if (!signUpToken) { router.push("/login"); } @@ -85,7 +91,7 @@ const SignupSurvey = ({ baseNickname, baseEmail, baseProfileImageUrl }: SignupSu showIconToast("logo", "회원가입이 완료되었습니다."); setTimeout(() => { - router.push("/"); + router.push(getCommunityRedirectOrFallback(redirectPath)); }, 100); }, }); diff --git a/apps/web/src/utils/authRedirect.ts b/apps/web/src/utils/authRedirect.ts new file mode 100644 index 00000000..f7e9476e --- /dev/null +++ b/apps/web/src/utils/authRedirect.ts @@ -0,0 +1,68 @@ +export const AUTH_REDIRECT_PARAM = "redirect"; + +const FALLBACK_REDIRECT_PATH = "/"; +const COMMUNITY_PATH_PREFIX = "/community/"; + +export const getSafeCommunityRedirectPath = (redirect: string | null | undefined): string | null => { + if (!redirect) { + return null; + } + + try { + const origin = typeof window === "undefined" ? "https://solid-connection.com" : window.location.origin; + const url = new URL(redirect, origin); + + if (url.origin !== origin) { + return null; + } + + if (!url.pathname.startsWith(COMMUNITY_PATH_PREFIX)) { + return null; + } + + return `${url.pathname}${url.search}${url.hash}`; + } catch { + return null; + } +}; + +export const getCommunityRedirectOrFallback = (redirect: string | null | undefined): string => { + return getSafeCommunityRedirectPath(redirect) ?? FALLBACK_REDIRECT_PATH; +}; + +export const buildLoginPathWithRedirect = (redirectPath: string): string => { + const safeRedirectPath = getSafeCommunityRedirectPath(redirectPath); + + if (!safeRedirectPath) { + return "/login"; + } + + return `/login?${AUTH_REDIRECT_PARAM}=${encodeURIComponent(safeRedirectPath)}`; +}; + +export const buildSignUpEmailPathWithRedirect = (redirectPath: string | null | undefined): string => { + const safeRedirectPath = getSafeCommunityRedirectPath(redirectPath); + + if (!safeRedirectPath) { + return "/sign-up/email"; + } + + return `/sign-up/email?${AUTH_REDIRECT_PARAM}=${encodeURIComponent(safeRedirectPath)}`; +}; + +export const buildSignUpPath = ({ + signUpToken, + redirectPath, +}: { + signUpToken: string; + redirectPath?: string | null; +}): string => { + const params = new URLSearchParams({ token: signUpToken }); + const safeRedirectPath = getSafeCommunityRedirectPath(redirectPath); + + if (safeRedirectPath) { + params.set(AUTH_REDIRECT_PARAM, safeRedirectPath); + } + + return `/sign-up?${params.toString()}`; +}; diff --git a/apps/web/src/utils/authUtils.ts b/apps/web/src/utils/authUtils.ts index 4dfe58ac..c98ad1ec 100644 --- a/apps/web/src/utils/authUtils.ts +++ b/apps/web/src/utils/authUtils.ts @@ -1,5 +1,6 @@ import { showIconToast } from "@/lib/toast/showIconToast"; import type { appleOAuth2CodeResponse } from "@/types/auth"; +import { AUTH_REDIRECT_PARAM, getSafeCommunityRedirectPath } from "./authRedirect"; export const authProviderName = (provider: "KAKAO" | "APPLE" | "EMAIL"): string => { if (provider === "KAKAO") { @@ -13,22 +14,27 @@ export const authProviderName = (provider: "KAKAO" | "APPLE" | "EMAIL"): string } }; -export const kakaoLogin = () => { +export const kakaoLogin = (redirectPath?: string) => { if (window.Kakao?.Auth) { + const safeRedirectPath = getSafeCommunityRedirectPath(redirectPath); + window.Kakao.Auth.authorize({ redirectUri: `${process.env.NEXT_PUBLIC_WEB_URL}/login/kakao/callback`, + ...(safeRedirectPath ? { state: safeRedirectPath } : {}), }); } else { showIconToast("logo", "Kakao SDK를 불러오는 중입니다. 잠시 후 다시 시도해주세요."); } }; -export const appleLogin = async () => { +export const appleLogin = async (redirectPath?: string) => { if (!window.AppleID || !window.AppleID.auth) { showIconToast("logo", "Apple SDK를 불러오는 중입니다. 잠시 후 다시 시도해주세요."); return; } + const safeRedirectPath = getSafeCommunityRedirectPath(redirectPath); + window.AppleID.auth.init({ clientId: process.env.NEXT_PUBLIC_APPLE_CLIENT_ID, scope: process.env.NEXT_PUBLIC_APPLE_SCOPE, @@ -39,7 +45,13 @@ export const appleLogin = async () => { try { const res = (await window.AppleID.auth.signIn()) as appleOAuth2CodeResponse; if (res.authorization) { - window.location.href = `/login/apple/callback?code=${encodeURIComponent(res.authorization.code)}`; + const params = new URLSearchParams({ code: res.authorization.code }); + + if (safeRedirectPath) { + params.set(AUTH_REDIRECT_PARAM, safeRedirectPath); + } + + window.location.href = `/login/apple/callback?${params.toString()}`; } } catch (error) { // Log error for developers From 992811bea31a6de2cc60dfe2bea2703764f4bdb1 Mon Sep 17 00:00:00 2001 From: yoonc01 Date: Sun, 14 Jun 2026 23:27:52 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20=EC=9D=B8=EC=A6=9D=20=EB=A1=9C?= =?UTF-8?q?=EB=94=A9=20UI=EB=A5=BC=20=EC=8A=A4=ED=94=BC=EB=84=88=EB=A1=9C?= =?UTF-8?q?=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/app/login/apple/callback/page.tsx | 3 ++- apps/web/src/app/login/kakao/callback/page.tsx | 3 ++- apps/web/src/app/login/page.tsx | 3 ++- apps/web/src/app/sign-up/email/page.tsx | 3 ++- apps/web/src/app/sign-up/page.tsx | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/web/src/app/login/apple/callback/page.tsx b/apps/web/src/app/login/apple/callback/page.tsx index 448fb8ee..6337d6a0 100644 --- a/apps/web/src/app/login/apple/callback/page.tsx +++ b/apps/web/src/app/login/apple/callback/page.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import { Suspense } from "react"; +import CloudSpinnerPage from "@/components/ui/CloudSpinnerPage"; import { NO_INDEX_ROBOTS } from "@/utils/seo"; import AppleLoginCallbackPage from "./AppleLoginCallbackPage"; @@ -11,7 +12,7 @@ export const metadata: Metadata = { const Page = () => (
- Loading...
}> + }> diff --git a/apps/web/src/app/login/kakao/callback/page.tsx b/apps/web/src/app/login/kakao/callback/page.tsx index d56e8325..300cc3c3 100644 --- a/apps/web/src/app/login/kakao/callback/page.tsx +++ b/apps/web/src/app/login/kakao/callback/page.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import { Suspense } from "react"; +import CloudSpinnerPage from "@/components/ui/CloudSpinnerPage"; import { NO_INDEX_ROBOTS } from "@/utils/seo"; import KakaoLoginCallbackPage from "./KakaoLoginCallbackPage"; @@ -11,7 +12,7 @@ export const metadata: Metadata = { const Page = () => (
- Loading...
}> + }> diff --git a/apps/web/src/app/login/page.tsx b/apps/web/src/app/login/page.tsx index 28ada00d..cb0d7b49 100644 --- a/apps/web/src/app/login/page.tsx +++ b/apps/web/src/app/login/page.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next"; import { Suspense } from "react"; +import CloudSpinnerPage from "@/components/ui/CloudSpinnerPage"; import KakaoScriptLoader from "@/lib/ScriptLoader/KakaoScriptLoader"; import { NO_INDEX_ROBOTS } from "@/utils/seo"; import LoginContent from "./LoginContent"; @@ -13,7 +14,7 @@ const LoginPage = () => { return (
- Loading...
}> + }> diff --git a/apps/web/src/app/sign-up/email/page.tsx b/apps/web/src/app/sign-up/email/page.tsx index a218765b..708a19d8 100644 --- a/apps/web/src/app/sign-up/email/page.tsx +++ b/apps/web/src/app/sign-up/email/page.tsx @@ -2,6 +2,7 @@ import type { Metadata } from "next"; import { Suspense } from "react"; import TopDetailNavigation from "@/components/layout/TopDetailNavigation"; +import CloudSpinnerPage from "@/components/ui/CloudSpinnerPage"; import { NO_INDEX_ROBOTS } from "@/utils/seo"; import EmailSignUpForm from "./EmailSignUpForm"; @@ -16,7 +17,7 @@ const EmailSignUpPage = () => { <>
- Loading...
}> + }> diff --git a/apps/web/src/app/sign-up/page.tsx b/apps/web/src/app/sign-up/page.tsx index 3c9933af..aa7295f0 100644 --- a/apps/web/src/app/sign-up/page.tsx +++ b/apps/web/src/app/sign-up/page.tsx @@ -3,6 +3,7 @@ import { Suspense } from "react"; import TopDetailNavigation from "@/components/layout/TopDetailNavigation"; import SignupSurvey from "@/components/login/signup/SignupSurvey"; +import CloudSpinnerPage from "@/components/ui/CloudSpinnerPage"; import { NO_INDEX_ROBOTS } from "@/utils/seo"; export const metadata: Metadata = { @@ -15,7 +16,7 @@ const SignUpPage = () => { <>
- Loading...
}> + }> From 72edffd4f2a19814b87527825b06a8ebf56405d9 Mon Sep 17 00:00:00 2001 From: yoonc01 Date: Mon, 15 Jun 2026 22:56:43 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85?= =?UTF-8?q?=20=ED=86=A0=ED=81=B0=20=EB=88=84=EB=9D=BD=20=EB=A6=AC=EB=8B=A4?= =?UTF-8?q?=EC=9D=B4=EB=A0=89=ED=8A=B8=20=EC=B2=98=EB=A6=AC=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/login/signup/SignupSurvey.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/web/src/components/login/signup/SignupSurvey.tsx b/apps/web/src/components/login/signup/SignupSurvey.tsx index 9f7c4730..91a57266 100644 --- a/apps/web/src/components/login/signup/SignupSurvey.tsx +++ b/apps/web/src/components/login/signup/SignupSurvey.tsx @@ -32,9 +32,6 @@ const SignupSurvey = ({ baseNickname, baseEmail, baseProfileImageUrl }: SignupSu const signUpToken = searchParams?.get("token"); const redirectPath = getSafeCommunityRedirectPath(searchParams?.get(AUTH_REDIRECT_PARAM)) ?? undefined; - if (!signUpToken) { - router.push("/login"); - } const { setAccessToken } = useAuthStore(); const [curStage, setCurStage] = useState(1); const [curProgress, setCurProgress] = useState(0); @@ -50,10 +47,20 @@ const SignupSurvey = ({ baseNickname, baseEmail, baseProfileImageUrl }: SignupSu const signUpMutation = usePostSignUp(); const uploadImageMutation = useUploadProfileImagePublic(); + useEffect(() => { + if (!signUpToken) { + router.replace("/login"); + } + }, [signUpToken, router]); + useEffect(() => { setCurProgress(((curStage - 1) / 3) * 100); }, [curStage]); + if (!signUpToken) { + return null; + } + const createRegisterRequest = async (): Promise => { const submitRegion: RegionKo[] = region === "아직 잘 모르겠어요" ? [] : [region as RegionKo];