diff --git a/src/frontend/apps/web/src/entities/auth/index.ts b/src/frontend/apps/web/src/entities/auth/index.ts deleted file mode 100644 index bd277d93..00000000 --- a/src/frontend/apps/web/src/entities/auth/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type { AuthToken } from './auth-type'; diff --git a/src/frontend/apps/web/src/entities/auth/auth-type.d.ts b/src/frontend/apps/web/src/entities/auth/model/auth-type.d.ts similarity index 100% rename from src/frontend/apps/web/src/entities/auth/auth-type.d.ts rename to src/frontend/apps/web/src/entities/auth/model/auth-type.d.ts diff --git a/src/frontend/apps/web/src/entities/index.ts b/src/frontend/apps/web/src/entities/index.ts index 64b0891f..056ea00c 100644 --- a/src/frontend/apps/web/src/entities/index.ts +++ b/src/frontend/apps/web/src/entities/index.ts @@ -1 +1,3 @@ -export type { AuthToken } from './auth'; +export type { AuthToken } from './auth/model/auth-type'; +export type { User } from './user/model/user-type'; +export { useUserStore } from './user/model/user-store'; diff --git a/src/frontend/apps/web/src/entities/user/.keep b/src/frontend/apps/web/src/entities/user/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/frontend/apps/web/src/entities/user/model/user-store.ts b/src/frontend/apps/web/src/entities/user/model/user-store.ts new file mode 100644 index 00000000..7e1bf199 --- /dev/null +++ b/src/frontend/apps/web/src/entities/user/model/user-store.ts @@ -0,0 +1,17 @@ +import { create } from 'zustand'; +import { User } from './user-type'; + +type UserStore = { + user: User | null; + setUser: (user: User | null) => void; +}; +export const useUserStore = create((set) => ({ + user: + typeof window !== 'undefined' + ? JSON.parse(localStorage.getItem('user') || 'null') + : null, + setUser: (user) => { + localStorage.setItem('user', JSON.stringify(user)); + set(() => ({ user })); + }, +})); diff --git a/src/frontend/apps/web/src/entities/user/model/user-type.d.ts b/src/frontend/apps/web/src/entities/user/model/user-type.d.ts new file mode 100644 index 00000000..6e1f9a8b --- /dev/null +++ b/src/frontend/apps/web/src/entities/user/model/user-type.d.ts @@ -0,0 +1,5 @@ +export type User = { + userId: number; + nickname: string; + profileImage: string; +}; diff --git a/src/frontend/apps/web/src/features/auth/api/requestLogin.api.ts b/src/frontend/apps/web/src/features/auth/api/requestLogin.api.ts index ce547965..e99791a0 100644 --- a/src/frontend/apps/web/src/features/auth/api/requestLogin.api.ts +++ b/src/frontend/apps/web/src/features/auth/api/requestLogin.api.ts @@ -2,9 +2,19 @@ import { postRequest } from '@/src/shared/services'; import { cookies } from 'next/headers'; +import { AuthToken, User } from '@/src/entities'; + +type LoginRes = { + user: User; + token: AuthToken; +}; +type LoginReq = { + platform: string; + redirectUri: string; +}; export const requestLogin = async (authorizationCode: string) => { - const { user, token } = await postRequest( + const { user, token } = await postRequest( 'gateway', `/api/v1/user/login?authorizationCode=${authorizationCode}`, { @@ -16,7 +26,7 @@ export const requestLogin = async (authorizationCode: string) => { const cookieOptions = { secure: process.env.MODE === 'production', }; - cookies().set('userId', user.userId, cookieOptions); + cookies().set('userId', String(user.userId), cookieOptions); cookies().set('accessToken', token.accessToken, cookieOptions); cookies().set('refreshToken', token.refreshToken, cookieOptions); diff --git a/src/frontend/apps/web/src/features/auth/model/use-login-redirect.ts b/src/frontend/apps/web/src/features/auth/model/use-login-redirect.ts index 3f64cf26..6552d045 100644 --- a/src/frontend/apps/web/src/features/auth/model/use-login-redirect.ts +++ b/src/frontend/apps/web/src/features/auth/model/use-login-redirect.ts @@ -4,16 +4,18 @@ import { useSearchParams } from 'next/navigation'; import { useRouter } from 'next/navigation'; import { useEffect } from 'react'; import { requestLogin } from '../api/requestLogin.api'; +import { useUserStore } from '@/src/entities'; export const useLoginRedirect = () => { const router = useRouter(); const searchParams = useSearchParams(); const code = searchParams.get('code'); + const setUser = useUserStore((state) => state.setUser); useEffect(() => { if (!code) { alert('인가 코드가 없습니다. 다시 로그인 해주세요.'); - router.replace('/'); + router.push('/'); return; } @@ -24,11 +26,12 @@ export const useLoginRedirect = () => { throw new Error('사용자 정보가 없습니다.'); } localStorage.setItem('user', JSON.stringify(user)); - router.replace('/stock'); + setUser(user); + router.push('/stock'); } catch (err) { console.error('로그인 실패:', err); alert('로그인에 실패했습니다. 다시 로그인 해주세요.'); - router.replace('/'); + router.push('/'); } }; diff --git a/src/frontend/apps/web/src/features/auth/model/use-logout.ts b/src/frontend/apps/web/src/features/auth/model/use-logout.ts new file mode 100644 index 00000000..3763fc27 --- /dev/null +++ b/src/frontend/apps/web/src/features/auth/model/use-logout.ts @@ -0,0 +1,20 @@ +'use client'; + +import { useUserStore } from '@/src/entities'; +import { useRouter } from 'next/navigation'; + +export const useLogout = () => { + const router = useRouter(); + const setUser = useUserStore((state) => state.setUser); + + return () => { + localStorage.removeItem('user'); + setUser(null); + document.cookie = + 'accessToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; + document.cookie = + 'refreshToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; + document.cookie = 'userId=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; + router.push('/'); + }; +}; diff --git a/src/frontend/apps/web/src/features/auth/ui/logout-button.tsx b/src/frontend/apps/web/src/features/auth/ui/logout-button.tsx index c9cf3329..dd404972 100644 --- a/src/frontend/apps/web/src/features/auth/ui/logout-button.tsx +++ b/src/frontend/apps/web/src/features/auth/ui/logout-button.tsx @@ -1,11 +1,16 @@ +'use client'; + import { Button } from '@workspace/ui/components'; +import { useLogout } from '../model/use-logout'; const LogoutButton = () => { + const handleLogout = useLogout(); return ( diff --git a/src/frontend/apps/web/src/features/user/ui/profile-nickname.tsx b/src/frontend/apps/web/src/features/user/ui/profile-nickname.tsx index 0dfae0c7..e07844ea 100644 --- a/src/frontend/apps/web/src/features/user/ui/profile-nickname.tsx +++ b/src/frontend/apps/web/src/features/user/ui/profile-nickname.tsx @@ -1,12 +1,12 @@ 'use client'; +import { useUserStore } from '@/src/entities'; import { Button, Input, Label } from '@workspace/ui/components'; import { Pencil } from 'lucide-react'; const ProfileNickname = () => { - //임시변수 const isNameEditMode = false; - const name = '공작새'; + const nickname = useUserStore((state) => state.user?.nickname ?? ''); return (
@@ -15,7 +15,7 @@ const ProfileNickname = () => { id="name" disabled={!isNameEditMode} placeholder="Enter your name" - value={name} + value={nickname} />