✏️기록하는 즐거움
article thumbnail
반응형

📙 개요

개발환경
next: v14.2.15
next-auth: v5.0.0-beta.25

 

로그인 상태에서 새로 고침 시 로그인 버튼이 보이면서 깜빡이는 현상

Next-Auth v5를 사용하여 Header에 유저 정보를 표시하던 중에 페이지를 새로 고침할 때 session과 관련된 조건부 렌더링 부분에서 깜빡임 현상이 발생했다.

관련 코드는 다음과 같다.

"use client";

import { useSession } from "next-auth/react";


export default function Header() {
  const { data: session } = useSession();

  return (
   // ...
    <div>
      {session  ? (
        <>
          <div>
            {session.user?.image && (
              <Image
                src={session.user.image}
                alt=""
                width={36}
                height={36}
              />
            )}
          </div>
          <Button>
            로그아웃
          </Button>
        </>
      ) : (
        <>
          <Link href="/login">
            로그인
          </Link>
          <Link href="/signup">
            회원가입
          </Link>
        </>
      )}
    </div>
  );
}

Header 컴포넌트는 클라이언트 컴포넌트이기 때문에 useSession() 훅을 사용하여 session 값을 가져와 조건부로 화면을 렌더링하고 있다.

 

📙 문제 분석

깜빡임 현상이 발생하는 이유는 로그인 상태에서 새로고침 시 세션 값을 비동기적으로 가져오는 과정에서 세션이 로드되기 전까지 status가 loading 상태이기 때문이다. 이 loading 상태와 실제 로드 완료 사이의 간격으로 인해 로그인 버튼이 순간적으로 보이게 된다.

 

loading 상태일 때 다른 화면을 보여주는 것도 가능하지만, 이 역시 사용자 경험을 저하시킬 수 있다.

그렇다면 어떻게 해결할 수 있을까?

 

나의 경우 useSession() 훅을 사용하는 대신, 서버 컴포넌트에서 세션 정보를 가져와 클라이언트 컴포넌트로 props를 전달하는 방식으로 해결했다.

서버에서 세션 정보를 가져오면 렌더링 시점에 세션 데이터를 제공하기 때문에, 클라이언트에서는 초기 로딩 상태 없이 즉시 세션 정보를 활용할 수 있다.

 

📙 서버에서 session 값을 가져와 클라이언트 컴포넌트에 전달하기

1. auth() 훅으로 서버에서 session 값 가져오기

import { auth } from "auth";

import Header from "@/_component/common/Header";

export default async function HeaderLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const session = await auth(); // 서버에서 세션 값 가져오기

  return (
    <>
      <Header session={session} />
    </>
  );
}

Next-Auth v5 이전에는 getServerSessioin() 으로 서버에서 세션 값을 가져올 수 있었지만, v5 이후에는 auth() 로 가져올 수 있다.

 

v4에서 v5로 업그레이드 되면서 달라진 메소드들

 

2. 클라이언트 컴포넌트에서 세션 사용하기

"use client";

import { Session } from "next-auth";

interface Props {
     session: Session | null;
}

export default function Header({ session }: Props) {

  return (
   // ...
    <div>
      {session  ? (
        <>
          <div>
            {session.user?.image  && (
              <Image
                src={session.user.image}
                alt=""
                width={36}
                height={36}
              />
            )}
          </div>
          <Button>
            로그아웃
          </Button>
        </>
      ) : (
        <>
          <Link href="/login">
            로그인
          </Link>
          <Link href="/signup">
            회원가입
          </Link>
        </>
      )}
    </div>
  );
}

로그인 상태에서 새로 고침을 하여도 로그인 버튼이 보이지 않음

 

📙 로그인을 하면 바로 업데이트가 되지 않는다 ?!

Header 컴포넌트에 서버에서 받은 session 정보를 전달하여 사용하는 방식은 새로고침 시 초기 세션 로딩 문제는 해결하지만, 로그인이나 로그아웃과 같은 상태 변화가 발생할 때 Header 컴포넌트가 즉시 업데이트되지 않는 문제가 있다.

 

즉, 로그인 이후 새로고침이 되기 전까지는 사용자 프로필이 아닌 로그인 버튼이 보이게 된다.

 

이는 서버에서 렌더링된 세션 데이터를 업데이트하려면 클라이언트와 서버 간에 동기화가 필요하기 때문이다.

이 문제는 서버에서 가져온 세션을 Header 컴포넌트에 전달하여 초기값으로 사용하면서, Header 컴포넌트에서 세션 상태를 갱신하도록 수정하여 해결할 수 있다.

 

"use client";

import { Session } from "next-auth";

interface Props {
     intialSession: Session | null;
}

export default function Header({ intialSession }: Props) {
  const { data: session } = useSession(); // 세션 상태 가져오기

  const activeSession = session || initialSession; // 갱신

  return (
   // ...
    <div>
      {activeSession ? (
        <>
          <div>
            {activeSession.user?.image && (
              <Image
                src={activeSession.user.image}
                alt=""
                width={36}
                height={36}
              />
            )}
          </div>
          <Button>
            로그아웃
          </Button>
        </>
      ) : (
        <>
          <Link href="/login">
            로그인
          </Link>
          <Link href="/signup">
            회원가입
          </Link>
        </>
      )}
    </div>
  );
}

클라이언트에서의 세션과 구별하기 위해 서버에서 전달받는 세션의 이름을 initialSession 으로 수정해주었다.

업데이트된 session 값이 있으면 해당 값을 사용하고, 없다면 서버에서 가져온 초기 세션 값을 사용함으로써 새로 고침 시의 깜빡임 현상과 로그인 이후 컴포넌트 업데이트 문제를 모두 해결할 수 있다.

반응형
profile

✏️기록하는 즐거움

@nor_coding

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!