axios 인터셉터로 API 관리하기

skyepodium·2020년 4월 18일
62
post-thumbnail

axios interceptors로 API를 공통 관리해 봅시다.
axios 깃허브 설명
뷰 - 인터셉터 전체 코드

혹시 그런적 있나요?

1. 매번 axios 요청할때마다, 겹치는 부분을 기본 URL로 설정하고 싶어요.

기본 URL
https://api.hnpwa.com/v0

나머지
/news/1.json
/newest/1.json
/ask/1.json
/show/1.json
/jobs/1.json

2. axios 사용할때마다 헤더를 매번 넣고 싶지 않아요.

3. 에러가 발생했을때 공통으로 처리하고 싶어요.

이런경우 1) 요청할때 2) 응답을 받을때 인터셉터를 사용해서 중간에 가로챈 후 공통으로 처리할 수 있습니다.

1. interceptors

1) 정의

인터셉터는 1.요청하기 직전, 2. 응답을 받고 then, catch로 처리 직전에 가로챌 수 있습니다.

2) 구성

크게 3가지 부분으로 구성됩니다.

    1. 인스턴스
    1. request 설정
    1. response 설정

그리고 request, response 설정은 각각 2개의 콜백함수를 받습니다.

import axios from 'axios'

// axios 인스턴스를 생성합니다.
const instance = axios.create({
    baseURL: 'https://api.hnpwa.com',
    timeout: 1000
  });

/*
    1. 요청 인터셉터
    2개의 콜백 함수를 받습니다.
*/
instance.interceptors.request.use(
    function (config) {
        // 요청 성공 직전 호출됩니다.
        // axios 설정값을 넣습니다. (사용자 정의 설정도 추가 가능)
        return config;
    }, 
    function (error) {
        // 요청 에러 직전 호출됩니다.
        return Promise.reject(error);
    }
);

/*
    2. 응답 인터셉터
    2개의 콜백 함수를 받습니다.
*/
instance.interceptors.response.use(
    function (response) {
    /*
        http status가 200인 경우
        응답 성공 직전 호출됩니다. 
        .then() 으로 이어집니다.
    */
        return response;
    },

    function (error) {
    /*
        http status가 200이 아닌 경우
        응답 에러 직전 호출됩니다.
        .catch() 으로 이어집니다.    
    */
        return Promise.reject(error);
    }
);

2. 실습

해커뉴스 오픈 API를 인터셉터를 사용해서 요청해봅시다.

1) 뷰 프로젝트 생성

vue cli 4.x (4버전 이상) 을 사용해서 프로젝트를 생성합니다

// vue create 생성할 프로젝트 이름

vue create axios_interceptors

2) axios 설치 및 실행

패키지 매니저인 npm 또는 yarn을 사용해서 axios를 설치합니다.

그리고, vue 개발 서버를 실행합니다.

# npm 사용
# axios 설치
npm i axios
# 개발 서버 실행
npm run serve

# yarn 사용
# axios 설치
yarn add axios
# 개발 서버 실행
yarn run serve

3) interceptors 작성

axios 인터셉터 파일을 생성해봅시다.

생성위치: /root/src/utils/Send.js
(root는 프로젝트 최상단 package.json 파일이 있는곳 입니다.)

// 파일경로: src/utils/send.js

import axios from 'axios'

/*
    axios 인스턴스를 생성합니다.
    생성할때 사용하는 옵션들 (baseURL, timeout, headers 등)은 다음 URL에서 확인할 수 있습니다.
    https://github.com/axios/axios 의 Request Config 챕터 확인
*/
const instance = axios.create({
    baseURL: 'https://api.hnpwa.com/v0',
    timeout: 1000
    // 해커 뉴스 API는 커스텀 헤더 넣으면 CORS걸려서 주석처리했습니다.
    // headers: {'X-Custom-Header': 'foobar'}
  });

/*
    1. 요청 인터셉터를 작성합니다.
    2개의 콜백 함수를 받습니다.

    1) 요청 바로 직전 - 인자값: axios config
    2) 요청 에러 - 인자값: error
*/
instance.interceptors.request.use(
    function (config) {
        // 요청 바로 직전
        // axios 설정값에 대해 작성합니다.
        return config;
    }, 
    function (error) {
        // 요청 에러 처리를 작성합니다.
        return Promise.reject(error);
    }
);



