feat: 로그인 버튼 생성
This commit is contained in:
62
src/store/useAuthStore.ts
Normal file
62
src/store/useAuthStore.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { create } from 'zustand';
|
||||
import Cookies from 'js-cookie';
|
||||
import { AuthResponse } from '@/features/auth/types';
|
||||
|
||||
interface AuthState {
|
||||
accessToken: string | null;
|
||||
user: AuthResponse['user'] | null;
|
||||
isAuthenticated: boolean;
|
||||
|
||||
// 액션
|
||||
setAuth: (data: AuthResponse) => void;
|
||||
logout: () => void;
|
||||
}
|
||||
|
||||
// 쿠키 키 상수 정의 (Access Token 보관용)
|
||||
const TOKEN_COOKIE_KEY = 'vr_access_token';
|
||||
|
||||
/**
|
||||
* VibeRoom 전역 인증(Auth) 상태 저장소
|
||||
*
|
||||
* Zustand를 활용하여 메모리에 상태를 쥐고 있으면서,
|
||||
* 쿠키(js-cookie)를 통해 브라우저 종료 후에도 세션이 유지되도록 동기화합니다.
|
||||
*/
|
||||
export const useAuthStore = create<AuthState>((set) => {
|
||||
// 브라우저 환경에서만 쿠키 접근
|
||||
const isClient = typeof window !== 'undefined';
|
||||
const savedToken = isClient ? Cookies.get(TOKEN_COOKIE_KEY) : null;
|
||||
|
||||
return {
|
||||
accessToken: savedToken || null,
|
||||
user: null, // 새로고침 시 이 토큰을 기반으로 유저 정보(me API)를 다시 가져와야 합니다(Hydrate).
|
||||
isAuthenticated: !!savedToken,
|
||||
|
||||
setAuth: (data: AuthResponse) => {
|
||||
// 1. 브라우저 쿠키에 저장 (보안 옵션 설정)
|
||||
Cookies.set(TOKEN_COOKIE_KEY, data.accessToken, {
|
||||
expires: 7, // 7일 후 만료
|
||||
secure: process.env.NODE_ENV === 'production', // HTTPS 환경에서만 전송
|
||||
sameSite: 'strict' // CSRF 공격 방어
|
||||
});
|
||||
|
||||
// 2. Zustand 메모리 상태 업데이트 (연결된 UI 전체 리렌더링)
|
||||
set({
|
||||
accessToken: data.accessToken,
|
||||
user: data.user,
|
||||
isAuthenticated: true
|
||||
});
|
||||
},
|
||||
|
||||
logout: () => {
|
||||
// 1. 쿠키에서 토큰 삭제
|
||||
Cookies.remove(TOKEN_COOKIE_KEY);
|
||||
|
||||
// 2. Zustand 상태 초기화
|
||||
set({
|
||||
accessToken: null,
|
||||
user: null,
|
||||
isAuthenticated: false
|
||||
});
|
||||
},
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user