NestJS 공식문서: https://docs.nestjs.com/openapi/introduction
$ npm install --save @nestjs/swagger swagger-ui-express
main.ts
import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle('Cat example')
.setDescription('cat api description')
.setVersion('1.0.0')
.addTag('cat')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document); // swagger endpoint 설정
await app.listen(3000);
}
bootstrap();
config가 swagger의 option으로 Title, Description, Version등을 설정할 수 있다.
setup()으로 swagger endpoint를 설정할 수 있다.
localhost/8000/api 로 접속하면 swagger 문서를 볼 수 있다.
Nest가 자동으로 controller를 분석해서 해당하는 api를 보여준다.
또한 해당 Api에 대한 설명을 제공하고자 할 때는 해당 controller 파일에서 @ApiOperation()을 추가하면 된다.
cats.controller.ts
import { ApiOperation } from '@nestjs/swagger';
@ApiOperation({ summary: '회원가입' })
@Post()
async signUp(@Body() body: CatRequestDto) {
return await this.catsService.signUp(body);
}
또한 request를 보낼 때 어떤 정보를 담아야하는지에 대한 정보를 제공하기 위해서는 CatRequestDto를 정의한 파일에서 @ApiProperty 데코레이터를 추가해주면 된다.
dto > cats.request.dto.ts
import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
export class CatRequestDto {
@ApiProperty({
example: 'test@naver.com',
description: 'email',
required: true,
})
@IsEmail()
@IsNotEmpty()
email: string;
}
response에 대한 정보는 controller 파일에서 @ApiResponse 데코레이터로 설정할 수 있다.
cats.controller.ts
@ApiResponse({
status: 500,
description: '서버 에러',
})
@ApiResponse({
status: 200,
description: '성공',
type: CatRequestDto,
})
@ApiOperation({ summary: '회원가입' })
@Post()
async signUp(@Body() body: CatRequestDto) {
return await this.catsService.signUp(body);
}
status 200으로 성공하는 경우 response type을 Dto를 사용해서 설정할 수 있다.
response dto를 생성해서 사용한다.
> dto > cat.dto.ts
import { ApiProperty } from '@nestjs/swagger';
import { Cat } from '../cats.schema';
export class ReadOnlyCatDto {
@ApiProperty({
example: '123',
description: 'id',
})
id: string;
@ApiProperty({
example: 'test@naver.com',
description: 'email',
required: true,
})
email: string;
@ApiProperty({
example: 'kong',
description: 'name',
required: true,
})
name: string;
}
id, email, name은 다 schema에서 정의한 내용이지만 cat.controller.ts나 cat.dto.ts에서 다시 정의하여 사용하고 있다.
재사용성을 높이기 위해서 schema에서 @ApiProperty를 추가해서 정의하고 이를 재사용하는 방향으로 리팩토링을 하면 좋을 것 같다.
cats.schema.ts
@Schema(options)
export class Cat extends Document {
@ApiProperty({
example: 'test@naver.com',
description: 'email',
required: true,
})
@Prop({
required: true,
unique: true,
})
@IsEmail()
@IsNotEmpty()
email: string;
...
}
cat.dto.ts
import { ApiProperty, PickType } from '@nestjs/swagger';
import { Cat } from '../cats.schema';
export class ReadOnlyCatDto extends PickType(Cat, ['email', 'name'] as const) {
@ApiProperty({
example: '123',
description: 'id',
})
id: string;
}
Response는 password를 반환해주지 않는다.
PickType(Cat, ['email', 'name'] as const)을 이용하면 Cat이라는 클래스에서 필요한 부분만 가져올 수 있다.
cats.request.dto.ts
import { PickType } from '@nestjs/swagger';
import { Cat } from '../cats.schema';
export class CatRequestDto extends PickType(Cat, [
'email',
'name',
'password',
] as const) {}
Cat 스키마를 상속받는다.