Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FE-29 ♻️ 코드 리뷰에 대한 리팩토링 #54

Merged
merged 8 commits into from
Jul 22, 2024
25 changes: 2 additions & 23 deletions src/apis/auth.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,9 @@
import type { PostSigninRequestType, PostSigninResponseType } from '@/schema/auth';
import { AxiosError } from 'axios';
import httpClient from '.';

const postSignin = async (request: PostSigninRequestType): Promise<PostSigninResponseType> => {
try {
const response = await httpClient.post('/auth/signIn', request);
return response.data;
} catch (error) {
if (error instanceof AxiosError) {
// Axios 에러인 경우
const axiosError = error as AxiosError;
if (axiosError.response) {
// 서버에서 응답이 온 경우 (예: 4xx, 5xx)
throw new Error('로그인 요청 처리 중 문제가 발생했습니다.');
} else if (axiosError.request) {
// 요청을 보냈지만 응답을 받지 못한 경우
throw new Error('서버 응답을 받지 못했습니다. 잠시 후 다시 시도해 주세요.');
} else {
// 요청을 설정하는 과정에서 문제가 발생한 경우
throw new Error('로그인 요청을 처리하는 동안 문제가 발생했습니다.');
}
} else {
// Axios 에러가 아닌 경우 (네트워크 문제 등)
throw new Error('알 수 없는 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.');
}
}
const response = await httpClient.post('/auth/signIn', request);
return response.data;
};

export default postSignin;
35 changes: 19 additions & 16 deletions src/apis/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,26 @@ httpClient.interceptors.response.use(

if (!refreshToken) {
window.location.href = '/auth/SignIn';
} else {
httpClient
.post('/auth/refresh-token', null, {
headers: { Authorization: `Bearer ${refreshToken}` },
})
.then((response) => {
const { accessToken } = response.data;
const { refreshToken: newRefreshToken } = response.data;
localStorage.setItem('accessToken', accessToken);
localStorage.setItem('refreshToken', newRefreshToken);
})
.catch(() => {
window.location.href = '/auth/SignIn';
});
return Promise.reject(error);
}
} else {
throw new Error(error.response.status);

return httpClient
.post('/auth/refresh-token', null, {
headers: { Authorization: `Bearer ${refreshToken}` },
})
.then((response) => {
const { accessToken, refreshToken: newRefreshToken } = response.data;
localStorage.setItem('accessToken', accessToken);
localStorage.setItem('refreshToken', newRefreshToken);

const originalRequest = error.config;
return httpClient(originalRequest);
})
.catch(() => {
window.location.href = '/auth/SignIn';
return Promise.reject(error);
});
}
return Promise.reject(error);
},
);
22 changes: 22 additions & 0 deletions src/hooks/useSignInMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import postSignin from '@/apis/auth';
import { toast } from '@/components/ui/use-toast';
import { useMutation } from '@tanstack/react-query';
import { useRouter } from 'next/router';

const useSigninMutation = () => {
const router = useRouter();

return useMutation({
mutationFn: postSignin,
onSuccess: (data) => {
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken);
router.push('/');
},
onError: () => {
toast({ description: '이메일 혹은 비밀번호를 확인해주세요.', className: 'border-state-error text-state-error font-semibold' });
},
});
};

export default useSigninMutation;
20 changes: 0 additions & 20 deletions src/hooks/userQueryHooks.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import postSignin from '@/apis/auth';
import quries from '@/apis/queries';
import { updateMe } from '@/apis/user';
import { GetUserReponseType, GetUserRequestType, PatchMeRequestType } from '@/schema/user';
import { MutationOptions } from '@/types/query';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router';

export const useMeQuery = () => useQuery(quries.user.getMe());

Expand All @@ -23,21 +21,3 @@ export const useUpdateMe = (options: MutationOptions<GetUserReponseType>) => {
},
});
};

export const useSignin = () => {
const router = useRouter();

return useMutation({
mutationFn: postSignin,
onSuccess: (data) => {
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken);
router.push('/');
},
onError: (error) => {
// NOTE: 임시 테스트용 콘솔, 토스트 추가 예정
/* eslint-disable no-console */
console.error(error);
},
});
};
5 changes: 0 additions & 5 deletions src/pageLayout/AuthLayout/AuthLayout.tsx

This file was deleted.

2 changes: 2 additions & 0 deletions src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import '@/styles/globals.css';
import type { AppProps } from 'next/app';
import { HydrationBoundary, QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import Toaster from '@/components/ui/toaster';

export default function App({ Component, pageProps }: AppProps) {
const [queryClient] = React.useState(() => new QueryClient());
return (
<QueryClientProvider client={queryClient}>
<HydrationBoundary state={pageProps.dehydratedState}>
<Component {...pageProps} />
<Toaster />
</HydrationBoundary>
<ReactQueryDevtools />
</QueryClientProvider>
Expand Down
15 changes: 5 additions & 10 deletions src/pages/auth/SignIn.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import Image from 'next/image';
import Link from 'next/link';
import AuthLayout from '@/pageLayout/AuthLayout/AuthLayout';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Form, FormControl, FormField, FormItem, FormMessage } from '@/components/ui/form';
import { PostSigninRequest, PostSigninRequestType } from '@/schema/auth';
import { useSignin } from '@/hooks/userQueryHooks';
import useSigninMutation from '@/hooks/useSignInMutation';

export default function SignIn() {
const mutationSignin = useSignin();
const mutationSignin = useSigninMutation();
// 폼 정의
const form = useForm<PostSigninRequestType>({
resolver: zodResolver(PostSigninRequest),
Expand All @@ -21,21 +20,17 @@ export default function SignIn() {
},
});

function onSubmit(values: PostSigninRequestType) {
mutationSignin.mutate(values);
}

// TODO: 나중에 컴포넌트 분리하기
return (
<AuthLayout>
<div className='flex flex-col justify-center items-center bg-background-100 w-full h-screen'>
<header className='mb-[50px] md:mb-[60px]'>
<Link href='/'>
<Image src='/lg.svg' alt='logo' width={172} height={48} />
</Link>
</header>

<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className='flex flex-col items-center lg:gap-6 gap-5 w-full px-6'>
<form onSubmit={form.handleSubmit((values: PostSigninRequestType) => mutationSignin.mutate(values))} className='flex flex-col items-center lg:gap-6 gap-5 w-full px-6'>
<div className='flex flex-col items-center lg:gap-4 gap-[10px] w-full lg:max-w-[640px] md:max-w-[384px]'>
<FormField
control={form.control}
Expand Down Expand Up @@ -100,6 +95,6 @@ export default function SignIn() {
<Image src='/logo-kakao.svg' alt='logo-kakao' width={60} height={60} className='md:size-[60px] size-10' />
</Button>
</div>
</AuthLayout>
</div>
);
}
Loading