programming/React

Auth.js signIn 완료 후 session 이 여전히 null (수동 리프레시를 해야만 session 이 업데이트 됨)

euuuuuz: 2024. 10. 30. 09:23

 

참고 : https://github.com/nextauthjs/next-auth/issues/9504#issuecomment-2326123445

 

 

[BEFORE]

layout.tsx 

import Footer from "@/components/footer";
import Header from "@/components/header";
import ReactQueryProvider from "@/components/provider/ReactQueryProvider";
import type { Metadata } from "next";
import { SessionProvider } from "next-auth/react";
import localFont from "next/font/local";
import { ToastContainer } from "react-toastify";
import "./globals.scss";

import "react-toastify/dist/ReactToastify.css";

const pretendard = localFont({
  src: "./fonts/PretendardVariable.woff2",
  display: "swap",
  weight: "45 920",
  variable: "--font-pretendard",
});

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="kr">
      <body className={`${pretendard.variable} font-pretendard antialiased`}>
        <ReactQueryProvider>
          <SessionProvider>
            <div id="modal-root" />
            <ToastContainer />
            <Header />
            {children}
            <Footer />
          </SessionProvider>
        </ReactQueryProvider>
      </body>
    </html>
  );
}

 

 

 

[AFTER]

layout.tsx

import Footer from "@/components/footer";
import Header from "@/components/header";
import ReactQueryProvider from "@/components/provider/ReactQueryProvider";
import type { Metadata } from "next";
import localFont from "next/font/local";
import { ToastContainer } from "react-toastify";
import "./globals.scss";

import { auth } from "@/auth";
import AuthSessionProvider from "@/components/provider/AuthSessionProvider";
import "react-toastify/dist/ReactToastify.css";

const pretendard = localFont({
  src: "./fonts/PretendardVariable.woff2",
  display: "swap",
  weight: "45 920",
  variable: "--font-pretendard",
});

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  const session = await auth();
  const sessionKey = new Date().valueOf();

  return (
    <html lang="kr">
      <body className={`${pretendard.variable} font-pretendard antialiased`}>
        <ReactQueryProvider>
          <AuthSessionProvider session={session} sessionKey={sessionKey}>
            <div id="modal-root" />
            <ToastContainer />
            <Header />
            {children}
            <Footer />
          </AuthSessionProvider>
        </ReactQueryProvider>
      </body>
    </html>
  );
}

 

provider/AuthSessionProvider 프로바이더 컴포넌트를 생성

// AuthSessionProvider.tsx
"use client";

import { SessionProvider } from "next-auth/react";
import { useMemo } from "react";

export default function AuthSessionProvider({ children, ...props }: any) {
  const { session, sessionKey } = props;
  const memoizedSessionKey = useMemo(() => {
    return sessionKey;
  }, [session]);

  return (
    <SessionProvider key={memoizedSessionKey} session={session}>
      {children}
    </SessionProvider>
  );
}

 

 

signIn 성공 후 메인 페이지로 리다이렉트 되었을때, 

클라이언트 컴포넌트에서 useSession() 으로 호출하는 session 데이터나,

서버 컴포넌트에서 auth() / getSession() 등으로 호출하는 session 데이터 모두 바로 authorized 상태와 유저 정보가 업데이트 된다