본문 바로가기

개발 공부/React

Next.js- cookies().get(), middleware 로그인 유지

SSR 시 로그인 유지 (cookies().get() 이용)

  • 페이지 진입 시 서버에서 쿠키(token)를 읽고
  • Redux에 로그인 정보를 세팅하여
  • 새로고침하거나 직접 URL로 접속해도 로그인 상태 유지

방법

  • app/page.tsx를 서버 컴포넌트로 만들고
  • cookies()를 이용해 쿠키에서 token을 읽어옴
  • Redux 초기화를 위한 상태 전달은 props 또는 hydration 방식

 

 

1. app/page.tsx → 서버 컴포넌트로 변경

// app/page.tsx (❌ "use client" 제거)

import { cookies } from "next/headers";
import HomeClient from "./HomeClient";

export default function HomePage() {
  const cookieStore = cookies();
  const token = cookieStore.get("token")?.value;

  // 토큰이 있다면 임의 유저 정보 설정 (실제 프로젝트에선 API 호출 필요)
  const user = token
    ? { id: "1", name: "테스트유저", email: "test@test.com" }
    : null;

  return <HomeClient user={user} token={token} />;
}

 

 

2. 클라이언트 컴포넌트 분리 (app/HomeClient.tsx)

'use client';

import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { RootState } from '@/store';
import { logout, setAuth } from '@/store/slices/authSlice';
import { useRouter } from 'next/navigation';

interface Props {
  user: {
    id: string;
    name: string;
    email: string;
  } | null;
  token: string | null;
}

export default function HomeClient({ user, token }: Props) {
  const reduxUser = useSelector((state: RootState) => state.auth.user);
  const dispatch = useDispatch();
  const router = useRouter();

  // 클라이언트에서 Redux 초기화 (최초 진입 시 1회만)
  useEffect(() => {
    if (user && token) {
      dispatch(setAuth({ user, token }));
    }
  }, [dispatch, user, token]);

  const handleLogout = async () => {
    await fetch('/api/logout');
    dispatch(logout());
    router.push('/login');
  };

  return (
    <main className="p-10">
      <h1 className="text-2xl font-bold">홈페이지</h1>
      {reduxUser ? (
        <>
          <p className="mt-4">환영합니다, {reduxUser.name}님!</p>
          <button
            onClick={handleLogout}
            className="mt-4 bg-red-500 text-white px-4 py-2 rounded"
          >
            로그아웃
          </button>
        </>
      ) : (
        <div className="mt-4 text-red-500">
          <p>로그인하지 않았습니다.</p>
          <button
            onClick={() => router.push('/login')}
            className="mt-2 bg-blue-500 text-white px-4 py-2 rounded"
          >
            로그인하러 가기
          </button>
        </div>
      )}
    </main>
  );
}

 

 

위치 동작
app/page.tsx 서버에서 cookies()로 토큰 추출
HomeClient.tsx 클라이언트에서 Redux 상태 초기화 (setAuth)
페이지 새로고침 시 서버 + 클라이언트 분리 작동 → 로그인 유지됨

 

 


로그인 보호 미들웨어 (middleware.ts)

  • 로그인 안 된 사용자가 특정 페이지에 접근하면 /login으로 리다이렉트

 

middleware란

요청(Request)이 들어올 때 그것을 가로채서 검사하거나 조작하고, 다음 단계로 넘겨주는 역할을 합니다.

Next.js에서의 middleware는 페이지가 렌더링되기 전에 실행되는 서버 사이드 코드입니다.

 

1. middleware.ts 생성

// middleware.ts

import { NextRequest, NextResponse } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')?.value;

  const protectedPaths = ['/mypage', '/settings'];

  const pathname = request.nextUrl.pathname;

  const isProtected = protectedPaths.includes(pathname);

  if (isProtected && !token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  return NextResponse.next();
}

 

 

상황 결과
로그인 쿠키가 있으면 SSR에서 Redux에 로그인 상태 저장
로그인 쿠키가 없는데 보호 페이지 접근 middleware가 /login으로 리다이렉트
로그인하면 쿠키 + Redux 저장됨 새로고침해도 유지됨
로그아웃하면 쿠키 제거 + Redux 초기화 접근 시 /login으로 튕김

'개발 공부 > React' 카테고리의 다른 글

Next.js - 동적 라우팅  (0) 2025.05.14
Next.js - layout.tsx, children  (0) 2025.05.11
Next.js, Redux - 로그인/로그아웃  (0) 2025.05.06
Redux login 예시  (0) 2025.05.05
getStaticProps, getStaticPaths  (0) 2025.04.26