본문 바로가기
javascript/Vue

vue 통신 가로채기 axios interceptor의 개념과 활용!

by 산코디 2024. 5. 22.

SPA 개발을 하다 보면 axios로 통신하는 경우가 많이 있는데 서버와 분리된 환경이다 보니 로그인 정보는 token을 이용해서 처리하는 경우가 많다. 이러한 경우 axios의 interceptor를 활용한다면 손쉽게 처리할 수 있다. 이를 보통 요청 가로채기라고 하는데, 통신 요청 직전을 가로채서 원하는 작업을 먼저 처리하고자 하는 것을 의미하기 때문이다.

그럼 axios의 interceptor는 어떤 방식으로 처리가 되는지 하나씩 자세히 살펴보자.


예제 코드는 모두 vue에서 작업을 진행하였다.
vue3, axios


interceptor란?

인터셉터(interceptor)는 소프트웨어에서 통신 중에 어떤 작업을 수행하기 전이나 후에 먼저 다른 작업을 처리할 수 있도록 처리해 주는 역할이다. 보통 HTTP 요청을 보내기 전에 특정한 로직을 수행하거나, 응답을 받은 후에 추가적인 처리를 할 때 주로 사용된다.

중재 기능
인터셉터는 주로 중재 기능을 수행하며, 요청이나 응답이 처리되기 전에 중간에서 삽입되어 추가 작업을 수행할 수 있도록 도와준다.

코드 재사용성
인터셉터를 사용하면 코드의 재사용성을 높일 수 있다. 특정한 작업을 인터셉터로 구현하면 이를 여러 곳에서 호출하여 사용할 수 있다.

유연성
인터셉터는 코드의 유연성을 높여주는데, 새로운 요구사항이나 변경 사항이 있을 때, 기존의 인터셉터를 수정하거나 새로운 인터셉터를 추가하여 기능을 확장할 수 있다.

로직 분리
인터셉터를 사용하면 코드의 로직을 분리할 수 있다. 예를 들어, 네트워크 요청에 관련된 로직을 인터셉터에 구현하면 이를 컨트롤러나 서비스와 분리하여 코드의 가독성을 높일 수 있다.


인터셉터는 http 통신에서 알아두면 활용성이 높은 기능 중 하나이기 때문에 위의 정리한 특징들과 같이 활용해보면 좋을 것 같다.




interceptor request

먼저 interceptor request는 http 요청할 때 인터셉터를 실행하는 작업이다. 가로채기를 시도한 후 콜백 함수를 통하여 원하는 작업을 실행하고 다시 http 요청을 시도하게 된다.


성 예시

import axios from 'axios'

// Request 인터셉터 생성
axios.interceptors.request.use(
  function(config) {
    // 요청을 보내기 전에 수행할 작업 추가
    return config
  },
  function(error) {
    // 요청 오류 시 수행할 작업 추가
    return Promise.reject(error)
  }
)

먼저 axios의 interceptor를 사용하려면 위의 코드와 같이
axios.interceptors.request.use
함수를 호출하여 코드를 작성하면 된다.

첫 번째 콜백 함수에서는 원하는 작업을 처리한다. 이 함수가 바로 http 요청 직전에 처리되는 함수라고 할 수 있다. 매개 변수로 config(요청 객체)를 받아 요청하는 객체의 값을 변경하고 추가하는 등의 작업을 할 수 있다.

여기서 중요한 부분은 config 값을 다루거나 특정 작업을 처리한 후에는 config를 다시 반환시켜주는게 중요하다. config를 반환하지 않으면 http 요청이 진행되지 않아 문제가 될 수 있으므로 이 부분을 유의해서 처리하는 것이 중요하다.

그리고 두 번째 콜백 함수는 에러 처리에 대한 함수다. 요청 중 에러가 발생한 경우 인터셉터에서 먼저 에러 처리를 하는 단계라고 볼 수 있다.


토큰 처리 코드

