• Home
  • About
    • lahuman photo

      lahuman

      열심히 사는 아저씨

    • Learn More
    • Facebook
    • LinkedIn
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

nestjs에서 swagger사용시, generic 타입에 대한 response schema 처리

22 Mar 2023

Reading time ~1 minute

nestjs에서 swagger사용시, generic 타입에 대한 response schema 처리

페이징 처리시 다음의 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"
    }
  ]
}

참고자료

  • How to generate Generics DTOs with nestjs/swagger


repositorynode Share Tweet +1