Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- LifeCycle
- node.js
- GraphQL
- bean
- javascript
- 코딩테스트
- Linux
- dfs
- MySQL
- REST API
- css
- html
- Spring
- 프로그래머스
- 인접리스트
- TIL
- 탐욕법
- nestjs
- typescript
- Deep Dive
- 자료구조
- 알고리즘
- 인접행렬
- java
- Kubernetes
- OOP
- puppeteer
- Interceptor
- winston
- JWT
Archives
- Today
- Total
처음부터 차근차근
[TIL - 231127] NestJS 공식 문서 정리 및 강의 수강 본문
728x90
[TIL - 23XXXX]
오늘 한 일
- NestJS 강의 수강
- NestJS 공식 문서 기초 정리
NestJS 강의 수강
- Fastcampus 강의를 들으면서 많은 모듈 사용방법을 간단하게 익혔다.
- 과거 TypeORM migration 방법도 다시한번 정리하였다.
1. interceptor를 통해 Pagenation을 위한 데이터 로직 변경 진행
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Request } from 'express';
import { Observable, map } from 'rxjs';
// Pagenation을 위한 Interceptor 구현 진행
@Injectable()
export class TransformInterceptor<T, R> implements NestInterceptor<T, R> {
intercept(context: ExecutionContext, next: CallHandler): Observable<R> {
return next.handle().pipe(
// rxjs의 map 메서드를 이용한다.
map((data) => {
// http request에서 query를 받아오기 위함.
const http = context.switchToHttp();
const request = http.getRequest<Request>();
// return 하는 객체가 배열일 경우 페이지네이션을 위해 객체 항목을 수정한다.
// 이는 저번에 작성했던 Swagger에 있는 명세와 동일하게 맞추기 위함.
if (Array.isArray(data)) {
return {
page: Number(request.query['page'] || 1),
size: Number(request.query['size'] || 20),
items: data,
};
} else {
return data;
}
}),
);
}
}
2. swagger에 보안 지정
// main.ts
import * as basicAuth from 'express-basic-auth';
// ..생략
const configService = app.get(ConfigService);
const stage = configService.get('STAGE');
// local과 dev 환경에서만 Swagger가 보일수 있게 설정하기
const SWAGGER_ENVS = ['local', 'dev'];
if (SWAGGER_ENVS.includes(stage)) {
app.use(
// swagger 경로 암호 설정
['/docs', 'docs-json'],
// express-basic-auth를 통해 암호 설정 진행
basicAuth({
challenge: true,
users: {
[configService.get('swagger.user')]: configService.get('swagger.password'),
},
}),
);
const config = new DocumentBuilder()
.setTitle('NestJS project')
.setDescription('NestJS project API description')
.setVersion('1.0')
.addBearerAuth()
.build();
const customOption: SwaggerCustomOptions = {
swaggerOptions: {
persistAuthorization: true,
},
};
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('docs', app, document, customOption);
}
3. env에 데이터 입력
import { registerAs } from '@nestjs/config';
// registerAS를 통해 configObject와 Factory를 설정해준다.
export default registerAs('swagger', async () => {
return {
user: process.env.SWAGGER_USER || 'park',
password: process.env.SWAGGER_PASSWORD || 'park',
};
});
4. Rate Limit 설정 진행
Throttler를 통해 brutal force 방어하며, guard를 통해 적용한다.
import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common';
import { Body, Controller, Get, Param, Post, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiExtraModels, ApiTags } from '@nestjs/swagger';
import { VideoService } from './video.service';
import { CreateVideoReqDto, FindVideoReqDto } from './dto/req.dto';
import { PageReqDto } from 'src/common/dto/req.dto';
import { CreateVideoResDto, FindVideoResDto } from './dto/res.dto';
import { ApiGetItemsResponse, ApiGetResponse, ApiPostResponse } from 'src/common/decorator/swagger.decorator';
import { PageResDto } from 'src/common/dto/res.dto';
import { ThrottlerBehindProxyGuard } from 'src/common/guards/throttler-behind-proxy.guard';
import { SkipThrottle, Throttle } from '@nestjs/throttler';
@UseGuards(ThrottlerBehindProxyGuard)
@ApiTags('Video')
@ApiExtraModels(FindVideoReqDto, PageReqDto, CreateVideoResDto, FindVideoResDto, PageResDto)
@Controller('api/videos')
export class VideoController {
@ApiBearerAuth()
@ApiGetItemsResponse(FindVideoResDto)
@SkipThrottle()
@Get()
findAll(@Query() { page, size }: PageReqDto) {
return this.videoService.findAll();
export class VideoController {
}
@ApiBearerAuth()
// Throttle을 조금 더 타이트하게 주고싶은 경우
@Throttle({ default: { ttl: 3, limit: 10 } })
@Get(':id/download')
async download(@Param() { id }: FindVideoReqDto) {
return this.videoService.download(id);
import { Injectable } from '@nestjs/common';
import { ThrottlerGuard } from '@nestjs/throttler';
@Injectable()
export class ThrottlerBehindProxyGuard extends ThrottlerGuard {
protected getTracker(req: Record<string, any>): Promise<string> {
// IP가 여러 군데를 통과해서 들어오는데, 가장 첫번째 IP가 클라이언트이다.
return req.ips.length ? req.ips[0] : req.ip;
}
}
import { Video } from './entity/video.entity';
import { VideoController } from './video.controller';
import { VideoService } from './video.service';
import { APP_GUARD } from '@nestjs/core';
import { ThrottlerGuard } from '@nestjs/throttler';
@Module({
imports: [TypeOrmModule.forFeature([Video])],
controllers: [VideoController],
providers: [VideoService],
providers: [VideoService, { provide: APP_GUARD, useClass: ThrottlerGuard }],
})
export class VideoModule {}
다양한 것들을 공부하였으며, 이것들 또한 정리가 필수적이다.
NestJS 공식문서 정리 진행
- NestJS 강의를 들으면서, 대부분의 내용이 공식 문서에 해당되는 것을 확인하였다.
- 따라서 이 부분도 같이 정리를 하면 좋겠다는 생각을 하였다.
- 하지만 해석하는데 시간이 오래 걸리는 것 같아, 간단하게 정리하는 것이 좋겠다는 판단.
'TIL' 카테고리의 다른 글
[TIL - 231208] 기술면접 회고, 블로그 이관 관련 정리 진행 (0) | 2023.12.09 |
---|---|
[TIL - 231204] 기업 면접 진행, 기업 과제 Refactoring 진행 (0) | 2023.12.04 |
[TIL - 231125] NestJS 정리, HTML 기초 강의 수강 (1) | 2023.11.25 |
[TIL - 231124] NestJS 기본 정리, GraphQL, REST API 설계 원칙 (1) | 2023.11.24 |
[TIL - 231123] 코딩 과제 진행 (1) | 2023.11.23 |