티스토리 뷰

BACKEND

nestjs API Rate Limit 적용하기

나를찾는아이 2023. 1. 17. 14:58
728x90
반응형

nestjs에는 nestjs/throttler라는 기본패키지를 제공하고 있어

 

API의 과도한 호출을 막기 위한 API Rate Limit을 쉽게 적용할수 있습니다

 

$ npm i --save @nestjs/throttler

패키지를 설치하고

 

@Module({
  imports: [
    ThrottlerModule.forRoot({
      ttl: 60,
      limit: 10,
    }),
  ],
})
export class AppModule {}

ThrottlerModule을 import 하세요

 

 

그리고 guard를 이용하여 전체 서비스에 적용할수 있습니다

 

{
  provide: APP_GUARD,
  useClass: ThrottlerGuard
}

 

 

Rate Limit가 필요없는곳에서는 @SkipThrottle 이라는 데코레이터를 통해서 해당 기능을 사용하지 않을수 있습니다

@SkipThrottle()
@Controller('users')
export class UsersController {}

 

 

기존 값을 덮어쓰기 할수도 있습니다

@Throttle(3, 60)
@Get()
findAll() {
  return "List users works with custom rate limiting.";
}

 

 

해당 기능을 사용할때는 주의해야할 사항이 있습니다

 

nestjs/throttler는 ip를 기반으로 API Rate Limit을 체크하고 있습니다

 

특정 IP를 기준으로 특정 API를 몇번호출했는지 체크하여 API Rate Limit을 적용하는 방식입니다

 

 

 

여러분이 운영하는 앱의 아키텍쳐 구성이 아래의 구성처럼 load balancer를 통해 트래픽을 받고 있거나

 

또 다른종류의 proxy가 앞단에 있어 해당 프록시가 여러분의 앱보다 먼저 트래픽을 받아 전송해주고 있다면

 

 

 

여러분의 앱은 로드밸런서 또는 proxy의 IP를 전달받게 됩니다

 

그렇게 될경우 올바르게 IP기반으로 차단이 되어지지 않기 때문에

 

Proxy 또는 로드밸런서로부터 전달된 X-Forwarded-For 헤더값을 사용해야합니다

 

그러면 최종 enduser의 IP 기반으로 체크를 할수 있습니다

 

 

이 기능을 위한 처리는 다음과 같이 ThrottlerGuard를 확장한 클래스를 Guard로 사용하는것으로 가능합니다

 

반드시명심해야할것은 nestjs에서 express를 사용하고 있는 경우

 

"trust proxy" 설정을 해주어야만 nestjs에서 올바르게 client ip를 가져올수 있습니다

 

// throttler-behind-proxy.guard.ts
import { ThrottlerGuard } from '@nestjs/throttler';
import { Injectable } from '@nestjs/common';

@Injectable()
export class ThrottlerBehindProxyGuard extends ThrottlerGuard {
  protected getTracker(req: Record<string, any>): string {
    return req.ips.length ? req.ips[0] : req.ip; // individualize IP extraction to meet your own needs
  }
}

// app.controller.ts
import { ThrottlerBehindProxyGuard } from './throttler-behind-proxy.guard';

@UseGuards(ThrottlerBehindProxyGuard)


// main.ts
app.set('trust proxy', true)

 

해당 설정이 완료되면 req.ips에 배열형태로 값이 전달며

 

[최종유저IP, 유저에 가까운 proxy IP, 그 다음으로 proxy IP]

 

이러한 순서로 IP가 담겨져옵니다

 

이 값에서 0번째 배열의 값을 사용하시면 됩니다

 

 

 

또하나의 팁!

 

nestjs/throttler는 기본적으로 메모리를 사용하여 호출 횟수를 카운팅 하고 있습니다

 

그렇기 때문에 여러분의 서버인스턴스가 여러개로 나누어져있다면

 

각각의 서버마다 호출횟수를 메모리에 저장하고 있기 때문에

 

예를 들어 3대의 서버가 1분당 100회의 Rate Limit을 가지고 있을때

 

특정 유저의 API 호출이 3대의 서버에 번갈아가면서 동작한다면

 

각 서버당 1분 100회의 Rate Limit을 갖게되어

 

최대 300회의 Rate Limit을 갖게 될수 있습니다

 

 

모든 인스턴스가 동일한 호출횟수값을 참조하게 하기 위해서는 메모리가 아닌 redis나 별도의 스토리지를 이용해야합니다

 

728x90
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함