본문 바로가기
카테고리 없음

stores/auth.js (초기화 상태 추가)

by 두잇건강 2025. 8. 6.
반응형
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import axios from 'axios'

export const useAuthStore = defineStore('auth', () => {
  // 상태
  const user = ref(null)
  const token = ref(localStorage.getItem('jwt-token'))
  const loading = ref(false)
  const error = ref('')
  const initialized = ref(false) // 초기화 상태 추가

  // 계산된 속성
  const isAuthenticated = computed(() => !!token.value && !!user.value)
  const userEmail = computed(() => user.value?.email || '')
  const userName = computed(() => user.value?.name || '')
  const userRoles = computed(() => user.value?.roles || [])
  const isAdmin = computed(() => userRoles.value.includes('ROLE_ADMIN'))

  // 인증 초기화
  const initializeAuth = async () => {
    if (initialized.value) return

    loading.value = true
    
    try {
      const savedToken = localStorage.getItem('jwt-token')
      const savedUser = localStorage.getItem('user-info')
      
      if (savedToken && savedUser) {
        token.value = savedToken
        user.value = JSON.parse(savedUser)
        setAuthToken(savedToken)
        
        // 토큰 유효성 검사
        try {
          await axios.get('/api/user/profile')
          // 토큰이 유효하면 사용자 정보 최신화
        } catch (error) {
          if (error.response?.status === 401) {
            // 토큰이 만료되었거나 유효하지 않음
            clearAuthData()
          }
        }
      }
    } catch (error) {
      console.error('인증 초기화 실패:', error)
      clearAuthData()
    } finally {
      loading.value = false
      initialized.value = true
    }
  }

  // 로그인
  const login = async (credentials) => {
    loading.value = true
    error.value = ''
    
    try {
      const response = await axios.post('/api/authenticate', credentials)
      
      if (response.data.jwt) {
        token.value = response.data.jwt
        user.value = {
          email: response.data.email || credentials.email,
          name: response.data.name || '',
          roles: response.data.roles || ['ROLE_USER'],
          id: response.data.userId || null
        }
        
        localStorage.setItem('jwt-token', response.data.jwt)
        localStorage.setItem('user-info', JSON.stringify(user.value))
        setAuthToken(response.data.jwt)
        
        return { success: true }
      }
    } catch (err) {
      error.value = err.response?.status === 401 
        ? '이메일 또는 비밀번호가 올바르지 않습니다.' 
        : '로그인 중 오류가 발생했습니다.'
      return { success: false, error: error.value }
    } finally {
      loading.value = false
    }
  }

  // 로그아웃
  const logout = async () => {
    loading.value = true
    
    try {
      await axios.post('/api/logout')
    } catch (err) {
      console.error('로그아웃 API 호출 실패:', err)
    } finally {
      clearAuthData()
      loading.value = false
    }
  }

  // 인증 데이터 정리
  const clearAuthData = () => {
    user.value = null
    token.value = null
    error.value = ''
    localStorage.removeItem('jwt-token')
    localStorage.removeItem('user-info')
    delete axios.defaults.headers.common['Authorization']
  }

  const setAuthToken = (authToken) => {
    if (authToken) {
      axios.defaults.headers.common['Authorization'] = `Bearer ${authToken}`
    } else {
      delete axios.defaults.headers.common['Authorization']
    }
  }

  return {
    // 상태
    user,
    token,
    loading,
    error,
    initialized,
    
    // 계산된 속성
    isAuthenticated,
    userEmail,
    userName,
    userRoles,
    isAdmin,
    
    // 액션
    login,
    logout,
    initializeAuth,
    clearAuthData
  }
})
반응형