fix(landing): 인증 상태에 따라 CTA 경로 분기

This commit is contained in:
2026-03-14 00:48:24 +09:00
parent a1424a4794
commit 6154bd54a8
4 changed files with 65 additions and 6 deletions

View File

@@ -1,5 +1,6 @@
import Link from "next/link"; import Link from "next/link";
import { copy } from '@/shared/i18n'; import { copy } from '@/shared/i18n';
import { AuthLandingLoginButton } from "@/features/auth/components/AuthLandingLoginButton";
import { AuthRedirectButton } from "@/features/auth/components/AuthRedirectButton"; import { AuthRedirectButton } from "@/features/auth/components/AuthRedirectButton";
import { Button } from "@/shared/ui/Button"; import { Button } from "@/shared/ui/Button";
@@ -19,7 +20,9 @@ export default function MarketingPage() {
<nav className="hidden md:flex items-center gap-6 text-sm font-medium text-brand-dark/80"> <nav className="hidden md:flex items-center gap-6 text-sm font-medium text-brand-dark/80">
<Button variant="ghost" size="sm" href="#features">{landing.nav.features}</Button> <Button variant="ghost" size="sm" href="#features">{landing.nav.features}</Button>
<Button variant="ghost" size="sm" href="#pricing">{landing.nav.pricing}</Button> <Button variant="ghost" size="sm" href="#pricing">{landing.nav.pricing}</Button>
<Button variant="ghost" size="sm" href="/login">{landing.nav.login}</Button> <AuthLandingLoginButton variant="ghost" size="sm">
{landing.nav.login}
</AuthLandingLoginButton>
<AuthRedirectButton variant="primary" size="md">{landing.nav.startFree}</AuthRedirectButton> <AuthRedirectButton variant="primary" size="md">{landing.nav.startFree}</AuthRedirectButton>
</nav> </nav>
</div> </div>

View File

@@ -0,0 +1,38 @@
'use client';
import type { ReactNode } from 'react';
import { useAuthStore } from '@/entities/auth';
import { Button, type ButtonSize, type ButtonVariant } from '@/shared/ui/Button';
import { hasClientAuth } from '../model/hasClientAuth';
interface AuthLandingLoginButtonProps {
children: ReactNode;
className?: string;
size?: ButtonSize;
variant?: ButtonVariant;
}
export function AuthLandingLoginButton({
children,
className,
size = 'sm',
variant = 'ghost',
}: AuthLandingLoginButtonProps) {
const accessToken = useAuthStore((state) => state.accessToken);
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
if (
hasClientAuth({
accessToken,
isAuthenticated,
})
) {
return null;
}
return (
<Button href="/login" variant={variant} size={size} className={className}>
{children}
</Button>
);
}

View File

@@ -1,11 +1,10 @@
'use client'; 'use client';
import Cookies from 'js-cookie';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { useAuthStore } from '@/entities/auth'; import { useAuthStore } from '@/entities/auth';
import { TOKEN_COOKIE_KEY } from '@/shared/config/authTokens';
import { Button, type ButtonSize, type ButtonVariant } from '@/shared/ui/Button'; import { Button, type ButtonSize, type ButtonVariant } from '@/shared/ui/Button';
import { hasClientAuth } from '../model/hasClientAuth';
interface AuthRedirectButtonProps { interface AuthRedirectButtonProps {
children: ReactNode; children: ReactNode;
@@ -21,7 +20,7 @@ export function AuthRedirectButton({
className, className,
size = 'md', size = 'md',
variant = 'primary', variant = 'primary',
authenticatedHref = '/space', authenticatedHref = '/app',
unauthenticatedHref = '/login', unauthenticatedHref = '/login',
}: AuthRedirectButtonProps) { }: AuthRedirectButtonProps) {
const router = useRouter(); const router = useRouter();
@@ -29,8 +28,14 @@ export function AuthRedirectButton({
const isAuthenticated = useAuthStore((state) => state.isAuthenticated); const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
const handleClick = () => { const handleClick = () => {
const hasAccessToken = isAuthenticated || Boolean(accessToken) || Boolean(Cookies.get(TOKEN_COOKIE_KEY)); router.push(
router.push(hasAccessToken ? authenticatedHref : unauthenticatedHref); hasClientAuth({
accessToken,
isAuthenticated,
})
? authenticatedHref
: unauthenticatedHref,
);
}; };
return ( return (

View File

@@ -0,0 +1,13 @@
'use client';
import Cookies from 'js-cookie';
import { TOKEN_COOKIE_KEY } from '@/shared/config/authTokens';
interface HasClientAuthInput {
accessToken: string | null;
isAuthenticated: boolean;
}
export const hasClientAuth = ({ accessToken, isAuthenticated }: HasClientAuthInput) => {
return isAuthenticated || Boolean(accessToken) || Boolean(Cookies.get(TOKEN_COOKIE_KEY));
};