Files
zellyy-finance/src/hooks/auth/useAppwriteAuth.ts
hansoo 9851627ff1 feat: Add CI/CD pipeline and code quality improvements
- Add GitHub Actions workflow for automated CI/CD
- Configure Node.js 18.x and 20.x matrix testing
- Add TypeScript type checking step
- Add ESLint code quality checks with enhanced rules
- Add Prettier formatting verification
- Add production build validation
- Upload build artifacts for deployment
- Set up automated testing on push/PR
- Replace console.log with environment-aware logger
- Add pre-commit hooks for code quality
- Exclude archive folder from linting

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-12 15:27:54 +09:00

187 lines
4.1 KiB
TypeScript

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<AuthState>({
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;