(url);
+};
+
+export default function Redirection() {
+ const { loggedInfo, setLoggedInfo } = useContext(AuthContext);
+ const [errorMessage, setErrorMessage] = useState('');
+ const [isLoading, setIsLoading] = useState(true);
+ const [params] = useSearchParams();
+
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ (async () => {
+ setIsLoading(true);
+ setErrorMessage('');
+
+ const code = params.get('code');
+ const REGISTER_API_URL = `${process.env.VOTOGETHER_BASE_URL}/auth/kakao/callback?code=${code}`;
+
+ await getAuthInfo(REGISTER_API_URL)
+ .finally(() => {
+ setIsLoading(false);
+ })
+ .catch(error => {
+ setErrorMessage(error.message);
+ })
+ .then(res => {
+ if (!res) return setErrorMessage('잘못된 형식의 response');
+
+ const { accessToken } = res;
+ setCookieToken('accessToken', accessToken);
+
+ setLoggedInfo({
+ ...loggedInfo,
+ accessToken: getCookieToken().accessToken,
+ isLogged: true,
+ });
+
+ navigate('/');
+ });
+ })();
+ }, [navigate, loggedInfo, setLoggedInfo]);
+
+ return (
+
+ {isLoading && '로그인 중입니다...'}
+ {errorMessage && errorMessage}
+
+ );
+}
diff --git a/frontend/src/routes/router.tsx b/frontend/src/routes/router.tsx
index 8f01b522f..dedb88f69 100644
--- a/frontend/src/routes/router.tsx
+++ b/frontend/src/routes/router.tsx
@@ -1,5 +1,7 @@
import { createBrowserRouter } from 'react-router-dom';
+import Login from '@pages/auth/Login';
+import Redirection from '@pages/auth/Redirection';
import Home from '@pages/Home';
import MyInfo from '@pages/MyInfo';
import CreatePost from '@pages/post/CreatePost';
@@ -13,10 +15,15 @@ const router = createBrowserRouter([
{
path: PATH.HOME,
element: ,
- children: [
- { path: 'search', element: },
- { path: 'login', element: },
- ],
+ children: [{ path: 'search', element: }],
+ },
+ {
+ path: PATH.LOGIN,
+ element: ,
+ },
+ {
+ path: 'auth/kakao/callback',
+ element: ,
},
{
path: PATH.POST,
@@ -34,7 +41,7 @@ const router = createBrowserRouter([
path: 'result/:postId',
element: ,
},
- { path: 'category/:categoryId', element: },
+ { path: 'posts/category/:categoryId', element: },
],
},
{
diff --git a/frontend/src/types/auth.ts b/frontend/src/types/auth.ts
new file mode 100644
index 000000000..015668185
--- /dev/null
+++ b/frontend/src/types/auth.ts
@@ -0,0 +1,3 @@
+export interface AuthResponse {
+ accessToken: string;
+}
diff --git a/frontend/src/types/user.ts b/frontend/src/types/user.ts
index 7e6cf2a8b..2bc5ed5fe 100644
--- a/frontend/src/types/user.ts
+++ b/frontend/src/types/user.ts
@@ -17,3 +17,10 @@ export interface UserInfoResponse {
export interface ModifyNicknameRequest {
nickname: string;
}
+
+
+export interface LoggedInfo {
+ accessToken: string;
+ isLogged: boolean;
+ userInfo?: UserInfoResponse;
+}
diff --git a/frontend/src/utils/cookie/index.ts b/frontend/src/utils/cookie/index.ts
new file mode 100644
index 000000000..bb7cededd
--- /dev/null
+++ b/frontend/src/utils/cookie/index.ts
@@ -0,0 +1,17 @@
+type CookieKey = 'accessToken' | 'refreshToken';
+
+export const setCookieToken = (key: CookieKey, token: string) => {
+ //secure 속성은 현재 dev에서는 http로 진행중이기 때문에 사용할 수 없음
+ document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(token)}; path=/`;
+};
+
+// token형식 = "key=value; key=value; key=value"
+export function getCookieToken() {
+ const cookie = document.cookie;
+ const cookieContent = {} as { [key: string]: any };
+ cookie.split('; ').forEach(pair => {
+ const [key, value] = pair.split('=');
+ cookieContent[key] = value;
+ });
+ return cookieContent as Record;
+}
diff --git a/frontend/src/utils/fetch.ts b/frontend/src/utils/fetch.ts
index 32a065c5c..c705a80a2 100644
--- a/frontend/src/utils/fetch.ts
+++ b/frontend/src/utils/fetch.ts
@@ -1,17 +1,31 @@
+import { getCookieToken } from './cookie';
+
const headers = {
'Content-Type': 'application/json;charset=utf-8',
Authorization: `Bearer `,
};
-const multiHeaders = {
- 'Content-Type': 'multipart/form-data',
- Authorization: `Bearer `,
+const makeFetchHeaders = () => {
+ const cookie = getCookieToken();
+
+ return {
+ ...headers,
+ Authorization: `Bearer ${cookie.accessToken}`,
+ };
+};
+
+const makeFetchMultiHeaders = () => {
+ const cookie = getCookieToken();
+
+ return {
+ Authorization: `Bearer ${cookie.accessToken}`,
+ };
};
export const getFetch = async (url: string): Promise => {
const response = await fetch(url, {
method: 'GET',
- headers,
+ headers: makeFetchHeaders(),
});
const data = await response.json();
@@ -27,7 +41,7 @@ export const postFetch = async (url: string, body: T): Promise =
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(body),
- headers,
+ headers: makeFetchHeaders(),
});
const data = await response.json();
@@ -43,7 +57,7 @@ export const putFetch = async (url: string, body: T): Promise =>
const response = await fetch(url, {
method: 'PUT',
body: JSON.stringify(body),
- headers,
+ headers: makeFetchHeaders(),
});
const data = await response.json();
@@ -58,7 +72,7 @@ export const putFetch = async (url: string, body: T): Promise =>
export const patchFetch = async (url: string, body?: T) => {
const response = await fetch(url, {
method: 'PATCH',
- headers,
+ headers: makeFetchHeaders(),
body: JSON.stringify(body),
});
@@ -74,7 +88,7 @@ export const patchFetch = async (url: string, body?: T) => {
export const deleteFetch = async (url: string) => {
const response = await fetch(url, {
method: 'DELETE',
- headers,
+ headers: makeFetchHeaders(),
});
return response;
@@ -84,7 +98,7 @@ export const multiPostFetch = async (url: string, body: FormData) => {
const response = await fetch(url, {
method: 'POST',
body,
- headers: multiHeaders,
+ headers: makeFetchMultiHeaders(),
});
const data = await response.json();
@@ -100,7 +114,7 @@ export const multiPutFetch = async (url: string, body: FormData) => {
const response = await fetch(url, {
method: 'PUT',
body,
- headers: multiHeaders,
+ headers: makeFetchMultiHeaders(),
});
const data = await response.json();