/** * 인증 관련 Alpine.js 컴포넌트 */ // 인증 모달 컴포넌트 window.authModal = () => ({ showLogin: false, loginForm: { email: '', password: '' }, loginError: '', loginLoading: false, async login() { this.loginLoading = true; this.loginError = ''; try { const response = await api.login(this.loginForm.email, this.loginForm.password); // 토큰 저장 api.setToken(response.access_token); localStorage.setItem('refresh_token', response.refresh_token); // 사용자 정보 로드 const user = await api.getCurrentUser(); // 전역 상태 업데이트 window.dispatchEvent(new CustomEvent('auth-changed', { detail: { isAuthenticated: true, user } })); // 모달 닫기 this.showLogin = false; this.loginForm = { email: '', password: '' }; } catch (error) { this.loginError = error.message; } finally { this.loginLoading = false; } }, async logout() { try { await api.logout(); } catch (error) { console.error('Logout error:', error); } finally { // 로컬 스토리지 정리 localStorage.removeItem('refresh_token'); // 전역 상태 업데이트 window.dispatchEvent(new CustomEvent('auth-changed', { detail: { isAuthenticated: false, user: null } })); } } }); // 자동 토큰 갱신 async function refreshTokenIfNeeded() { const refreshToken = localStorage.getItem('refresh_token'); if (!refreshToken || !api.token) return; try { // 토큰 만료 확인 (JWT 디코딩) const tokenPayload = JSON.parse(atob(api.token.split('.')[1])); const now = Date.now() / 1000; // 토큰이 5분 내에 만료되면 갱신 if (tokenPayload.exp - now < 300) { const response = await api.refreshToken(refreshToken); api.setToken(response.access_token); localStorage.setItem('refresh_token', response.refresh_token); } } catch (error) { console.error('Token refresh failed:', error); // 갱신 실패시 로그아웃 api.setToken(null); localStorage.removeItem('refresh_token'); window.dispatchEvent(new CustomEvent('auth-changed', { detail: { isAuthenticated: false, user: null } })); } } // 5분마다 토큰 갱신 체크 setInterval(refreshTokenIfNeeded, 5 * 60 * 1000);