일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Express
- Python
- cookie
- flask
- 자료구조
- GIT
- nodejs
- Bull
- 정렬
- class
- Nest.js
- JavaScript
- TypeScript
- Queue
- nestjs
- jest
- game
- MySQL
- Sequelize
- MongoDB
- mongoose
- typeORM
- AWS
- OCR
- 공룡게임
- 게임
- dfs
- Dinosaur
- react
- Today
- Total
포시코딩
2월24일 - @nestjs/throttler 본문
개요
Nest.js에서는 @nestjs/throttler 를 통해
특정 유저(IP 기준)가 짧은 시간내에 여러 번 같은 API를 호출하는 것을 방지할 수 있다.
이것을 Rate Limit 기능이라고 한다.
설치
https://www.npmjs.com/package/@nestjs/throttler
npm i @nestjs/throttler
사용 방법
코드
app.module.ts
// ...다른 import 생략
import { ThrottlerGuard, ThrottlerModule } from '@nestjs/throttler'
import { APP_GUARD } from '@nestjs/core';
@Module({
imports: [
// ...생략
ThrottlerModule.forRoot({
ttl: 60,
limit: 2, // ttl 동안 limit 번 만큼의 요청만 받는다.
}),
],
controllers: [AppController],
providers: [
AppService,
{
provide: APP_GUARD,
useClass: ThrottlerGuard,
}
],
})
export class AppModule {}
app.module에서 간단하게 설정할 수 있는데
ThrottlerModule.forRoot({
ttl: 60,
limit: 2, // ttl 동안 limit 번 만큼의 요청만 받는다.
}),
import에 위 코드를 추가하고
{
provide: APP_GUARD,
useClass: ThrottlerGuard,
}
providers에 위 코드를 추가하면 된다.
이상하게 나는 @nestjs/throttler 관련 class들이 자동완성으로 import 되지 않는 문제가 있어
직접 import를 다 써주었다.
이렇게 작성하면 위의 ttl, limit에 적은 옵션을 통해
모든 API에 대해 60초 동안 2번 만큼의 요청만 할 수 있다.
결과 확인
3번 이상 호출 시 429 status code 에러를 내며
ThrottleException을 통해 너무 많은 요청이라는 메시지를 받게 된다.
429 status code 추가 설명.
추가 기능
하지만 이렇게 모든 API에 대해 제한을 걸어 버리면
throttler를 적용하고 싶지 않은 API에도 제한이 걸리게 된다.
그럴 때는 아래와 같이 사용할 데코레이터들이 존재한다.
@SkipThrottle()
@SkipThrottle()
@Get('/hot-articles')
async getHotArticles() {
return await this.boardService.getHotArticles();
}
이처럼 controller의 메서드 위에 사용 시 해당 API에 대해서는 throttler의 제한 없이
사용이 가능하며
@SkipThrottle()
@Controller()
export class AppController {
@SkipThrottle(false)
dontSkip() {} // app.module.ts에서 설정한 글로벌 throttle 설정이 적용된다.
doSkip() {} // controller 위의 @SkipThrottle() 덕분에 throttle 제한과 관계없이 사용가능
}
이런식으로 controller 전체에 @SkipThrottle()을 먹인 후
특정 메서드에만 @SkipThrottle(false)를 적용할 수도 있다.
@Throttle()
@Throttle(5, 60)
@Get('/hot-articles')
async getHotArticles() {
return await this.boardService.getHotArticles();
}
아니면 직접 Rate limit을 특별하게 적용할 수도 있다.
@Throttle(limit, ttl)의 형태로 적용하면 위의 메서드는 60초에 5번까지만 호출이 가능하게 변한다.
++ 참고사항
나는 이상하게 @SkipThrottle()과 @Throttle()도 import 자동완성이 되지 않아 헤맸었는데
import { SkipThrottle, Throttle } from '@nestjs/throttler';
직접 작성하고 나서야 정상 작동을 확인할 수 있었다. 참고!
정리
자의든 타의든 특정 API에 대해 한번에 여러 번 요청하는 일이 생길 수 있고
만에 하나 DDoS, DoS 같은 공격이 있을 때
DDoS 공격 방어는 힘들더라도 DoS 공격에 대한 방어는 어느 정도 가능하니
Nest.js로 서버를 구축한다면 @nestjs/throttler를 통해 최소한의 방어책을 구축하길 추천한다.
'TIL' 카테고리의 다른 글
2월27일 - Nest.js에서 jest로 테스트 코드 작성하기 (0) | 2023.02.27 |
---|---|
2월25일 - ERROR [TypeOrmModule] Unable to connect to the database. Retrying (1) (0) | 2023.02.26 |
2월23일 - debounce, throttle (0) | 2023.02.23 |
2월22일 - Authentication, Authorization 차이 (0) | 2023.02.22 |
2월21일 - nestjs-form-data (0) | 2023.02.21 |