axios.interceptors.request.use(
  function(config) {
    // 헤더에 인증 토큰 추가
    config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`
    return config
  },
  function(error) {
    return Promise.reject(error)
  }
)

보통 요청할 때의 인터셉터 단계에서 보안과 관련된 작업을 처리하는데, axios를 요청할 때마다 보안관련 코드를 삽입하는 것보다 위와 같이 인터셉터 코드를 공통화하여 처리하면 코드의 재사용성이 좋아질 수 있다.

위의 코드에서 첫 번째 콜백 함수를 보면 config.headers에 권한 정보를 추가하고 있다. 이를 통해 요청 직전에 권한 정보를 추가하여 간단하게 보안 처리를 할 수 있다.


위의 정리한 바와 같이 axios.interceptor.request를 사용하여 http 요청시의 인터셉터 처리가 가능하다는 것을 알 수 있었다. 두 종류의 콜백 함수 처리만 잘해준다면 큰 문제없이 인터셉터 처리를 할 수 있다.




interceptor response

response를 처리할 때에도 같은 맥락으로 인터셉터 처리가 가능하다. 조금 다른 부분은 request는 요청 직전을 가로채어 처리를 하는 반면, response는 응답 후의 작업을 가로채어 처리를 하게 된다. 시점이 조금 다르다는 것을 제외하면 흐름은 같다고 볼 수 있다.


작성 예시

import axios from 'axios'

// Response 인터셉터 생성
axios.interceptors.response.use(
  function(response) {
    // 응답을 받은 후에 수행할 작업 추가
    return response
  },
  function(error) {
    // 응답 오류 시 수행할 작업 추가
    return Promise.reject(error)
  }
)

request와 유사하지만 호출하는 함수가 조금 다르다.
axios.interceptors.response.use와 같이 request 부분만 response로 변경하면 응답에 대한 인터셉터 가로채기가 가능하다.

나머지 두 콜백 함수에 대해서는 흐름이 동일하다. 첫 번째 콜백 함수는 응답 결과에 대해 가로채기를 하여 해당 결과에 대한 처리를 먼저 한 후 최종 결과를 반환한다. 여기서도 request와 동일하게 결과를 반드시 반환해야 한다.

그리고 두 번째 콜백 함수는 에러 처리에 대한 내용이다. 여기서도 request와 동일하다고 볼 수 있다.




interceptor 해제

인터셉터를 사용하여 요청과 응답의 가로채기 후 작업을 처리했다면 처리한 후의 인터셉터 객체를 해제시켜줘야 한다.
axios를 통해 생성하고 사용한 인터셉터는 내부적으로 남아있게 된다. 사용 후 처리를 하지 않으면 매번 호출한 인터셉터의 처리 내용이 누적되어 불필요한 메모리가 쌓이게 된다. 그렇기 때문에 인터셉터를 사용한다면 반드시 해제 처리를 해줘야 한다.


interceptor 누적 확인

console.log(axios.interceptors.request)
console.log(axios.interceptors.response)

위와 같이 request와 response를 콘솔에 출력하면 그동안 생성된 인터셉터 객체가 배열로 쌓여있게 된다. vue와 같은 프레임워크는 SPA이기 때문에 사용자가 별도의 새로고침을 하지 않으면 인터셉터는 계속 누적되게 된다.
그래서 반드시 인터셉터를 생성하고 사용한 후에는 eject 시켜줘야 한다.


interceptor eject

import axios from 'axios'

// Request 인터셉터 생성
const reqInterceptor = axios.interceptors.request.use(
  function(config) {
    // 요청을 보내기 전에 수행할 작업 추가
    return config
  },
  function(error) {
    // 요청 오류 시 수행할 작업 추가
    return Promise.reject(error)
  }
)

// 사용한 요청 인터셉터 eject
axios.interceptors.request.eject(reqInterceptor)

위의 코드는 요청 인터셉터에 대한 eject 처리 코드다. 위와 같이 생성하는 인터셉터를 변수로 할당하고, 처리가 끝난 후 마지막에 eject 처리를 해주면 끝이다. 이렇게 처리를 하면 axios.interceptors.request에는 생성했던 인터셉터 객체는 null로 초기화가 되는 구조다. 혹시나 배열 건수가 줄어들지 않아서 헷갈릴 수 있는데, null로 처리되는 것까지 확인된다면 정상적으로 처리된 것이다.

response도 동일하게 처리하면 된다.

eject
eject는 어떤 시스템이나 프로세스에서 특정한 구성 요소를 제거하거나 해제하는 동작을 의미한다. axios에서의 eject는 설정한 인터셉터를 해제하는 기능을 수행한다.

 


공통 함수 예제

axios의 interceptor에 대해서 개념과 사용 방법을 이해했다면 함수로 응용해서 사용한다면 훨씬 더 효율적이게 활용할 수 있다.

import axios from 'axios'

function commonAxios(url, method, data) {

  // 요청 인터셉터 생성
  const reqInter = axios.interceptors.request.use(
    config => {
      // 작업 처리 코드 추가
      
      return config
    },
    error => {
      // 에러 처리 코드 추가
      
      return Promise.reject(error)
    }
  )
  
  // 응답 인터셉터 생성
  const resInter = axios.interceptors.response.use(
    response => {
      // 작업 처리 코드 추가
      
      return response
    },
    error => {
      // 에러 처리 코드 추가
      
      return Promise.reject(error)
    }
  )
  
  // axios 요청
  const request = axios({
    url    : url,
    method : method,
    data   : data,
  })
  
  // interceptor 해제
  axios.interceptors.request(reqInter)
  axios.interceptors.response(resInter)
  
  return request
}

위의 코드는 commonAxios라는 함수를 만들어 공통으로 인터셉터 처리한 후 axios 요청 결과를 반환하는 예제다.

위의 코드에서 순서대로 보면,
1. request에 대한 인터셉터 처리
2. response에 대한 인터셉터 처리
3. axios 요청
4. 인터셉터 해제

이렇게 작성되어 있다. 그러나 실제 함수를 실행하게 되면 3번 axios 요청이 실행되어야지만 1번, 2번, 4번이 순서대로 실행된다. 즉, 인터셉터의 선언만 되어 있고, 실제 요청이 실행된 후 인터셉터가 작동한다고 볼 수 있다.

위와 같이 공통 함수로 사용한다면 프로젝트 내에서 전체적으로 손쉽게 인터셉터의 처리를 할 수 있다.



axios interceptor 사용 시 주의사항

인터셉터와 같이 http 통신을 가로채거나 제어하는 기능을 사용할 때에는 주의해서 사용해야 한다. 앞서 정리한 바와 같이 공통화 처리를 하거나, 보안처리, 인터셉터 누적으로 인한 메모리 누수 등 신경써야 할 부분이 많으므로 반드시 주의해야 할 사항들을 고려해야 한다.


순서
인터셉터는 등록된 순서대로 실행되기 때문에 중요한 작업을 수행하는 인터셉터는 다른 인터셉터보다 먼저 등록해야 한다.

에러 처리
인터셉터에서 발생하는 모든 에러는 Promise.reject()를 통해 전파되어야 한다. 그렇지 않으면 발생한 오류가 숨겨질 수 있으며, 이로 인해 예기치 않은 동작이 발생할 수 있다.

메모리 누수
앞서 언급한 바와 같이 인터셉터를 등록한 후 사용이 끝나면 eject 함수를 사용하여 반드시 해당 인터셉터를 해제해야 한다. 그렇지 않으면 메모리 누수가 발생하여 서비스에 영향을 줄 수 있다.

네트워크 요청 헤더
네트워크 요청 헤더를 수정하는 경우에는 사용자가 요청한 정보가 잘못된 방식으로 처리되지 않도록 주의해야 한다.

인터셉터 오버헤드
인터셉터는 모든 요청과 응답에 대해 실행되므로 네트워크 요청의 성능에 영향을 줄 수 있다. 그렇기 때문에 인터셉터을 사용할 때에는 성능에 주의하는 것이 좋다.




마무리

소프트웨어에서 인터셉터는 정말 활용도가 높은 기능이라고 생각한다. 내부적으로 보안 처리를 해야하는데, 요청 코드를 작성할 때마다 헤더에 추가하는 작업을 넣는 것 또한 비효율적이며, 반복되는 코드가 많아져서 재사용성 또한 떨어진다.
그래서 이와 같이 axios에서 제공되는 인터셉터를 활용하여 서비스의 품질을 올려보는 것도 좋을 것 같다.

반응형