카테고리 없음

nextAuth supabase 소셜로그인 상태유지

윤미주 2024. 4. 4. 17:27

supabase에 이메일 값 전달

import { getLoginUserType } from '@/types/authUser/authUserTypes';
import { supabase } from '../supabase/supabase';

export const getUserIdByEmail = async (email: string): Promise<getLoginUserType> => {
  const { data, error } = await supabase //
    //테이블 이름
    .from('users')
    // 컬럼
    .select('user_id')
    //필터
    .eq('email', email as string)
    .single();
  if (error || !data) throw error;
  return data;
};

 

쿼리를 이용해 email 전달

import { getUserIdByEmail } from '@/app/api/userEmail/loginUserId';
import { getLoginUserType } from '@/types/authUser/authUserTypes';
import { useQuery } from '@tanstack/react-query';

export function useReadLoginUserId(email: string) {
  return useQuery<getLoginUserType, Error>({
    queryKey: ['LoginUserId', { email }],
    queryFn: () => getUserIdByEmail(email),
    //이메일 존재할때만 쿼리 실행
    enabled: !!email
  });
}

 

 

로그인 상태유지

nextAuth에서 주는 세션으로 로그인 상태유지를 하려고 하는 경우

새로고침 시 세션에 값을 불러오기 전까지 상태유지가 잠시 풀리는 경우가 발생

 

브라우저스토리지, 로컬스토리지, 세션스토리지 에 세션에서 주는 유저의 email을 담아서 사용

 

로그인 시 세션에 저장되는 값을 세션스토리지에 담기

'use client';

import { useEffect } from 'react';
import { useSession } from 'next-auth/react';
import { supabase } from '@/app/api/supabase/supabase';

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

  useEffect(() => {
    // 최초 실행 시 현재 세션의 이메일 주소를 sessionStorage에 저장
    const userEmail = session?.user?.email;
    if (userEmail) {
      sessionStorage.setItem('userEmail', userEmail);
    }

    // Supabase 인증 상태 변경 시 콜백 함수
    // supabase.auth.onAuthStateChange를 통해 생성된 리스는 사용자 인증상태가 변할 떄마다 실행됨.
    // 생명 주기동안 계속 실행됙 ㅣ때문에 사용자가 해당 페이지를 벗어나면 해제해 줘야함 (메모리누수)
    const { data: authListener } = supabase.auth.onAuthStateChange((event, session) => {
      const currentEmail = session?.user?.email;
      if (event === 'SIGNED_IN' && currentEmail) {
        // 로그인 시 이메일 주소가 있으면 저장
        sessionStorage.setItem('userEmail', currentEmail);
      }
    });

    return () => {
      // 정리해주는 코드
      // session이 변경되어 useEffect가 재실행 되기전에 깨깟이 정리해줌 (메모리 누수 방지)
      authListener.subscription.unsubscribe();
    };
  }, [session]);

  const userEmail = sessionStorage.getItem('userEmail');

  return userEmail;
}

 

로그아웃 시 세션스토리지 값 지우기

'use client';
import { useUserEmail } from '@/hooks/useLogin/useUserEmail';
import { signOut } from 'next-auth/react';
import Link from 'next/link';

export default function LoginState() {
  const userEmail = useUserEmail();

  const handleLogout = async () => {
    sessionStorage.removeItem('userEmail');
    await signOut({ redirect: true, callbackUrl: '/' });
  };

  return <div>{userEmail ? <button onClick={handleLogout}>Logout</button> : <Link href="/hello">Login</Link>}</div>;
}