-
NestJs Swagger 문서 만들기공부하기/node.js 2023. 3. 2. 22:02
Swagger가 뭐야?
API 문서화 툴로서, API의 요청/응답 데이터, 파라미터, 경로, 헤더 등 API를 이용하는 데 필요한 모든 정보를 제공합니다.
또 API를 이용하는 클라이언트가 API를 쉽게 이해하고, 테스트할 수 있으며, 개발자는 API의 사용 방법을 명확하게 이해할 수 있습니다.
저희는 NestJs에서 소개하는 @nestjs/swagger 모듈을 사용하여 스웨거 문서를 만들도록 하겠습니다.
@nestjs/swagger를 사용하여 swagger 문서 만들기
1. 모듈 install
npm install --save @nestjs/swagger
2. main.ts에서 swagger setup
main.ts async function bootstrap() { ... const config = new DocumentBuilder() .setTitle('설문조사 스웨거') .setDescription('api 설명서') .setVersion('1.0') .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api', app, document); ... } bootstrap();
3. 'http://localhost:[자신의_포트번호]/api/' 로 접속시 api와 스키마만 존재하는 비어있는 스웨거 문서가 자동으로 제작되어 있습니다.
Types and parameters
@ApiPropery 어노테이션을 사용하여 스웨거 schemas 프로퍼티 제작하기
export class SurveyCreateDto implements SurveyCreateInPortInputDto { @IsString() @ApiProperty({ description: '설문지 이름', required: false, }) name: string; @IsString() @ApiProperty({ type: String, description: '설문지 상세설명', required: true, minimum: 0, maximum: 10, default: '디폴트!', }) description: string; }
- description: 프로퍼티를 설명하는 옵션입니다.
- required: 필수값 여부, default는 true
- minimum: 최소값을 명시합니다.
- maximum: 최대값을 명시합니다.
- default: default 값을 명시할 수 있습니다.
@ApiQuery 어노테이션을 사용하여 스웨거 문서 api 파라메터 queryString 제작하기
@Get('/search') @ApiQuery({ name: 'page', required: false }) @ApiQuery({ name: 'size', required: false }) @ApiQuery({ name: 'sort', enum: SORT_OPTION, required: false }) @ApiQuery({ name: 'keyword', required: false }) async search( @Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number, @Query('size', new DefaultValuePipe(10), ParseIntPipe) size: number, @Query( 'sort', new DefaultValuePipe(SORT_OPTION.ASC), new ParseEnumPipe(SORT_OPTION), ) sort: SORT_OPTION, @Query('keyword', new DefaultValuePipe('')) keyword: string, ) { ... }
- 직접 명시하지 않아도 자동으로 매칭됩니다.
- 저의 경우 쿼리 스트링의 디폴트값을 설정해뒀기 때문에 required를 변경하기 위해 사용했습니다.
@ApiParam 어노테이션을 사용하여 스웨거 문서 api 파라메터 제작하기
@Get('find/:id') @ApiParam({ name: 'id', required: true }) async findOne(@Param('id', ParseIntPipe) id: number) { ... }
- 명시적으로 작성한 url 파라메터입니다.
- 구지 작성하지 않아도 위 이미자와 동일한 결과를 볼 수 있습니다.
Operations
@ApiTags 어노테이션을 사용하여 스웨거 문서 컨트롤러 api 그룹화하기
@Controller('survey') @ApiTags('survey') export class SurveyController extends ErrorController { ... }
- @ApiTags('태그명')으로 컨트롤러에 속한 api를 그룹화합니다.
@ApiOperation 어노테이션을 사용하여 스웨거 문서 엔드포인트 설명하기
@Get('find') ... @ApiOperation({ summary: '설문지 리스트 요청', description: '설문지 리스트를 페이지 단위로 요청합니다.', }) ... }
- summary: 스웨거 문서의 엔드포인트를 펼치지 않아도 한눈에 확인할 수 있는 문구입니다.
- description: 엔드포인트를 상세 설명합니다.
@공통 응답 타입 만들기
1. 스웨거 문서에서 사용할 엔티티 클래스에 @ApiProperty() 어노테이션 추가하기
설문지 엔티티 @Entity({ name: 'survey', }) export class Survey extends BaseEntity { @Index({ fulltext: true }) @Column({ comment: '설문지 이름' }) @ApiProperty() name: string; @Column({ type: 'text', comment: '설문지 설명' }) @ApiProperty() description: string; @OneToMany((type) => Question, (question) => question.survey) @ApiProperty({ type: [Question] }) question: Question[]; } 질문 엔티티 @Entity({ name: 'question', }) export class Question extends BaseEntity { @Column({ type: 'tinyint', comment: '질문 번호' }) @ApiProperty() question_number: number; @Column({ type: 'text', comment: '질문 내용' }) @ApiProperty() text: string; @Column({ comment: '객관식/주관식' }) @ApiProperty() type: string; @Column({ type: 'int' }) @ApiProperty() survey_id: number; @ManyToOne((type) => Survey, (survey) => survey.question) @JoinColumn({ name: 'survey_id' }) survey: Survey; @OneToMany((type) => Option, (option) => option.question) @ApiProperty({ type: [Option] }) option: Option[]; @OneToMany((type) => Response, (response) => response.question) @ApiProperty({ type: [Response] }) responses: Response[]; } 선택지 엔티티 @Entity({ name: 'question_opt', }) export class Option extends BaseEntity { @Column({ type: 'tinyint', comment: '보기 넘버' }) @ApiProperty() option_number: number; @Column({ type: 'int' }) @ApiProperty() question_id: number; @Column({ type: 'varchar', comment: '보기' }) @ApiProperty() text: string; @ManyToOne((type) => Question, (opt) => opt.option) @JoinColumn({ name: 'question_id' }) question: Question; }
2. 공통 응답 타입 선언하기
import { applyDecorators, Type } from '@nestjs/common'; import { ApiOkResponse, ApiProperty, getSchemaPath } from '@nestjs/swagger'; export class ResObj<T> { @ApiProperty() data: T; constructor(data: T) { this.data = data; } } export class ResObjList<T> { @ApiProperty() data: T[]; @ApiProperty() count: number; constructor(data: T[], count: number) { this.data = data; this.count = count; } } export const ResOkObjList = <TModel extends Type<any>>(model: TModel) => { return applyDecorators( ApiOkResponse({ schema: { allOf: [ { $ref: getSchemaPath(ResObjList) }, { properties: { count: { type: 'int', default: 10, }, data: { type: 'array', items: { $ref: getSchemaPath(model) }, }, }, }, ], }, }), ); }; export const ResOkObj = <TModel extends Type<any>>(model: TModel) => { return applyDecorators( ApiOkResponse({ schema: { allOf: [ { $ref: getSchemaPath(ResObj) }, { properties: { data: { type: 'object', properties: { items: { $ref: getSchemaPath(model) }, }, }, }, }, ], }, }), ); };
3. 공통 응답 타입 스웨거 문서에 추가하기 (main.ts)
async function bootstrap() { ... const config = new DocumentBuilder() .setTitle('설문조사 스웨거') .setDescription('api 설명서') .setVersion('1.0') .build(); const options: SwaggerDocumentOptions = { extraModels: [ResObjList, ResObj], }; const document = SwaggerModule.createDocument(app, config, options); SwaggerModule.setup('api', app, document); ... } bootstrap();
4. 컨트롤러에서 사용할 엔티티 스웨거 문서에 추가하기
@Controller('survey') @ApiTags('survey') @ApiExtraModels(Survey) <- 이거!! export class SurveyController extends ErrorController { ... }
-> 엔티티는 기본적으로 스웨거가 자동으로 스웨거 스키마에 추가하지 않습니다.
그러므로 컨트롤러에서 사용하는 Survey 엔티티 클래스 타입을 @ApiExtraModels 어노테이션을 사용해서 스웨거 문서에 추가합니다.
5. 공통 응답 타입 엔드포인트에 적용하기
@Get('find') ... @ResOkObjList(Survey) ... async findAll( ... ) { ... } @Get('find/:id') ... @ResOkObj(Survey) async findOne(@Param('id', ParseIntPipe) id: number) { ... }
결과
엔드포인트 에러 리스폰스 스웨거 문서에 추가해보기
@Get('find') ... @ApiNotFoundResponse({ description: 'Not Found Error' }) <- 이거! ... async findAll( ... ) sort: SORT_OPTION, ) { ... }
- 404 에러 응답 스웨거 문서에 추가
결과
이렇게 기본적으로 스웨거 문서 제작에 필요한 어노테이션을 알아봤습니다.
'공부하기 > node.js' 카테고리의 다른 글
NestJs, Redis 캐싱 기록 (0) 2023.03.12 NestJs Cache 탐색 및 기록 (0) 2023.03.09 헥사고날 NestJs, TypeOrm dto type 리펙토링 (0) 2023.02.26 NestJs Controller @Query Pipe 기록 (0) 2023.02.25 NestJs TypeOrm Exception (0) 2023.02.24