Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: useAuth 중복수정 #90

Merged
merged 5 commits into from
Jan 1, 2025
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
268 changes: 155 additions & 113 deletions src/hooks/use-auth.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* eslint-disable*/

/*eslint-disable*/
"use client";

import { create } from "zustand";

import { deleteCookie, getCookie, setCookie } from "@/utils/next-cookies";

interface LoginResponse {
Expand All @@ -24,141 +22,104 @@ interface AuthStore {
deposit: number | null;
isAuthenticated: boolean;
isInitialized: boolean;
isInitializing: boolean;
setAuth: (response: LoginResponse) => Promise<void>;
clearAuth: () => Promise<void>;
initAuth: () => Promise<void>;
}

/**
* 인증 토큰을 관리하는 Zustand 스토어 훅
* 인증 상태를 관리하는 Zustand 스토어 훅
*
* @example
* // 1. 컴포넌트에서 토큰 관리
* import { useAuth } from '@/hooks/useAuth';
* @description
* - 로그인/로그아웃 상태 관리
* - 토큰 및 사용자 정보 관리
* - 쿠키 기반의 인증 상태 유지
* - 중복 초기화 방지 로직 포함
*
* function LoginComponent() {
* @example
* // 1. 로그인 처리
* const LoginComponent = () => {
* const { setAuth } = useAuth();
*
* const handleLogin = async () => {
* const response = await fetch('/api/login');
* const data = await response.json();
* await setAuth(data); // 로그인 후 인증 정보 저장
* const response = await loginAPI();
* await setAuth(response);
* };
* }
* };
*
* @example
* // 2. API 요청시 토큰 사용
* function ProtectedComponent() {
* const { token } = useAuth();
* // 2. 인증이 필요한 API 요청
* const ProtectedComponent = () => {
* const { token, isInitialized } = useAuth();
*
* const fetchData = async () => {
* const response = await fetch('/api/protected', {
* headers: {
* 'Authorization': `Bearer ${token}`
* }
* });
* };
* }
* useEffect(() => {
* if (!isInitialized) return;
*
* const fetchData = async () => {
* const response = await fetch('/api/protected', {
* headers: { Authorization: `Bearer ${token}` }
* });
* };
*
* fetchData();
* }, [isInitialized, token]);
* };
*
* @example
* // 3. 컴포넌트 마운트시 인증 상태 초기화
* function App() {
* // 3. 앱 초기화시 인증 상태 복원
* const App = () => {
* const { initAuth } = useAuth();
*
* useEffect(() => {
* initAuth(); // 페이지 로드시 쿠키에서 인증 정보 복원
* initAuth();
* }, []);
* }
* };
*
* @example
* // 4. 로그아웃시 인증 정보 제거
* function LogoutButton() {
* const { clearAuth } = useAuth();
*
* const handleLogout = async () => {
* await clearAuth(); // 로그아웃시 인증 정보 삭제
* await clearAuth();
* };
* }
*/

export const useAuth = create<AuthStore>((set) => ({
token: null,
memberId: null,
memberName: null,
memberNickName: null,
annualIncome: null,
deposit: null,
isAuthenticated: false,
isInitialized: false,

setAuth: async (response: LoginResponse) => {
const {
token,
memberId,
memberName,
memberNickName,
annualIncome,
deposit,
} = response;

// Store all relevant data in cookies
await setCookie("token", token);
await setCookie("memberId", memberId.toString());
await setCookie("memberName", memberName);
await setCookie("memberNickName", memberNickName);
await setCookie("annualIncome", annualIncome.toString());
await setCookie("deposit", deposit.toString());

set({
token,
memberId,
memberName,
memberNickName,
annualIncome,
deposit,
isAuthenticated: true,
isInitialized: true,
});
},

clearAuth: async () => {
// Clear all cookies
await deleteCookie("token");
await deleteCookie("memberId");
await deleteCookie("memberName");
await deleteCookie("memberNickName");
await deleteCookie("annualIncome");
await deleteCookie("deposit");

set({
token: null,
memberId: null,
memberName: null,
memberNickName: null,
annualIncome: null,
deposit: null,
isAuthenticated: false,
isInitialized: true,
});
},

initAuth: async () => {
try {
set({ isInitialized: false });

const token = await getCookie("token");
const memberIdStr = await getCookie("memberId");
const memberName = await getCookie("memberName");
const memberNickName = await getCookie("memberNickName");
const annualIncomeStr = await getCookie("annualIncome");
const depositStr = await getCookie("deposit");

// Convert string values back to numbers
const memberId = memberIdStr ? parseInt(memberIdStr, 10) : null;
const annualIncome = annualIncomeStr
? parseInt(annualIncomeStr, 10)
: null;
const deposit = depositStr ? parseInt(depositStr, 10) : null;
export const useAuth = create<AuthStore>((set, get) => {
let initPromise: Promise<void> | null = null;

return {
token: null,
memberId: null,
memberName: null,
memberNickName: null,
annualIncome: null,
deposit: null,
isAuthenticated: false,
isInitialized: false,
isInitializing: false,

setAuth: async (response: LoginResponse) => {
const {
token,
memberId,
memberName,
memberNickName,
annualIncome,
deposit,
} = response;

// 모든 쿠키 설정을 병렬로 처리
await Promise.all([
setCookie("token", token),
setCookie("memberId", memberId.toString()),
setCookie("memberName", memberName),
setCookie("memberNickName", memberNickName),
setCookie("annualIncome", annualIncome.toString()),
setCookie("deposit", deposit.toString()),
]);

set({
token,
Expand All @@ -167,12 +128,93 @@ export const useAuth = create<AuthStore>((set) => ({
memberNickName,
annualIncome,
deposit,
isAuthenticated: !!token,
isAuthenticated: true,
isInitialized: true,
});
},

clearAuth: async () => {
// 모든 쿠키 삭제를 병렬로 처리
await Promise.all([
deleteCookie("token"),
deleteCookie("memberId"),
deleteCookie("memberName"),
deleteCookie("memberNickName"),
deleteCookie("annualIncome"),
deleteCookie("deposit"),
]);

set({
token: null,
memberId: null,
memberName: null,
memberNickName: null,
annualIncome: null,
deposit: null,
isAuthenticated: false,
isInitialized: true,
});
} catch (error) {
set({ isInitialized: true });
throw error;
}
},
}));
},

initAuth: async () => {
if (get().isInitialized) {
return;
}

if (initPromise) {
return initPromise;
}

initPromise = (async () => {
try {
set({ isInitializing: true });

// 모든 쿠키 조회를 병렬로 처리
const [
token,
memberIdStr,
memberName,
memberNickName,
annualIncomeStr,
depositStr,
] = await Promise.all([
getCookie("token"),
getCookie("memberId"),
getCookie("memberName"),
getCookie("memberNickName"),
getCookie("annualIncome"),
getCookie("deposit"),
]);

const memberId = memberIdStr ? parseInt(memberIdStr, 10) : null;
const annualIncome = annualIncomeStr
? parseInt(annualIncomeStr, 10)
: null;
const deposit = depositStr ? parseInt(depositStr, 10) : null;

set({
token,
memberId,
memberName,
memberNickName,
annualIncome,
deposit,
isAuthenticated: !!token,
isInitialized: true,
isInitializing: false,
});
} catch (error) {
set({
isInitialized: true,
isInitializing: false,
});
throw error;
} finally {
initPromise = null;
}
})();

return initPromise;
},
};
});
Loading