관리 메뉴

꿈꾸는 개발자

axios interceptor로 rate limit에 대응하기 본문

기타

axios interceptor로 rate limit에 대응하기

rickysin 2024. 5. 1. 14:55

Rate Limiting 

Rate Litming이란 일정한 시간 동안 호출할 수 있는 API 수를 의미한다. 사용자가 혹은 개발자의 실수로 일정 시간 동안 제한된 수 이상의 요청을 보내게 되면 요청이 실패하게 된다. (보통은 429 too many request error가 반환된다) 보통 서버에서 rate limit을 적용하면, 서버의 안정성을 높일 수 있다. 

 

하지만 본 글은 rate limit에 관해 다루는 글이 아니기 떄문에, 자세한 사항들은 추가적으로 학습하길 권장한다. 


프론트에서 Api call 제한하는 방법 

회사에서 rate limit에 대응의 필요성을 인지한 후 여러 방법을 시도해봤다. 

 

  • 첫 번째, tanstack Query을 활용한 요청 제한

처음에는 tanstack query에서 위와 같은 기능을 제공하지 않을까? 라는 기대와 함께 조사를 진행했지만, 

 

https://github.com/TanStack/query/discussions/4609

 

Add a rate limiting option · TanStack query · Discussion #4609

This could be a entire new library, but I think the idea really fits TanStack Query. I noticed the problem while developing a SPA using Vue Query. Constantly hot reloading and refreshing the page u...

github.com

 

아쉽게도 TkDodo에 따르면 관련 기능은 추가되지 않을 것으로 보인다. 

 

  • 그렇게 생각한 것이 두 번째 방법이다. 바로 interceptors을 사용하는 것

axios request interceptors를 사용해봤다면, 알 것으로 생각되지만, interceptors는 말 그대로 모든 요청 전에 거치는 middleware 역할을 수행한다. 그렇다면, 여기에 rate limit을 가하면 어떨까 생각을 했다. 

 

function rateLimitRequest(axiosInstance: AxiosInstance, delay: number) {
  let lastInvocationTime: number | undefined = undefined;

  const delayCalls = (config: InternalAxiosRequestConfig) => {
    const now = Date.now();
    if (lastInvocationTime) {
      lastInvocationTime += delay;
      const waitPeriodForThisRequest = lastInvocationTime - now;
      if (waitPeriodForThisRequest > 0) {
        return new Promise<InternalAxiosRequestConfig>((resolve) => {
          setTimeout(() => resolve(config), waitPeriodForThisRequest);
        });
      }
    }

    lastInvocationTime = now;
    return config;
  };

  axiosInstance.interceptors.request.use(scheduler);
}

 

위 코드를 적용하면, 한 페이지에 요청이 5개가 동시에 호출된다고 했을 때 delay 매개변수에 할당되는 number 만큼의 지연이 순차적으로 보장된다. delay가 150ms라고 했을 때 (A => 150초후 B => 150초 후 C와 같이 순차적으로 진행된다. 따라서, 매 요청 사이의 필수적으로 간격을 줘야 한다면 위 방법을 시도해보는 것도 나쁘지 않을 것 같다. 

 

단, 더 좋은 방법이 있다면...댓글로 부탁 드립니다...!!