데이터 패칭 라이브러리 - Axios (5. 요청 가로채기)

eeensu·2024년 7월 26일
post-thumbnail

가로채기 (Interceptor)

Axios의 인터셉터는 요청(request)과 응답(response)을 가로채고, 이를 처리하거나 수정할 수 있는 강력한 기능을 제공한다. 이를 통해 요청 전이나 응답 후에 공통적인 작업을 수행할 수 있으며, 로깅, 인증 토큰 추가, 오류 처리 등을 쉽게 구현할 수 있다. 인터셉터는 Axios 인스턴스에서 사용되며, 다음과 같은 두 가지 유형이 있다.

형태는 axiosInstance.request.use() 의 형태로 쓰이며, response도 동일하다. use에 들어가는 인자는 다음과 같다.

use(onFulfilled, onRejected, options): number
  • onFulfilled
    (config: AxiosRequestConfig) => AxiosRequestConfig | Promise<AxiosRequestConfig> 의 타입을 가지는 콜백함수 이며
    요청이나 응답이 반환되었을 때 실행된다. 이 함수는 같은 타입의 값을 반환하거나, 같은 타입을 resolve하는 프로미스를 반환할 수 있다.
  • onRejected
    (error: AxiosError): Promise<AxiosError> 의 타입을 가지는 콜백함수이며,
    요청이나 응답에서 오류가 발생했을 때 실행된다. 이 함수는 오류 객체를 받아서 처리한 후 다시 오류를 반환하거나 새로운 결과를 반환할 수 있다.
  • options (optional)
    AxiosInterceptorOptions 의 타입을 가지며 인터셉터에 대한 추가 옵션을 설정할 수 있는 객체이다.
    • synchronous (boolean) : 이 옵션은 인터셉터가 동기적으로 실행되어야 하는지 여부를 결정한다. 일반적으로 인터셉터는 비동기적으로 실행되지만, 특정 상황에서 인터셉터의 로직이 동기적으로 처리되어야 할 필요가 있을 때 synchronous 옵션을 true로 설정할 수 있다. 기본값은 false 이며 비동기적으로 실행된다.
    • runWhen ((config: InternalAxiosRequestConfig) => boolean)
      이 함수는 인터셉터가 실행될 조건을 정의한다. 함수는 InternalAxiosRequestConfig 타입의 config 객체를 인자로 받아서, 특정 조건에 따라 true 또는 false를 반환한다. 이 반환값에 따라 인터셉터가 실행 여부를 결정한다.
  • 반환 값
    인터셉터의 고유 식별자인 숫자를 반환한다. 이 식별자는 인터셉터를 나중에 제거할 때 사용된다.


요청 인터셉터 (Request Interceptors)

요청 인터셉터는 HTTP 요청이 서버로 전송되기 전에 호출된다. 이 인터셉터를 사용하면, 요청을 수정하거나 특정 작업을 수행할 수 있다. 예를 들어, 요청 헤더에 인증 토큰을 추가하거나, 요청을 로깅할 수 있다.

// 요청 인터셉터 설정
axiosInstance.interceptors.request.use(
  (config) => {
    // 요청을 보내기 전에 공통적으로 필요한 작업을 이곳에서 수행
    
    // ex) 프론트에서 가지고있는 인증 토큰(쿠키, 세션 등)을 서버에 전송할 때 포함시켜 전송하는 로직 
    const token = getAuthToken();
    if (!!token) {
      config.headers['Authorization'] = `Bearer ${token}`;
    }
    
 // ex)api를 전송하기 전에 전역 로딩 상태를 세팅하는 로직
    setIsLoading(true)
    
    return config;
  },
  (error) => {
    // 요청 오류가 발생한 경우 작업 수행
    console.error('Request error:', error);
    return Promise.reject(error); // 필요에 따라 다른 오류처리 가능
  }
);

응답 인터셉터 (Response Interceptors)

응답 인터셉터는 서버에서 응답을 받은 후, 응답이 애플리케이션에 전달되기 전에 호출된다. 이를 통해 응답 데이터를 수정하거나, 오류 처리를 일관되게 수행할 수 있다.

axiosInstance.interceptors.response.use(
  (response) => {
    // 서버로부터 전달받은 응답을 처리하기 전에 이곳에서 한번 가공할 수 있음
    console.log('Response:', response);
    
    // ex)request interceptor 때 세팅해놓은 전역 로딩 상태를 해제하는 로직
    setIsLoading(false)
    
    return response;
  },
  (error) => {
    // 응답 오류가 발생한 경우 작업 수행
    // 서버에서 제공하는 오류의 상태에 따라서, 
    // 프론트에서 기존 인증과 관련된 세팅을 리셋하거나 재요청을 하는 등의 작업을 수행할 수 있다.
    
    // ex) 서버로부터 받은 상태 코드값을 통해 화면에 보여줄 에러 표시
    if (error.response.status === 401) {
     	console.log('Unauthorized, logging out...'); 
    }
    
    // 에러가 발생하면, 첫번째 인자의 콜백함수를 타지 않으므로, 로딩상태에 대한 해제도 따로 필요
      setIsLoading(false)
    
    return Promise.reject(error);
  }
);



인터셉터의 동작 흐름

  1. 요청 인터셉터 : 클라이언트에서 서버로 요청을 보내기 전에 호출된다.
  2. 요청 전송 : 수정된 요청이 서버로 전송된다.
  3. 응답 수신 : 서버로부터 응답을 받는다.
  4. 응답 인터셉터 : 서버로부터 받은 응답을 클라이언트에 전달하기 전에 호출된다.



인터셉터 체인

Axios의 인터셉터는 체인 형태로 작동한다. 여러 개의 요청 및 응답 인터셉터를 등록할 수 있으며, 각각의 인터셉터는 체인의 다음 인터셉터로 요청/응답을 전달한다.

axiosInstance.interceptors.request.use(firstRequestInterceptor);
axiosInstance.interceptors.request.use(secondRequestInterceptor);
axiosInstance.interceptors.response.use(firstResponseInterceptor);
axiosInstance.interceptors.response.use(secondResponseInterceptor);
// 이 경우, request의 firstRequestInterceptor 가 먼저 호출되고, 그 다음 second... 가 호출된다. response도 마찬가지로 순차적으로 호출된다.

인터셉터 제거

  • eject
    특정 인터셉터를 제거하는 함수이다. request.use()resposne.use() 는 각각 number 형태의 아이디값을 리턴하는데, 그 아이디값을 eject() 함수의 매개변수로 대입하면 제거가 가능하다.
const resInterceptorID = axiosInstance.interceptors.response.use(
  (response: AxiosResponse) => {
    // 응답 데이터 로그
    console.log(response.data);
    return response;
  },
  error => {
    return Promise.reject(error);
  }
);

// 인터셉터 제거
axiosInstance.interceptors.request.eject(reqInterceptorID);
// response 도 동일
  • clear
    특정 인터셉터가 아닌 모든 인터셉터를 제거한다
axiosInstance.interceptors.request.clear();
axiosInstance.interceptors.response.clear();
profile
안녕하세요! 프론트엔드 개발자입니다! (2024/03 ~)

0개의 댓글