Vue.js 환경에서 Axios를 활용한 비동기 HTTP 요청 처리

Axios 개요 및 설치

Vue.js 애플리케이션에서 비동기 HTTP 통신을 구현할 때 Axios는 가장 널리 사용되는 Promise 기반의 클라이언트 라이브러리입니다. 브라우저와 Node.js 환경 모두에서 원활하게 작동하며, 직관적인 API를 제공합니다.

패키지 설치

프로젝트 환경에 맞는 패키지 매니저를 사용하여 Axios를 설치할 수 있습니다.

# npm 사용
npm install axios

# yarn 사용
yarn add axios

# pnpm 사용
pnpm add axios

또는 빌드 도구를 사용하지 않는 환경에서는 CDN을 통해 스크립트를 직접 로드할 수 있습니다.

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

기본 HTTP 메서드 활용

GET 요청 및 데이터 바인딩

서버로부터 데이터를 가져와 Vue 컴포넌트의 상태에 바인딩하는 기본적인 GET 요청 예시입니다. 라이프사이클 훅인 mounted 내에서 호출합니다.

new Vue({
  el: '#dashboard',
  data() {
    return {
      platformList: [],
      isLoading: false
    };
  },
  async mounted() {
    this.isLoading = true;
    try {
      const { data } = await axios.get('https://api.example.com/v1/platforms');
      this.platformList = data.items;
    } catch (err) {
      console.error('데이터 조회 중 오류 발생:', err.message);
    } finally {
      this.isLoading = false;
    }
  }
});

URL에 쿼리 파라미터를 전달할 때는 params 객체를 활용하는 것이 가독성과 유지보수 측면에서 유리합니다.

axios.get('https://api.example.com/v1/users', {
  params: {
    userId: 98765,
    role: 'admin'
  }
})
.then(res => console.log(res.data))
.catch(err => console.error(err));

POST 요청 및 데이터 전송

서버로 새로운 리소스를 생성하거나 데이터를 전송할 때는 POST 메서드를 사용합니다. 두 번째 인자로 전송할 페이로드(payload)를 전달합니다.

const payload = {
  username: 'dev_user',
  email: 'dev@example.com',
  preferences: { theme: 'dark' }
};

axios.post('https://api.example.com/v1/users/register', payload)
  .then(res => {
    console.log('등록 성공:', res.data.userId);
  })
  .catch(err => {
    console.error('등록 실패:', err.response?.data?.message);
  });

다중 요청 병렬 처리

여러 개의 독립적인 API를 동시에 호출해야 할 경우, Promise.all을 사용하여 네트워크 대기 시간을 단축할 수 있습니다. (참고: 기존 axios.all는 공식적으로 지원이 중단되었으므로 표준 Promise.all 사용을 권장합니다.)

const fetchUserProfile = () => axios.get('https://api.example.com/v1/users/1001');
const fetchUserActivity = () => axios.get('https://api.example.com/v1/users/1001/activity');

Promise.all([fetchUserProfile(), fetchUserActivity()])
  .then(([profileRes, activityRes]) => {
    console.log('프로필:', profileRes.data);
    console.log('활동 내역:', activityRes.data);
  })
  .catch(err => console.error('병렬 요청 실패:', err));

Axios 인스턴스 및 커스텀 설정

매 요청마다 동일한 설정을 반복하는 것을 피하기 위해, 커스텀 설정이 적용된 Axios 인스턴스를 생성하여 재사용할 수 있습니다.

const apiClient = axios.create({
  baseURL: 'https://api.example.com/v2/',
  timeout: 5000,
  headers: {
    'X-Custom-Header': 'VueApp',
    'Accept': 'application/json'
  }
});

// 인스턴스를 통한 요청
apiClient.get('/metrics')
  .then(res => console.log(res.data));

주요 요청 설정 옵션 (Request Config)

요청을 생성할 때 전달할 수 있는 주요 설정 객체의 구조입니다.

