PromleeBlog
sitemap
aboutMe

posting thumbnail
Axios로 API 연동 및 비동기 처리하기 - Vue 기본기 다지기 7편
API Integration and Async Operations with Axios - Vue Basics Part 7

📅

🚀

들어가기 전에 🔗

'Vue 기본기 다지기 6편'에서는 Pinia를 이용해 여러 컴포넌트가 공유하는 상태를 중앙에서 관리하는 방법을 배웠습니다.
이제 우리 앱은 내부의 데이터 흐름을 깔끔하게 정리할 수 있게 되었습니다.

이번 7편에서는 드디어 Vue 애플리케이션의 외부, 즉 서버와 통신하는 방법을 알아보겠습니다.
현대의 웹 앱은 대부분 자체적으로 모든 데이터를 가지고 있기보다는, 필요할 때마다 서버에 데이터를 요청하여 화면을 동적으로 업데이트하는 방식으로 동작합니다.
이러한 서버와의 통신 과정을
API 연동
이라고 합니다.
이 과정은 '비동기(Asynchronous)'로 처리되는데, 오늘은 이 비동기 통신을 쉽고 편리하게 다룰 수 있도록 도와주는 axios 라이브러리의 사용법을 중점적으로 살펴보겠습니다.

🚀

Axios 설치 및 기본 설정 🔗

먼저 우리 프로젝트에 Axios를 설치해야 합니다.
터미널에서 아래 명령어를 실행해 주세요.
npm install axios
설치가 완료되면, 실무에서처럼 API의 기본 주소(Base URL)와 같이 반복적으로 사용되는 설정을 미리 지정해둔 'Axios 인스턴스'를 만들어 사용하는 것이 효율적입니다.
src 폴더 밑에 api 폴더를 만들고 index.js 파일을 생성해 보겠습니다.
src/api/index.js
import axios from 'axios';
 
// Axios 인스턴스를 생성합니다.
const api = axios.create({
  // API 요청의 기본 주소를 설정합니다.
  // 모든 요청 앞에 이 주소가 붙게 됩니다.
  baseURL: 'https://jsonplaceholder.typicode.com'
});
 
export default api;
이렇게 인스턴스를 만들어두면, 앞으로 우리는 axios.get('https://jsonplaceholder.typicode.com/posts') 대신 api.get('/posts') 와 같이 짧고 간결하게 코드를 작성할 수 있습니다.

🚀

컴포넌트 생명주기와 API 호출 🔗

그렇다면 API 호출은 컴포넌트의 어느 시점에서 하는 것이 가장 좋을까요.
이때 필요한 개념이 바로
생명주기 훅(Lifecycle Hooks)
입니다.
생명주기 훅은 컴포넌트가 생성되고, 화면에 부착되고, 업데이트되고, 사라지는 각 단계에서 Vue가 자동으로 실행해 주는 함수들입니다.

API를 통해 화면에 보여줄 초기 데이터를 가져오는 작업은, 컴포넌트가 화면에 마운트된(부착된) 직후에 실행하는 것이 가장 일반적입니다.
이때 사용하는 훅이 바로 onMounted 입니다.
PostList.vue
<script setup>
import { ref, onMounted } from 'vue';
import api from '@/api'; // 우리가 만든 Axios 인스턴스를 가져옵니다.
 
const posts = ref([]);
 
// onMounted 훅에 비동기 함수를 전달합니다.
onMounted(async () => {
  try {
    // 컴포넌트가 마운트되면 API를 호출하여 게시물 목록을 가져옵니다.
    const response = await api.get('/posts?_limit=10'); // 10개만 가져오기
    posts.value = response.data; // 응답 데이터를 posts 상태에 저장합니다.
  } catch (error) {
    console.error('데이터를 가져오는 중 에러 발생:', error);
  }
});
</script>
 
<template>
  <div>
    <h1>게시물 목록</h1>
    <ul>
      <li v-for="post in posts" :key="post.id">
        {{ post.title }}
      </li>
    </ul>
  </div>
</template>
위 코드는 PostList 컴포넌트가 화면에 준비되자마자 /posts API를 호출하고, 응답으로 받은 게시물 목록을 화면에 그려줍니다.

🚀

로딩 및 에러 상태 관리하기 🔗

실제 서비스에서는 네트워크가 느리거나 서버에 문제가 생길 수 있습니다.
이런 상황을 대비하지 않으면 사용자는 빈 화면만 보거나, 왜 앱이 동작하지 않는지 알 수 없어 답답함을 느끼게 됩니다.
따라서 API를 호출할 때는
로딩(loading)
상태와
에러(error)
상태를 관리하는 것이 매우 중요합니다.
try...catch...finally 구문을 사용하면 이 로직을 깔끔하게 구현할 수 있습니다.
PostList.vue
<script setup>
import { ref, onMounted } from 'vue';
import api from '@/api';
 
const posts = ref([]);
const isLoading = ref(false); // 로딩 상태를 관리할 ref
const error = ref(null);      // 에러 상태를 관리할 ref
 
onMounted(async () => {
  isLoading.value = true; // API 호출 시작 전에 로딩 상태를 true로 설정
  error.value = null;
 
  try {
    // try 블록 안에서 API를 호출합니다.
    const response = await api.get('/posts?_limit=10');
    posts.value = response.data;
  } catch (err) {
    // catch 블록에서 에러를 처리합니다.
    console.error('데이터를 가져오는 중 에러 발생:', err);
    error.value = '데이터를 불러올 수 없습니다. 잠시 후 다시 시도해주세요.';
  } finally {
    // finally 블록은 성공/실패 여부와 관계없이 항상 실행됩니다.
    isLoading.value = false; // API 호출이 끝나면 로딩 상태를 false로 설정
  }
});
</script>
 
<template>
  <div>
    <h1>게시물 목록</h1>
    <div v-if="isLoading">
      로딩 중입니다...
    </div>
    <div v-else-if="error">
      <p style="color: red;">{{ error }}</p>
    </div>
    <ul v-else>
      <li v-for="post in posts" :key="post.id">
        {{ post.title }}
      </li>
    </ul>
  </div>
</template>
이제 사용자는 데이터를 불러오는 중인지, 혹은 문제가 발생했는지 명확하게 알 수 있어 훨씬 더 나은 사용자 경험을 제공하게 됩니다.

🚀

결론 🔗

이번 시간에는 Vue 애플리케이션이 외부 서버와 통신하는 데 필수적인 API 연동 방법을 배웠습니다.
비동기 데이터 처리를 능숙하게 다루는 것은 동적인 최신 웹 애플리케이션을 만드는 데 가장 핵심적인 기술 중 하나입니다.
다음 'Vue 기본기 다지기 8편'에서는 컴포넌트의 스타일을 관리하는 방법과, 특정 조건에 따라 화면의 일부를 보여주거나 숨기는 조건부 렌더링에 대해 알아보겠습니다.

참고 🔗