axios 인터셉터를 사용해서 API호출을 polling 하는방법

박은정·2023년 1월 6일
0

TIL

목록 보기
58/70
post-thumbnail

해당 블로그 내용을 번역하면서 정리한 내용입니다.

이 게시물은 장기간 실행되는 비동기 API 호출을 위해 UI 애플리케이션에서 axios 인터셉트를 사용해서 폴링 로직을 중앙 집중화하는 방법을 살펴봅니다.
endjin의 Marain의 프레임워크와 Azure Durable Functions를 포함한, 많은 프레임워크는 비동기 HTTP API 패턴 을 구현해서 외부 클라이언트와 장기 실행 작업상태를 조정하는 문제를 해결합니다.

일반적으로 HTTP 엔드포인트 는 장기간 실행 작업을 트리거하는 데 사용되며, 클라이언트 애플리케이션이 작업이 완료될 때 확인하기 위해 폴링할 수 있는 상태 엔드포인트를 반환합니다.

호출 클라이언트가 웹UI와 같은 사용자 대면 애플리케이션인 경우, 일반적으로 클라이언트는 장기 실행 작업에서 어떤 일이 일어나는지 보기 위해 대기해서 사용자에게 문제가 발생하면 이를 알릴 수 있습니다.

비동기 RESTful API가 지원하는 모던 싱글페이지 웹 애플리케이션에서 이 요구사항은 상당히 일반적이며, 이 게시물의 나머지 부분은 이 API 패턴으로 작업하는 데 필요한 UI 로직을 단순화하고 중앙 집중화하는 방법을 살펴봅니다.

배경

이 예시는 @nust/axios 모듈을 자바스크립트 HTTP 클라이언트로 사용하는 Nuxt.js 애플리케이션에 기반한 접근 방식을 구체적으로 설명합니다.
하지만 원칙과 접근 방법은 npm Axios 모듈을 사용할 수 있는 모든 자바스크립트 클라언트에 적용됩니다.

이는, 요청/응답/오류 시 실행되는 중앙 집중식 hooks인 axios 인터넵터에서 자체적으로 지원하는 것을 기반으로 하기 때문에, axios 모듈을 구성할 때 쉽게 구성할 수 있습니다.

// axios 모듈
axios.interceptors.request.use(config => {
  // axios request 보내기 전에 할 일
  return config;
}, error => {
  // axios 에러request 보내기 전에 할 일
  return Promise.reject(error);
});

axios.interceptors.response.use(response => {
  // 2XX 범위 안에 있는 모든 상태 코드는 이 함수를 트리거합니다.
  // 데이터를 response받으면서 할 일
  return response;
}, error => {
  // 2XX 범위를 벗어나는 상태 코드는 이 함수를 트리거합니다.
  // 에러를 response받으면서 할 일
  return Promise.reject(error);
});

모듈의 Nuxt 특정 버전은 이를 한 단계 더 발전시켜 axios 모듈의 동작을 확장하기 위해 플러그인 내부에서 사용할 수 있는 helpers를 export합니다.

export default function ({$axios, redirect}) {
  $axios.onError(error => {
    if(error.response.status === 500) {
      redirect('엔드포인트')'
    }
  })
}

이러한 인터셉터는 폴링 로직을 정의하는 데 사용될 수 있으며, 이는 API 호출이 자동으로 동일한 패턴으로 따르도록 중앙 집중화될 수 있음을 의미합니다.

접근방법

장기간 실행되는 비동기 API 패턴은 다음과 같이 작동합니다.

  1. 클라이언트 애플리케이션이 HTTP 요청을 전송하여 장시간 실행 작업을 트리거합니다. 이 작업은 일반적으로 POST 또는 PUT 요청과 같은 일종의 상태 업데이트를 수행하는 작업으로 제한됩니다.
  2. 응답은 HTTP 202 Accepted 상태를 반환하며, 요청이 처리를 위해 대기열에 있음을 나타냅니다.
  3. 응답에는 상태 엔드포인트의 URL를 지정하는 위치 HTTP 헤더도 포함됩니다.
  4. 클라이언트 애플리케이션은 작업의 상태 (대기, 실행, 성공, 실패 등)를 검색하기 위해 상태 엔드포인트를 폴링합니다.
  5. 작업이 완료되면 일반적으로 상태 엔드포인트는 결과 리소스 (즉, 생성/업데이트된 리소스)의 URL를 지정하는 다른 위치 HTTP 헤더를 반환합니다.
  6. 클라이언트 애플리케이션이 이 URL에 리소스 검색 요청을 발행합니다.

다음 해결방안은 HTTP 요청을 발행하는 코드가 자동으로 위의 단계를 따르도록 Axios 인터세버나 helper 함수 내부의 패턴을 적용합니다.

export default function ({ $axios }) {
  const succeeded = "Succeeded";
  const failed = "Failed";
  $axios.onResponse(async (response) => {
    // 202응답이 아닌경우, 정상적으로 반환합니다.
    // 여기서 풀링이 필요한 상태일때 202응답을 주기로 약속한 경우입니다.
    if (response.status !== 202) return response;

    // 202 응답코드: 폴링이 필요하다고 사용합니다.
    console.log("HTTP 202 상태코드를 받아서 폴링작업을 합니다.");
    console.log(`${response.header.location} 에서 실행 중인 작업`);

    // 초기 작업상태를 검색합니다
    let pollingResponse = await $axios.get(respose.header.location);
    console.log(`초기 작업상태: ${pollingResponse.data.status}`);

    // 성공하지도 않고,실패하지도 않은 상태일때 계속 반복합니다.
    while (
      pollingResponse.data.status !== succeeded &&
      pollingResponse.data.status !== failed
    ) {
      // 2초동안 axios호출해서 pollingResponse 결과값을 업데이트합니다.
      setTimeout(async () => {
        pollingResponse = await $axios.get(response.header.location);
        console.log(`폴링상태의 작업상태: ${pollingResponse.data.status}`);
      }, 2000);
    }

    // 만약 작업이 실패한 경우 실행합니다.
    // 실패를 예외로 처리해서 다음과 같이 처리할 수 있습니다.
    if (pollingResponse.data.status === failed) throw "작업실패";
    console.log("작업성공!");
    console.log(
      `${pollingResponse.data.resourceLocation}에서 리소스 검색중입니다.`
    );

    // 작업이 설공하면 최종 리소스 위치에서 응답을 반환합니다.
    return await $axios.get(pollingResponse.data.resourceLocation);
  });
}

인터셉터 로직이 설정되면 HTTP 202 코드를 반환하기 위해 필요한 모든 요청이 자동으로 폴링됩니다.
호출 코드는 다음 예시처럼 장기적으로 실행되는 작업을 알 필요없이 결과 리소스 위치에서 응답을 수신합니다.

async function testFunction() {
  try {
    const response = await this.$axios.put('ENDPOINT', payload);
    // 이 시점에서 모든 폴링작업이 처리되었듯이, 응답은 업데이트된 리소스입니다.
  }
  catch (err) {
    // 만약 실행작업이 실패하면 해당 위치에서 처리할 수 있습니다.
  }
}
profile
새로운 것을 도전하고 노력한다

0개의 댓글