ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • nestjs에서 swagger사용시, generic 타입에 대한 response schema 처리
    NodeJS 2023. 6. 5. 14:01

    페이징 처리시 다음의 DTO를 사용하고 있습니다.

    export class Pagination<T> {
      @ApiProperty()
      public results: T[];
      @ApiProperty()
      public page_total: number;
      @ApiProperty()
      public total: number;
    
      constructor(paginationResults: PaginationResultInterface<T>) {
        this.results = paginationResults.results;
        this.page_total = paginationResults.results.length;
        this.total = paginationResults.total;
      }
    }

    다른 부분의 표현은 문제가 없는데, generic 타입인 public results: T[];를 제대로 표현하지 못해서 아쉬움을 느끼고 있었습니다.

    How to generate Generics DTOs with nestjs/swagger를 찾아서 적용하니 잘 표현 되네요.

    적용 방법은 아래와 같습니다.

    우선 신규 ApiOkResponsePaginated 데코레이터를 추가 합니다.

    import {
      ApiOkResponse,
      getSchemaPath,
      ApiExtraModels,
      ApiProperty,
    } from '@nestjs/swagger';
    import { PaginationResultInterface } from './pagination.results.interface';
    import { applyDecorators, Type } from '@nestjs/common';
    
    export class Pagination<T> {
      // 중요! ApiProperty 를 사용하지 않음
      public results: T[];
      @ApiProperty()
      public page_total: number;
      @ApiProperty()
      public total: number;
    
      constructor(paginationResults: PaginationResultInterface<T>) {
        this.results = paginationResults.results;
        this.page_total = paginationResults.results.length;
        this.total = paginationResults.total;
      }
    }
    
    // 데코레이터 추가
    export const ApiOkResponsePaginated = <DataDto extends Type<unknown>>(
      dataDto: DataDto
    ) =>
      applyDecorators(
        ApiExtraModels(Pagination, dataDto),
        ApiOkResponse({
          schema: {
            allOf: [
              { $ref: getSchemaPath(Pagination) },
              {
                properties: {
                  data: {
                    type: 'array',
                    items: { $ref: getSchemaPath(dataDto) },
                  },
                },
              },
            ],
          },
        })
      );

    마지막으로 아래와 같이 사용하려는 컨트롤러에서 @ApiResponse 대신 @ApiOkResponsePaginated 를 사용합니다.

      @ApiOperation({ summary: '아이템 상품 목록 조회' })
      @ApiOkResponsePaginated(ItmPrdMRO) // ApiOkResponsePaginated와 함께 사용할 generic 타입 지정
      @Get('prd/list')
      async getItmPrdMPaginate(@Query() dto: FindByCondDto) {
        return await this.itmPrdMService.getItmPrdMPaginate(dto);
      }

    설정을 하고 결과를 확인하면 아래와 같이 원하는 response schema를 확인 할 수 있습니다.

    {
      "page_total": 0,
      "total": 0,
      "data": [
        {
          "id": 0,
          "admAdminMIdNm": "string",
          "itmDcd": "string",
          "imgPath": "string",
          "itmWearDcdNm": "string",
          "avlbStrtDt": "string",
          "avlbEndDt": "string",
          "appItmNm": "string",
          "itmNm": "string",
          "prdAmt": 0,
          "modDtm": "string"
        }
      ]
    }

    참고자료

    'NodeJS' 카테고리의 다른 글

    정규식을 이용해서 package-lock.json의 주소를 변경 처리  (0) 2023.06.02
    VSCode에서 Jest Debug 설정  (0) 2023.05.31
    nestjs-pino 로깅 처리  (0) 2023.05.30
    Node.js 메모리 옵션  (0) 2023.05.29
    Nodejs 동작 훑어보기  (0) 2023.05.27
Designed by Tistory.