/*
    2. 응답 인터셉터를 작성합니다.
    2개의 콜백 함수를 받습니다.

    1) 응답 정성 - 인자값: http response
    2) 응답 에러 - 인자값: http error
*/
instance.interceptors.response.use(
    function (response) {
    /*
        http status가 200인 경우
        응답 바로 직전에 대해 작성합니다. 
        .then() 으로 이어집니다.
    */
        return response;
    },

    function (error) {
    /*
        http status가 200이 아닌 경우
        응답 에러 처리를 작성합니다.
        .catch() 으로 이어집니다.    
    */
        return Promise.reject(error);
    }
);

// 생성한 인스턴스를 익스포트 합니다.
export default instance;

4) API 파일 작성하기

왜 API 파일을 작성해야하나요?

각가의 화면 .vue 파일에 작성하고 불러오더라도 크게 문제는 없습니다.

다만, 만약 10명 이상 다수의 개발자, 100개 이상 다수의 API등 프로젝트의 규모가 커졌을 때 각각의 파일에서 요청하는 방식은 공통으로 처리하기도, 관리하기도 쉽지 않습니다.

인터셉터와 API 파일을 사용했을때의 장점

  1. 공통부분을 인터셉터가 처리해주기 때문에 관리하기 쉽습니다.(헤더, baseURL 등)
  2. 실수가 줄어듭니다. (개별의 개발자가 작성해야할 부분이 줄어들기 때문에 실수또한 줄어듭니다.)
// 파일경로: src/api/News.js

// 작성한 axios 인터셉터를 가져옵니다.
import Send from '../utils/Send.js'

export default {
    getNews() {
        // axios 요청을 생성합니다.
        /*
        axios 요청을 생성합니다.
        https://github.com/axios/axios axios API 챕터
        인터셉터를 안썼으면 다음과 같습니다.
        axios({
            baseURL: 'https://api.hnpwa.com',
            url: '/news/1.json',
            method: 'get'  
        })
        */          
        return Send({
                // baseURL설정되어 있기 때문에 그 뒤의 URL만 작성합니다.
                url: '/news/1.json',
                method: 'get'
            })
    },
    getNewest() {
        return Send({
                url: '/newest/1.json',
                method: 'get'
            })
    },
    getAsk() {
        return Send({
                url: '/ask/1.json',
                method: 'get'
            })
    },
    getShow() {
        return Send({
                url: '/show/1.json',
                method: 'get'
            })
    },
    getJobs() {
            Send({
                url: '/jobs/1.json',
                method: 'get'
            })
    }        
}

5) 요청하기

App.vue 파일을 수정합니다.

파일경로: /root/src/App.vue

<template>
  <div id="app">
    main
  </div>
</template>

<script>
import News from '@/api/News'

export default {
  name: 'App',
  created() {
    News.getNews()
      .then((res) => {
        console.log('res', res)
      })
      .catch((error) => {
        console.log('error', error)
      })
  }
}
</script>

6) 응답 결과 확인

인터셉터에서 요청직전 넣어준 baseURL, timeout이 응답 파라미터에 들어있음을 확인할 수 있습니다.

그리고 응답값을 잘 받았습니다.

4. 더 활용하기

그밖에도 인터셉터를 활용는 다양한 방법이 있습니다.

  1. 로그인 전후 분기 처리해서 헤더 넣어주기
  2. 모든 요청에 로딩 인디케이터 삽입하기
  3. 응답 에러 발생시, 알림 팝업 만들기
profile
callmeskye

3개의 댓글

comment-user-thumbnail
2021년 12월 20일

덕분에 정말 잘 알고갑니다 ㅠ ㅠ 좋은 글 감사합니다.

1개의 답글
comment-user-thumbnail
2022년 10월 25일

필요를 잘 못 느끼고 있었는데 다양한 활용 방법이 있네요! 잘 배워갑니다 :))

답글 달기