로그아웃 기능 구현 (+ notFound 처리)

Odyssey·2025년 3월 27일
0

Next.js_study

목록 보기
42/58
post-thumbnail

2025.3.28 금요일의 공부기록

내용 3줄 정리

  1. Next.js에서 getSession()을 통해 로그인 상태를 확인하고, 사용자가 없을 경우 notFound()를 호출해 내장 에러 페이지를 렌더링한다.
  2. 로그인 상태 확인 시 세션의 사용자 ID를 활용해 DB에서 사용자 정보를 조회한다.
  3. 로그아웃은 "use server" 환경에서 session.destroy() 후 redirect()를 사용해 메인 페이지로 이동시켜 세션을 종료한다.

📌 로그인 상태 확인 및 notFound 사용법

Next.js의 notFound() 함수는 사용자가 요청한 데이터를 찾을 수 없을 때 적절한 UI를 보여주는 데 유용하게 사용된다.
이 함수를 호출하면 즉시 Next.js의 내장된 not-found.tsx 페이지를 렌더링하며, 더 이상 컴포넌트가 렌더링되지 않는다.

  • notFound()는 반환값이 없으며, TypeScript의 never 타입으로 지정되어 있기 때문에 별도로 return notFound()와 같이 사용할 필요는 없다.

예시 코드

import db from "@/lib/db";
import { getSession } from "@/lib/session";
import { notFound } from "next/navigation";

async function getUser() {
  const session = await getSession();

  if (session?.userId) {
    const user = await db.user.findUnique({
      where: { id: session.userId },
    });

    if (user) {
      return user;
    }
  }

  // 사용자가 존재하지 않을 경우 NotFound 처리
  notFound();
}
  • 사용자가 존재하지 않으면 자동으로 not-found.tsx가 렌더링되어 사용자에게 자연스러운 에러 페이지를 보여준다.

📌 Next.js 공식 문서 - notFound()


로그아웃 기능 구현하기 (session.destroy())

로그아웃 기능은 매우 간단하게 세션을 파괴(destroy)하는 방식으로 구현된다. 세션을 파괴하면 세션에 저장된 사용자 정보는 삭제되며, 사용자 인증 상태가 즉시 해제된다.

로그아웃 함수 예시 코드 ("use server" 사용)

Next.js 14+에서는 form action에서 서버 액션을 통해 간단히 로그아웃을 처리할 수 있다.

import { redirect } from "next/navigation";
import { getSession } from "@/lib/session";

const logOut = async () => {
  "use server";
  const session = await getSession();
  session.destroy();  // 세션 파괴 (로그아웃)
  redirect("/");      // 로그아웃 후 메인 페이지로 이동
};
  • 서버 액션("use server")을 사용하여 서버에서 세션을 삭제하고, 클라이언트로 즉시 리다이렉트한다.

모든 기능을 통합한 완성 예제 코드 (Profile.tsx)

다음 코드는 로그인 상태 확인, 사용자 정보 조회, 로그아웃 기능, 사용자 미존재 시 notFound 처리를 모두 포함한 예제이다.

import db from "@/lib/db";
import { getSession } from "@/lib/session";
import { redirect, notFound } from "next/navigation";

// 사용자 조회 함수 (로그인 상태 확인)
async function getUser() {
  const session = await getSession();

  if (session?.userId) {
    const user = await db.user.findUnique({
      where: { id: session.userId },
    });

    if (user) {
      return user;
    }
  }

  // 사용자가 존재하지 않으면 NotFound 처리
  notFound();
}

export default async function Profile() {
  const user = await getUser();

  const logOut = async () => {
    "use server";
    const session = await getSession();
    session.destroy();
    redirect("/");
  };

  return (
    <div>
      <h1>Welcome! {user.username}!</h1>
      <form action={logOut}>
        <button>Logout</button>
      </form>
    </div>
  );
}

코드 설명 및 핵심 포인트 정리

  • 로그인 상태 확인: getSession()으로 현재 사용자의 세션 정보를 확인한다. 세션에서 얻은 사용자 ID로 Prisma를 통해 DB에서 사용자 정보를 조회한다.
  • notFound 처리: 사용자가 없거나 세션이 유효하지 않을 때는 즉시 notFound()를 호출하여 내장된 에러 페이지를 렌더링한다.
  • 로그아웃 기능: 서버 액션으로 구현된 logOut 함수를 통해 세션을 제거하고 사용자 인증 상태를 해제한다. 이후 즉시 메인 페이지(/)로 이동시킨다.

추가적인 고려 사항

  • 세션 쿠키 옵션에서 HttpOnly, Secure 옵션을 설정하여 보안을 더욱 강화한다.
  • session.destroy() 이후 추가로 쿠키나 캐시를 지워야 한다면, 필요한 로직을 추가로 구현할 수 있다.
  • 사용자가 로그아웃한 후 다시 로그인 페이지로 안내하거나 관련 메시지를 띄워주는 것도 좋은 UX이다.

0개의 댓글