{
  url: '/endpoint', // 필수: 요청할 서버의 엔드포인트
  method: 'get',    // HTTP 메서드 (기본값: get)
  baseURL: 'https://api.example.com', // 상대 경로 URL 사용 시 자동 결합
  headers: { 'Authorization': 'Bearer token_value' }, // 커스텀 헤더
  params: { search: 'keyword' }, // URL 쿼리 파라미터
  data: { key: 'value' }, // 요청 본문 (POST, PUT, PATCH 전용)
  timeout: 3000, // 요청 타임아웃 (밀리초)
  withCredentials: true, // CORS 요청 시 쿠키 및 인증 정보 포함 여부
  responseType: 'json', // 응답 데이터 타입 (arraybuffer, blob, text 등)
  validateStatus: function (status) {
    return status >= 200 && status < 300; // Promise를 resolve할 HTTP 상태 코드 범위
  }
}

응답 객체 구조 (Response Schema)

요청이 성공적으로 완료되면 Axios는 다음과 같은 구조의 응답 객체를 반환합니다.

{
  data: {},          // 서버에서 반환된 실제 페이로드
  status: 200,       // HTTP 상태 코드
  statusText: 'OK',  // HTTP 상태 메시지
  headers: {},       // 서버 응답 헤더
  config: {}         // 해당 요청에 사용된 Axios 설정 객체
}

인터셉터(Interceptors)를 활용한 전역 처리

인터셉터를 사용하면 요청이 전송되기 전이나 응답을 받은 직후에 특정 로직(예: 토큰 주입, 전역 에러 로깅)을 가로채어 실행할 수 있습니다.

// 요청 인터셉터: 인증 토큰 자동 주입
const reqInterceptor = apiClient.interceptors.request.use(
  config => {
    const token = localStorage.getItem('auth_token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  error => Promise.reject(error)
);

// 응답 인터셉터: 전역 에러 핸들링
apiClient.interceptors.response.use(
  response => response,
  error => {
    if (error.response && error.response.status === 401) {
      console.warn('인증이 만료되었습니다. 로그인 페이지로 이동합니다.');
      // 리디렉션 로직 수행
    }
    return Promise.reject(error);
  }
);

// 인터셉터 해제
apiClient.interceptors.request.eject(reqInterceptor);

요청 취소 (Cancellation)

사용자가 페이지를 이탈하거나 특정 조건에 의해 진행 중인 네트워크 요청을 중단해야 할 때, 최신 웹 표준인 AbortController를 사용하는 것이 권장됩니다.

const controller = new AbortController();

axios.get('https://api.example.com/v1/large-dataset', {
  signal: controller.signal
})
.then(res => console.log('데이터 로드 완료'))
.catch(err => {
  if (axios.isCancel(err)) {
    console.log('사용자에 의해 요청이 취소됨:', err.message);
  } else {
    console.error('기타 네트워크 오류:', err);
  }
});

// 특정 시점에 요청 중단
setTimeout(() => {
  controller.abort('더 이상 데이터가 필요하지 않음');
}, 1000);

Form URL Encoded 형식 전송

Axios는 기본적으로 JavaScript 객체를 JSON으로 직렬화하여 전송합니다. 만약 application/x-www-form-urlencoded 형식으로 데이터를 보내야 한다면, 환경에 맞는 직렬화 도구를 사용해야 합니다.

브라우저 환경 (URLSearchParams)

const formData = new URLSearchParams();
formData.append('clientId', 'web_app');
formData.append('grantType', 'authorization_code');

axios.post('https://api.example.com/oauth/token', formData, {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
});

Node.js 환경 (qs 라이브러리)

const qs = require('qs');
const payload = { filter: { status: 'active' }, sort: 'created_at' };

axios.post('https://api.example.com/v1/search', qs.stringify(payload), {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
});

TypeScript 지원

Axios는 내장된 TypeScript 타입 정의를 제공하여, 개발 시 안정적인 타입 추론과 자동 완성을 지원합니다.

import axios, { AxiosResponse } from 'axios';

interface User {
  id: number;
  name: string;
}

axios.get<User>('https://api.example.com/v1/users/1')
  .then((response: AxiosResponse<User>) => {
    console.log(response.data.name); // 타입 안전성 보장
  });

태그: Vue.js axios HTTP JavaScript Promise

5월 30일 12:10에 게시됨