Skip to content

Commit

Permalink
fix: middleware 오동작으로 생긴 배포 이슈 수정 및 리팩토링 (2차) (#39)
Browse files Browse the repository at this point in the history
* add NextResponse.next()

* remove middleware for deploy test

* add middleware with runtime config

* change to edge not experimental

* remove next()

* add edge runtime on next config

* version up nextjs for deploy test

* remove experimental runtime

* Revert "version up nextjs for deploy test"

This reverts commit 13d5ce9.

* remove middleware for fixing deploy

* move redirection logic to app comp and refactor

* replace getStaticProps to needProtected attribute

* set isLoading default value to true

* change name for readability
  • Loading branch information
young-do authored Feb 11, 2023
1 parent 593cdcb commit 29ae9d3
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 47 deletions.
31 changes: 31 additions & 0 deletions hooks/useProtectedRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useUser } from '@/store/useUser';
import { useRouter } from 'next/router';
import { useEffect } from 'react';

export const useProtectedRoute = (isProtectedPage = false, redirectUrl = '/') => {
const router = useRouter();
const { user, isLoading, login } = useUser();

// @note:
// 1. 로그인 전에 로딩 페이지를 보여주는 이유는
// 로그인 되기 전에 supabase를 통해 api 호출하면 signIn이 되어있지 않아 아무값을 못 얻게되기 때문이다.
// 2. protected 페이지는 유저 정보가 없을떄 지속적으로 로딩 페이지를 노출하는 이유는
// redirectUrl로 이동하기 때문이다.
const showLoadingPage = isProtectedPage ? isLoading || !user : isLoading;

useEffect(() => {
// @note:
// getServerSideProps에서 edge function을 호출해도 그 응답에 접근할 수 없기에
// 로그인 여부를 client side에서 최초 mount된 시점에 체크합니다.
// https://nextjs.org/docs/api-routes/edge-api-routes#differences-between-api-routes
login().catch(() => null);
}, [login]);

useEffect(() => {
if (isProtectedPage && !isLoading && !user) {
router.replace(redirectUrl);
}
}, [isLoading, isProtectedPage, redirectUrl, router, user]);

return { showLoadingPage };
};
23 changes: 0 additions & 23 deletions middleware.ts

This file was deleted.

28 changes: 7 additions & 21 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,26 @@
import type { AppProps } from 'next/app';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactElement, ReactNode, useEffect } from 'react';
import { ReactElement, ReactNode } from 'react';
import Head from 'next/head';
import { ChakraProvider } from '@chakra-ui/react';
import theme from '@/styles/theme';
import { NextPage } from 'next';
import ErrorBoundary from '@/components/ErrorBoundary/ErrorBoundary';
import { useUser } from '@/store/useUser';
import { useProtectedRoute } from '@/hooks/useProtectedRoute';

export type NextPageWithLayout<P = object, IP = P> = NextPage<P, IP> & {
getLayout?: (page: ReactElement) => ReactNode;
isProtectedPage?: boolean;
};

type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout;
};

function App({ Component, pageProps }: AppPropsWithLayout) {
const { login, isLoading } = useUser();
const queryClient = new QueryClient();
const getLayout = Component.getLayout ?? ((page) => page);

useEffect(() => {
// @note:
// getServerSideProps에서 edge function을 호출해도 그 응답에 접근할 수 없기에
// 로그인 여부를 client side에서 최초 mount된 시점에 체크합니다.
// https://nextjs.org/docs/api-routes/edge-api-routes#differences-between-api-routes
login().catch(() => null);
}, [login]);
const { showLoadingPage } = useProtectedRoute(Component?.isProtectedPage, '/');

return (
<>
Expand All @@ -40,16 +33,9 @@ function App({ Component, pageProps }: AppPropsWithLayout) {
</Head>
<QueryClientProvider client={queryClient}>
<ChakraProvider theme={theme} resetCSS>
{/* @note: 로그인 되기 전에 supabase를 통해 api 호출하면
signIn이 되어있지 않아 아무값을 못 얻게되므로
일단은 로딩 문구를 보여줍니다... */}
{isLoading
? 'loading...'
: getLayout(
<ErrorBoundary fallback={<div>에러 페이지</div>}>
<Component {...pageProps} />
</ErrorBoundary>
)}
<ErrorBoundary fallback={<div>에러 페이지</div>}>
{showLoadingPage ? 'loading...' : getLayout(<Component {...pageProps} />)}
</ErrorBoundary>
</ChakraProvider>
</QueryClientProvider>
</>
Expand Down
1 change: 1 addition & 0 deletions pages/bucketlist/[folderId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ BucketListItem.getLayout = (page) => (
{page}
</MainLayout>
);
BucketListItem.isProtectedPage = true;

export default BucketListItem;
1 change: 1 addition & 0 deletions pages/bucketlist/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ BucketList.getLayout = (page) => (
{page}
</MainLayout>
);
BucketList.isProtectedPage = true;

export default BucketList;
3 changes: 2 additions & 1 deletion pages/event/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import AddBucketFolderModal from '@/components/modal/AddBucketFolderModal';

const Event: NextPageWithLayout = () => {
const { isOpen, onOpen, onClose } = useDisclosure();

return (
<>
<h1>일정</h1>
Expand All @@ -27,5 +27,6 @@ Event.getLayout = (page) => (
{page}
</MainLayout>
);
Event.isProtectedPage = true;

export default Event;
2 changes: 2 additions & 0 deletions pages/mypage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ MyPage.getLayout = (page) => (
</MainLayout>
);

MyPage.isProtectedPage = true;

export default MyPage;
3 changes: 1 addition & 2 deletions store/useUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ type UserState = {

export const useUser = create<UserState>((set) => ({
user: null,
isLoading: false,
isLoading: true,
selectedGroupId: null,
login: async () => {
// @note: 세션에 담긴 쿠키를 통해 자신의 유저 정보를 가져옵니다.
set({ isLoading: true });
try {
const res = await fetch('/api/auth/me');
const user: User | null = (await res.json())?.data?.user;
Expand Down

0 comments on commit 29ae9d3

Please sign in to comment.