import { useState, useEffect, useCallback } from "react"; import { account } from "@/lib/appwrite"; import { ID } from "appwrite"; // 인증 상태 인터페이스 interface AuthState { user: any | null; loading: boolean; error: Error | null; } // 로그인 입력값 인터페이스 interface LoginCredentials { email: string; password: string; } // 회원가입 입력값 인터페이스 interface SignupCredentials extends LoginCredentials { name?: string; } /** * Appwrite 인증 관련 훅 * 로그인, 로그아웃, 회원가입 및 사용자 상태 관리 */ export const useAppwriteAuth = () => { // 인증 상태 관리 const [authState, setAuthState] = useState({ user: null, loading: true, error: null, }); // 컴포넌트 마운트 상태 추적 const [isMounted, setIsMounted] = useState(true); // 사용자 정보 가져오기 const getCurrentUser = useCallback(async () => { try { const user = await account.get(); if (isMounted) { setAuthState({ user, loading: false, error: null, }); } return user; } catch (error) { if (isMounted) { setAuthState({ user: null, loading: false, error: error as Error, }); } return null; } }, [isMounted]); // 이메일/비밀번호로 로그인 const login = useCallback( async ({ email, password }: LoginCredentials) => { try { setAuthState((prev) => ({ ...prev, loading: true, error: null })); // 비동기 작업 시작 전 UI 스레드 차단 방지 await new Promise((resolve) => setTimeout(resolve, 0)); const session = await account.createEmailPasswordSession( email, password ); const user = await account.get(); if (isMounted) { setAuthState({ user, loading: false, error: null, }); } return { user, session }; } catch (error) { if (isMounted) { setAuthState((prev) => ({ ...prev, loading: false, error: error as Error, })); } throw error; } }, [isMounted] ); // 회원가입 const signup = useCallback( async ({ email, password, name }: SignupCredentials) => { try { setAuthState((prev) => ({ ...prev, loading: true, error: null })); // 비동기 작업 시작 전 UI 스레드 차단 방지 await new Promise((resolve) => setTimeout(resolve, 0)); const user = await account.create(ID.unique(), email, password, name); // 회원가입 후 자동 로그인 await account.createEmailPasswordSession(email, password); if (isMounted) { setAuthState({ user, loading: false, error: null, }); } return user; } catch (error) { if (isMounted) { setAuthState((prev) => ({ ...prev, loading: false, error: error as Error, })); } throw error; } }, [isMounted] ); // 로그아웃 const logout = useCallback(async () => { try { setAuthState((prev) => ({ ...prev, loading: true })); // 현재 세션 삭제 await account.deleteSession("current"); if (isMounted) { setAuthState({ user: null, loading: false, error: null, }); } } catch (error) { if (isMounted) { setAuthState((prev) => ({ ...prev, loading: false, error: error as Error, })); } throw error; } }, [isMounted]); // 초기 사용자 정보 로드 useEffect(() => { setIsMounted(true); getCurrentUser(); // 정리 함수 return () => { setIsMounted(false); }; }, [getCurrentUser]); return { user: authState.user, loading: authState.loading, error: authState.error, login, signup, logout, getCurrentUser, }; }; export default useAppwriteAuth;