Next.js) 인증이 필요한 페이지 리다이렉션 분기처리

ynnsuis·2023년 7월 5일
3

팀 프로젝트를 진행하면서 특정 페이지를 접근시 리다이렉션을 해줘야하는 로직을 작성 해야할 일이 있었다.
예를 들면 로그인되지 않은 상태에서 마이페이지, 글 작성페이지의 접근을 막아야했고 유저경험을 향상시키기 위해 로그인 된 상태에선 로그인, 회원가입 등 auth와 관련된 페이지들 접근을 막아야했다.

클라이언트 단에서의 분기처리 로직

SSR 프레임워크의 경험이 거의 없다보니 처음에는 각 페이지 컴포넌트 내에서 조건문을 통해 분기처리를 했다. 처음 작성한 코드는 이랬다.

const MyPage = ({ initialCurrentUser }: { initialCurrentUser: User }) => {
  const router = useRouter();
  // 로그인한 유저정보를 패치해오는 로직
  const { data: currentUser } = useQuery<User>(
    ["currentUser"],
    () => getCurrentUser(),
    {
      initialData: initialCurrentUser,
    }
  );

  // 리다이렉트하는 로직
  if (!currentUser) {
    router.replace("/auth/login");
  }

  return (
    <Container>
    <Wrapper>
      <ProfileCard />
      <RecipeCards />
    </Wrapper>
  </Container>
  );
};

문제 : 리다이렉션 직전에 잠깐 렌더링되는 JSX요소들

문제는 코드를 이렇게 작성할 경우, 이런식으로 MyPage의 JSX요소가 살짝 노출되고 리다이렉트가 되었는것이었다.

원인을 찾아보니까 리다이렉트 명령이 처리되고, 실행되는 도중에 JSX 요소가 렌더링 되어서 생기는 현상이었다.

이 문제를 해결하기위해 리다이렉트 로직에 return null을 추가했봤다.

  // 리다이렉트하는 로직
  if (!currentUser) {
    router.replace("/auth/login");
    return null
  }

이렇게 하면, 리다이렉트가 실행될땐 MyPage의 JSX구문을 렌더링하지 않으니 해당페이지를 숨길수 있다.

일단 1차적인 목표인 페이지 접근을 막는것에는 성공했다. 하지만 여전히 깜빡거리는 페이지와 잠깐 사이에 렌더링되는 공용레이아웃이 너무 거슬렸다. 완벽한 해결방법이 아니였다. 계속 열심히 구글링과 공식문서를 찾아보았다.

해결 : Next.js Middleware

열심히 해결방법을 찾아보다가 Next.js 공식문서에서 Middleware라는 기능을 발견했다.

Middleware allows you to run code before a request is completed. Then, based on the incoming request, you can modify the response by rewriting, redirecting, modifying the request or response headers, or responding directly.

해석해보면 미들웨어는 요청이 완료되기전에 코드를 실행하는걸 도와준다. 들어오는 요청에 따라 요청 또는 응답 헤더를 다시 작성, 리디렉션, 수정하거나 직접 응답하여 응답을 수정할 수 있다고 한다. 딱 내가 찾던 기능이였다.

공식 문서에 나와있는대로 Root 폴더에 Middleware.ts 라는 파일을 만들고

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 

export function middleware(request: NextRequest) {
  // 리다이렉트 조건
  if (
    !request.cookies.get("session-id")
  ) {
    return NextResponse.redirect(new URL("/auth/login", request.url));
  }
}
 

export const config = {
  // 이 Middleware가 동작할 경로들을 추가해주면된다.
  matcher: '/my-page/:path*',
}

이런식으로 쿠키에 session-id값이 없으면 Login 페이지로 리다이렉트하는 코드를 추가했다. 이 코드는 matcher 부분에 작성된 /my-page/ 로 시작하는 경로에서만 동작하게하였다. 그 결과는...!

대성공이였다. 서버단에서 요청을 처리하니까 다른 화면을 렌더링하지않고 바로 Login페이지로 매끄럽게 리다이렉트를 할수있었다. Next.js은 정말 배울때부터 너무 마음에들었고, 실제로 사용해 볼수록 놀라운 프레임워크인것 같다.

0개의 댓글