이로

Vue3 Axios.create 설계 및 에러처리 본문

컴퓨터/자바스크립트

Vue3 Axios.create 설계 및 에러처리

利路 2024. 11. 26. 11:31
반응형

axios.create 주요 용도

 

  • 기본 설정 공통화
    • baseURL, timeout, headers 등의 공통 설정
    • 환경별(개발/스테이징/운영) 다른 설정 적용
    • 인증 토큰 등의 공통 처리
  • 요청/응답 전처리
    • 요청 전 헤더 설정
    • 응답 데이터 가공
    • 에러 처리 통합
  • 코드 재사용성
    • 여러 컴포넌트에서 동일한 설정 재사용
    • 설정 변경 시 한 곳에서 관리

 

설계

기본구조

// @/apis/modules/user-api.js
import { defaultAPI } from '../config/axios-config'

export const userAPI = {
  getProfile: () => defaultAPI.get('/user/profile'),
  updateProfile: (data) => defaultAPI.put('/user/profile', data),
  uploadAvatar: (file) => fileAPI.post('/user/avatar', file)
}

// @/apis/modules/auth-api.js
import { defaultAPI } from '../config/axios-config'

export const authAPI = {
  login: (credentials) => defaultAPI.post('/auth/login', credentials),
  logout: () => defaultAPI.post('/auth/logout'),
  refreshToken: () => defaultAPI.post('/auth/refresh')
}

// 컴포넌트에서 사용
<script setup>
import { userAPI } from '@/apis/modules/user-api'
import { authAPI } from '@/apis/modules/auth-api'

const handleLogin = async (credentials) => {
  try {
    const response = await authAPI.login(credentials)
    // 로그인 처리
  } catch (error) {
    // 에러 처리
  }
}
</script>

 

에러처리

// @/apis/utils/error-handler.js
export const handleAPIError = (error) => {
  const status = error.response?.status
  const errorCode = error.response?.data?.errorCode

  switch (errorCode) {
    case 'TOKEN_EXPIRED':
      return refreshTokenAndRetry(error)
    case 'VALIDATION_ERROR':
      return handleValidationError(error)
    default:
      return handleDefaultError(error)
  }
}

 

예 - case 1 Axios 인터셉터에서 사용

// @/apis/config/axios-config.js
import { handleAPIError } from '../utils/error-handler'

const instance = axios.create({
  baseURL: 'https://api.example.com'
})

instance.interceptors.response.use(
  response => response,
  error => handleAPIError(error)
)

 

예 - case 2 개별 API 호출에서 사용

 

// @/apis/modules/user-api.js
import { handleAPIError } from '../utils/error-handler'

export const userAPI = {
  updateProfile: async (userData) => {
    try {
      const response = await defaultAPI.put('/user/profile', userData)
      return response.data
    } catch (error) {
      return handleAPIError(error)
    }
  }
}

 

예 - case 3 API 모듈에서 사용

// @/views/Profile.vue
<template>
  <div>
    <form @submit.prevent="handleSubmit">
      <input v-model="profileData.name" />
      <button type="submit">저장</button>
    </form>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { userAPI } from '@/apis/modules/user-api'
import { handleAPIError } from '@/apis/utils/error-handler'

const profileData = ref({
  name: ''
})

const handleSubmit = async () => {
  try {
    await userAPI.updateProfile(profileData.value)
    // 성공 메시지 표시
    toast.success('프로필이 업데이트되었습니다.')
  } catch (error) {
    // 에러 핸들러가 처리
    handleAPIError(error)
  }
}
</script>

캐시처리

// @/apis/utils/cache-manager.js
const cacheManager = {
  set: (key, data, ttl) => {
    const item = {
      data,
      timestamp: Date.now(),
      ttl
    }
    localStorage.setItem(key, JSON.stringify(item))
  },
  
  get: (key) => {
    const item = JSON.parse(localStorage.getItem(key))
    if (!item) return null
    
    if (Date.now() - item.timestamp > item.ttl) {
      localStorage.removeItem(key)
      return null
    }
    
    return item.data
  }
}

// API 호출에 캐시 적용
const fetchWithCache = async (key, apiCall, ttl = 5 * 60 * 1000) => {
  const cachedData = cacheManager.get(key)
  if (cachedData) return cachedData
  
  const data = await apiCall()
  cacheManager.set(key, data, ttl)
  return data
}

 

로깅 및 모니터링

// @/apis/utils/logger.js
export const apiLogger = {
  logRequest: (config) => {
    if (process.env.NODE_ENV === 'development') {
      console.log(`API Request: ${config.method.toUpperCase()} ${config.url}`, {
        headers: config.headers,
        data: config.data
      })
    }
  },
  
  logError: (error) => {
    // 에러 로깅 서비스로 전송
    const errorData = {
      url: error.config.url,
      method: error.config.method,
      status: error.response?.status,
      message: error.message,
      timestamp: new Date().toISOString()
    }
    
    // 에러 추적 서비스로 전송
    // errorTrackingService.log(errorData)
  }
}

 

테스트

// @/apis/config/axios-config.test.js
import { createAxiosInstance } from './axios-config'

describe('Axios Instance', () => {
  let instance

  beforeEach(() => {
    instance = createAxiosInstance({
      baseURL: 'http://test-api.com'
    })
  })

  it('should handle 401 errors', async () => {
    // 테스트 구현
  })

  it('should retry failed requests', async () => {
    // 테스트 구현
  })
})

 

반응형
Comments