[Vue3,ts,vit] axios 통신할때 스피너 로딩바 구현 후 통신끝나면 로딩바 감추기
Vue 3 + Vite 프로젝트에서 Axios를 사용할 때 전역 로딩바(Global Loading Bar)를 구현하는 일반적인 방식은 다음과 같다
Axios 통신 중에 화면 중앙에 회전 로딩 스피너를 보여주는 방식으로 구현한 예시이다.
구현 전략
- Axios Interceptor를 활용해 요청 시작 시 로딩 시작, 응답 완료 시 로딩 종료.
- Pinia 또는 Reactive State로 로딩 상태 관리.
- 컴포넌트에서 로딩 UI 표시.
- Axios 요청 중일 때 전체 화면을 덮는 회전 스피너 표시
- 요청이 끝나면 자동으로 사라짐
1. 로딩 상태 전역 관리 (Pinia 사용)
먼저 Pinia를 설치하지 않았다면 설치:
npm install pinia
stores/loading.ts
또는 stores/loading.ts
생성:
import { defineStore } from 'pinia'
export const useLoadingStore = defineStore('loading', {
state: () => ({
loading: false
}),
actions: {
start() {
this.loading = true
},
stop() {
this.loading = false
}
}
})
2. Axios Interceptor 설정
plugins/axios.js
또는 utils/axios.js
파일 생성:
import axios from 'axios'
import { useLoadingStore } from '@/stores/loading'
const api = axios.create({
baseURL: '/api'
})
api.interceptors.request.use(
(config) => {
const loading = useLoadingStore()
loading.start()
return config
},
(error) => {
const loading = useLoadingStore()
loading.stop()
return Promise.reject(error)
}
)
api.interceptors.response.use(
(response) => {
const loading = useLoadingStore()
loading.stop()
return response
},
(error) => {
const loading = useLoadingStore()
loading.stop()
return Promise.reject(error)
}
)
export default api
3. 메인 설정에 Pinia 추가
main.js
또는 main.ts
:
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
4. 로딩 바 컴포넌트 만들기 (src/components/LoadingBar.vue)
<template>
<div v-if="loading" class="overlay">
<div class="spinner"></div>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { useLoadingStore } from '@/stores/loading'
const loadingStore = useLoadingStore()
const loading = computed(() => loadingStore.loading)
</script>
<style scoped>
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.6);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000;
}
.spinner {
width: 60px;
height: 60px;
border: 8px solid #ccc;
border-top: 8px solid #42b983;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
</style>
5. App.vue
에서 로딩바 표시
src/App.vue
<template>
<LoadingBar />
<router-view />
</template>
<script setup>
import LoadingBar from '@/components/LoadingBar.vue'
</script>
6. 사용 예시 (컴포넌트에서 API 호출)
<template>
<button @click="fetchData">데이터 가져오기</button>
</template>
<script setup>
import api from '@/utils/axios'
const fetchData = async () => {
try {
const res = await api.get('/test') // 백엔드 테스트용 엔드포인트
console.log(res.data)
} catch (err) {
console.error('에러 발생:', err)
}
}
</script>
테스트 팁
- 네트워크 응답이 너무 빠르면 로딩바가 안 보일 수 있어요.
→ 테스트용으로setTimeout
을response interceptor
에 넣으면 좋아요:
await new Promise(resolve => setTimeout(resolve, 1000)) // 응답 지연
요약
- Pinia로 로딩 상태를 전역 관리.
- Axios Interceptor로 자동으로 로딩 제어.
- 컴포넌트로 로딩바 표시.
구성 요소 | 설명 |
---|---|
Pinia | 전역 로딩 상태 관리 |
Axios | 요청 전/후 로딩 상태 토글 |
LoadingSpinner.vue | 중앙 회전 스피너 컴포넌트 |
App.vue | 전역으로 로딩 UI 삽입 |