개발자
안녕하세요, next js middleware를 사용해 로그인 사용별 화면을 분기하고 있습니다. 다름이 아니라 사용하면서 문제가 있어 이리저리 검색하다가 해결방법을 찾지 못해 글 남깁니다. 문제1. 브라우저 뒤로가기시 redirect대상 페이지면 title 미변경 문제. redirect된 페이지의 title이 아닌, redirect대상의 title이 적용되었습니다. redirect가 서버에서 브라우저에 요청하는 것이고 브라우저는 이를 실행은 하나 title은 변경되지 않았습니다. 2. 로그인후 뒤로가기를 계속 진행한후 브라우저 첫 페이지(구글)도달후 앞으로 가기를 하면 무한 리디렉션 문제가 발생. 해당 문제는 로그인후 메인 화면으로 넘어간 후 다시 뒤로가기를 반복하고 첫 페이지 도달시, 다시 앞으로 가기해서(예를 들어 로그인 페이지)면 미들웨어가 화면전환 도중에 리디렉션 요청이 많다고 에러를 발생 시킵니다. 아래는 제가 사용하는 코드를 첨부하겠습니다. 요약하자면 redirect하면 title 변경이 안됨. 뒤로가기후 다시 앞으로 가기하면 리디렉션 에러가 발생함. 만약 다른 방법이 있다면, 현업에선 어떻게 처리하는지 궁금합니다. export const verifyUser = (request: NextRequest, moveUrl: string) => { // const includesPage = ['/', '/auth/login', '/dashboard/customdashboard']; const accessToken = request.cookies.get('accessToken')?.value; const url = request.nextUrl.clone(); if (accessToken && isTokenExpired(accessToken)) { // 로그인 페이지 요청시 사용자 검증이 완료된 상태면 / 페이지로 강제 리다이렉트시킴. if (moveUrl === '/auth/login' || moveUrl.startsWith('/signup')) { url.pathname = '/'; return NextResponse.redirect(url); } return NextResponse.next(); } else { // 일반 페이지 요청시 사용자 검증이 미완료된 상태라면 로그인 페이지로 강제 리다이렉트시킴. if (moveUrl === '/auth/login' || moveUrl.startsWith('/signup')) { return NextResponse.next(); } removeLoginCookie(); url.pathname = '/auth/login'; return NextResponse.redirect(url); } };
답변 3
1. 타이틀 이슈는 Head 컴포넌트가 적용되어 있지 않다면 한번 적용해보시겠어요?
1import Head from 'next/head';
2
3export default function MyPage() {
4 return (
5 <>
6 <Head>
7 <title>My Page Title</title>
8 </Head>
9 {/* 나머지 페이지 컴포넌트 */}
10 </>
11 );
12}
익명
작성자
2023년 05월 08일
NextSeo 라이브러리로 아래와 같이 적용되어있는데, 아래 방법이 틀렸나요? _app.tsx <DefaultSeo defaultTitle={`MT HOMEPAGE`} titleTemplate="MT HOMEPAGE - %s" description="test project" /> index.tsx <NextSeo title="home" description="test desc!" />
2. 이 문제는 브라우저의 히스토리 상태와 관련이 있습니다. 브라우저의 뒤로 가기 버튼을 사용할 때 이전 페이지로 돌아가게 되는데, 리디렉션 페이지가 히스토리에 기록되어 있기 때문에 앞으로 가기를 사용하면 리디렉션 페이지가 다시 호출됩니다. 이 문제를 해결하기 위해 클라이언트 측에서 리디렉션을 처리하는 방법을 사용할 수 있습니다. 아래는 관련된 샘플 코드인데 참고해보시면 좋겠습니다.
1import { useEffect } from 'react';
2import { useRouter } from 'next/router';
3import { isTokenExpired } from 'path/to/your/isTokenExpiredFunction';
4import removeLoginCookie from 'path/to/your/removeLoginCookieFunction';
5
6function MyApp({ Component, pageProps }: AppProps) {
7 const router = useRouter();
8
9 useEffect(() => {
10 const handleRouteChange = async () => {
11 const accessToken = document.cookie.accessToken;
12 const isLoggedIn = accessToken && !isTokenExpired(accessToken);
13
14 // 예외 처리 페이지 목록
15 const exceptions = ['/auth/login', '/signup'];
16
17 if (!exceptions.includes(router.pathname)) {
18 if (!isLoggedIn) {
19 // 로그인이 되어 있지 않은 경우 로그인 페이지로 이동
20 removeLoginCookie();
21 router.push('/auth/login');
22 }
23 } else if (router.pathname === '/auth/login' && isLoggedIn) {
24 // 로그인 페이지에서 로그인 상태인 경우 메인 페이지로 이동
25 router.push('/');
26 }
27 };
28
29 handleRouteChange();
30 router.events.on('routeChangeComplete', handleRouteChange);
31
32 // 컴포넌트가 unmount될 때 이벤트 리스너를 제거합니다.
33 return () => {
34 router.events.off('routeChangeComplete', handleRouteChange);
35 };
36 }, [router]);
37
38 return <Component {...pageProps} />;
39}
40
41export default MyApp;
익명
작성자
2023년 05월 08일
위 방법을 사용한다면, next js middleware는 필요없게 되나요?
'Next.js'의 미들웨어를 사용해 리다이렉션을 처리할 때, 브라우저 캐시와 관련된 이슈로 보입니다. 브라우저는 페이지를 캐시하고, 뒤로 가기나 앞으로 가기 버튼을 클릭할 때 이 캐시된 페이지를 사용하게 됩니다. 이로 인해 미들웨어는 실행되지 않고, 따라서 리다이렉션이 발생하지 않습니다. 이 문제를 해결하기 위해 'Next.js' 애플리케이션의 모든 페이지에 'Cache-Control' 헤더를 추가할 수 있습니다. 이 헤더는 브라우저에게 페이지를 캐시하지 않도록 지시합니다. '_document.tsx' 파일에서 아래의 코드를 추가할 수 있습니다: 아래 코드는 모든 페이지에 'Cache-Control' 헤더를 추가하여 브라우저 캐시를 막습니다. 이로 인해 브라우저의 뒤로 가기나 앞으로 가기 버튼을 클릭할 때마다 'Next.js' 미들웨어가 항상 실행되도록 할 수 있습니다. 하지만, 이런 방법은 페이지 로딩 성능에 영향을 줄 수 있으므로 신중하게 고려해야 합니다. 다른 방법으로는, 로그인 상태를 클라이언트 측에서 검증하고 필요에 따라 리다이렉션을 수행하는 것입니다. 이렇게 하면 서버 측 미들웨어에서 처리하는 것보다 더 유연하게 상황을 처리할 수 있습니다. React의 useEffect 훅을 사용하여 로그인 상태를 확인하고, 상태에 따라 사용자를 리다이렉션 할 수 있습니다. 이 경우, 브라우저의 뒤로 가기/앞으로 가기 동작에 대한 문제를 피할 수 있습니다. 다만, 이런 방법은 보안상의 문제가 있을 수 있습니다. 클라이언트 측에서 로그인 상태를 검증하는 것은 서버 측에서 검증하는 것보다 보안에 취약할 수 있으므로 이 점을 고려해야 합니다.
1import Document, { Html, Head, Main, NextScript } from 'next/document'
2
3class MyDocument extends Document {
4 render() {
5 return (
6 <Html>
7 <Head>
8 <meta httpEquiv="Cache-Control" content="no-store" />
9 </Head>
10 <body>
11 <Main />
12 <NextScript />
13 </body>
14 </Html>
15 )
16 }
17}
18
19export default MyDocument
커리어리 AI 봇의 답변을 평가해 주세요!
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
지금 가입하면 모든 질문의 답변을 볼 수 있어요!