diff --git a/src/_apis/auth/auth-apis.tsx b/src/_apis/auth/auth-apis.tsx deleted file mode 100644 index 51a931ca..00000000 --- a/src/_apis/auth/auth-apis.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { fetchApi } from '@/src/utils/api'; -import { LoginRequest, LoginResponse, SignupRequest, SignupResponse, User } from '@/src/types/auth'; - -export function signupUser(data: SignupRequest): Promise<{ data: SignupResponse }> { - return fetchApi<{ data: SignupResponse; headers: Headers }>('/auths/signup', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - }).then((response) => { - const token = response.headers.get('Authorization'); - return { data: { token } }; - }); -} - -export function loginUser(data: LoginRequest): Promise<{ data: LoginResponse }> { - return fetchApi<{ data: LoginResponse; headers: Headers }>('/auths/login', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - }).then((response) => { - const token = response.headers.get('Authorization'); - return { data: { token } }; - }); -} - -export function getUser(): Promise<{ data: User }> { - return fetchApi<{ data: User }>('/auths/user', { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }); -} diff --git a/src/_apis/auth/login-apis.ts b/src/_apis/auth/login-apis.ts new file mode 100644 index 00000000..2c3fd9a6 --- /dev/null +++ b/src/_apis/auth/login-apis.ts @@ -0,0 +1,20 @@ +import { fetchApi } from '@/src/utils/api'; +import { LoginRequest, LoginResponse } from '@/src/types/auth'; + +export function login(data: LoginRequest): Promise<{ data: LoginResponse }> { + return fetchApi<{ data: LoginResponse; headers: Headers }>( + '/auths/login', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }, + 5000, + true, + ).then((response) => { + const token = response.headers.get('Authorization'); + return { data: { token } }; + }); +} diff --git a/src/_apis/auth/logout-apis.ts b/src/_apis/auth/logout-apis.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/_apis/auth/signup-apis.ts b/src/_apis/auth/signup-apis.ts new file mode 100644 index 00000000..7d46d776 --- /dev/null +++ b/src/_apis/auth/signup-apis.ts @@ -0,0 +1,20 @@ +import { fetchApi } from '@/src/utils/api'; +import { SignupRequest, SignupResponse } from '@/src/types/auth'; + +export function signup(data: SignupRequest): Promise<{ data: SignupResponse }> { + return fetchApi<{ data: SignupResponse; headers: Headers }>( + '/auths/signup', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }, + 5000, + true, + ).then((response) => { + const token = response.headers.get('Authorization'); + return { data: { token } }; + }); +} diff --git a/src/_apis/auth/user-apis.ts b/src/_apis/auth/user-apis.ts new file mode 100644 index 00000000..bf4cf39a --- /dev/null +++ b/src/_apis/auth/user-apis.ts @@ -0,0 +1,11 @@ +import { fetchApi } from '@/src/utils/api'; +import { User } from '@/src/types/auth'; + +export function getUser(): Promise<{ data: User }> { + return fetchApi<{ data: User }>('/auths/user', { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); +} diff --git a/src/_queries/auth/auth-queries.tsx b/src/_queries/auth/auth-queries.tsx deleted file mode 100644 index abd8418a..00000000 --- a/src/_queries/auth/auth-queries.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { getUser, loginUser, signupUser } from '@/src/_apis/auth/auth-apis'; -import { useAuthStore } from '@/src/store/use-auth-store'; -import { ApiError } from '@/src/utils/api'; -import { transformKeysToCamel } from '@/src/utils/transform-keys'; -import { LoginRequest, LoginResponse, SignupRequest, SignupResponse, User } from '@/src/types/auth'; - -export function usePostSignupQuery() { - const handleAuthSuccess = useHandleAuthSuccess(); - - return useMutation<{ data: SignupResponse }, ApiError, SignupRequest>({ - mutationFn: signupUser, - onSuccess: async (response) => { - await handleAuthSuccess(response.data.token); - }, - }); -} - -export function usePostLoginQuery() { - const handleAuthSuccess = useHandleAuthSuccess(); - - return useMutation<{ data: LoginResponse }, ApiError, LoginRequest>({ - mutationFn: loginUser, - onSuccess: async (response) => { - await handleAuthSuccess(response.data.token); - }, - }); -} - -export function getUserQuery() { - return { - queryKey: ['user'], - queryFn: getUser, - select: (data: User) => transformKeysToCamel(data), - }; -} - -function useHandleAuthSuccess() { - const queryClient = useQueryClient(); - const { login, setUser } = useAuthStore(); - - return async function handleAuthSuccess(token: string | null) { - if (!token) { - throw new Error('토큰이 없습니다'); - } - - try { - const accessToken = token.replace(/^Bearer\s/, ''); - login(accessToken); - const user: User = await queryClient.fetchQuery(getUserQuery()); - setUser(user); - } catch (error) { - throw new Error('사용자 상태 업데이트 실패'); - } - }; -} diff --git a/src/_queries/auth/login-queries.ts b/src/_queries/auth/login-queries.ts new file mode 100644 index 00000000..7b65170b --- /dev/null +++ b/src/_queries/auth/login-queries.ts @@ -0,0 +1,16 @@ +import { useMutation } from '@tanstack/react-query'; +import { login } from '@/src/_apis/auth/login-apis'; +import { ApiError } from '@/src/utils/api'; +import { LoginRequest, LoginResponse } from '@/src/types/auth'; +import { useHandleAuthSuccess } from './use-handle-auth-success'; + +export function usePostLoginQuery() { + const handleAuthSuccess = useHandleAuthSuccess(); + + return useMutation<{ data: LoginResponse }, ApiError, LoginRequest>({ + mutationFn: login, + onSuccess: async (response) => { + await handleAuthSuccess(response.data.token); + }, + }); +} diff --git a/src/_queries/auth/logout-queries.ts b/src/_queries/auth/logout-queries.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/_queries/auth/signup-queries.ts b/src/_queries/auth/signup-queries.ts new file mode 100644 index 00000000..eb39a5a1 --- /dev/null +++ b/src/_queries/auth/signup-queries.ts @@ -0,0 +1,16 @@ +import { useMutation } from '@tanstack/react-query'; +import { signup } from '@/src/_apis/auth/signup-apis'; +import { ApiError } from '@/src/utils/api'; +import { SignupRequest, SignupResponse } from '@/src/types/auth'; +import { useHandleAuthSuccess } from './use-handle-auth-success'; + +export function usePostSignupQuery() { + const handleAuthSuccess = useHandleAuthSuccess(); + + return useMutation<{ data: SignupResponse }, ApiError, SignupRequest>({ + mutationFn: signup, + onSuccess: async (response) => { + await handleAuthSuccess(response.data.token); + }, + }); +} diff --git a/src/_queries/auth/use-handle-auth-success.ts b/src/_queries/auth/use-handle-auth-success.ts new file mode 100644 index 00000000..1352948f --- /dev/null +++ b/src/_queries/auth/use-handle-auth-success.ts @@ -0,0 +1,24 @@ +import { useQueryClient } from '@tanstack/react-query'; +import { useAuthStore } from '@/src/store/use-auth-store'; +import { User } from '@/src/types/auth'; +import { getUserQuery } from './user-apis'; + +export function useHandleAuthSuccess() { + const queryClient = useQueryClient(); + const { login, setUser } = useAuthStore(); + + return async function handleAuthSuccess(token: string | null) { + if (!token) { + throw new Error('토큰이 없습니다'); + } + + try { + const accessToken = token.replace(/^Bearer\s/, ''); + login(accessToken); + const user: User = await queryClient.fetchQuery(getUserQuery()); + setUser(user); + } catch (error) { + throw new Error('사용자 상태 업데이트 실패'); + } + }; +} diff --git a/src/_queries/auth/user-apis.ts b/src/_queries/auth/user-apis.ts new file mode 100644 index 00000000..cc339273 --- /dev/null +++ b/src/_queries/auth/user-apis.ts @@ -0,0 +1,11 @@ +import { getUser } from '@/src/_apis/auth/user-apis'; +import { transformKeysToCamel } from '@/src/utils/transform-keys'; +import { User } from '@/src/types/auth'; + +export function getUserQuery() { + return { + queryKey: ['user'], + queryFn: getUser, + select: (data: User) => transformKeysToCamel(data), + }; +} diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx index 7181f694..f58b42a4 100644 --- a/src/app/(auth)/login/page.tsx +++ b/src/app/(auth)/login/page.tsx @@ -4,7 +4,7 @@ import React from 'react'; import { useForm } from 'react-hook-form'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; -import { usePostLoginQuery } from '@/src/_queries/auth/auth-queries'; +import { usePostLoginQuery } from '@/src/_queries/auth/login-queries'; import LoginForm, { LoginFormValues } from './_component/login-form'; export default function LoginPage() { diff --git a/src/app/(auth)/signup/page.tsx b/src/app/(auth)/signup/page.tsx index 40f58225..e36deae8 100644 --- a/src/app/(auth)/signup/page.tsx +++ b/src/app/(auth)/signup/page.tsx @@ -4,7 +4,7 @@ import React from 'react'; import { useForm } from 'react-hook-form'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; -import { usePostSignupQuery } from '@/src/_queries/auth/auth-queries'; +import { usePostSignupQuery } from '@/src/_queries/auth/signup-queries'; import SignupForm, { SignupFormValues } from './_component/signup-form'; export default function LoginPage() { diff --git a/src/utils/api.ts b/src/utils/api.ts index 5f876175..0b6110a8 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -19,6 +19,7 @@ export async function fetchApi( url: string, options: RequestInit = {}, timeout = 5000, + isAuth = false, ): Promise { const controller = new AbortController(); const { signal } = controller; @@ -50,8 +51,9 @@ export async function fetchApi( throw new ApiError(response.status, errorMessage, errorDetail); } - - return { data: await response.json() } as T; + const data = await response.json(); + if (isAuth) return { data, headers: response.headers } as T; + return { data } as T; } catch (error) { if (error instanceof Error) { if (error.name === 'AbortError') throw new ApiError(408, 'Request timeout');