/** * 인증 관련 Alpine.js 컴포넌트 */ // 인증 모달 컴포넌트 window.authModal = () => ({ showLogin: false, loginForm: { email: '', password: '' }, loginError: '', loginLoading: false, async login() { this.loginLoading = true; this.loginError = ''; try { // 실제 API 호출 const response = await window.api.login(this.loginForm.email, this.loginForm.password); // 토큰 저장 window.api.setToken(response.access_token); localStorage.setItem('refresh_token', response.refresh_token); // 사용자 정보 가져오기 const userResponse = await window.api.getCurrentUser(); // 전역 상태 업데이트 window.dispatchEvent(new CustomEvent('auth-changed', { detail: { isAuthenticated: true, user: userResponse } })); // 모달 닫기 (부모 컴포넌트의 상태 변경) window.dispatchEvent(new CustomEvent('close-login-modal')); this.loginForm = { email: '', password: '' }; } catch (error) { this.loginError = error.message || '로그인에 실패했습니다'; } finally { this.loginLoading = false; } }, async logout() { try { await window.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); // 갱신 실패시 로그아웃 window.api.setToken(null); localStorage.removeItem('refresh_token'); window.dispatchEvent(new CustomEvent('auth-changed', { detail: { isAuthenticated: false, user: null } })); } } // 5분마다 토큰 갱신 체크 setInterval(refreshTokenIfNeeded, 5 * 60 * 1000);