도찐개찐

[NestJS] Swagger 사용하기 본문

NodeJS/NestJS

[NestJS] Swagger 사용하기

도개진 2023. 10. 31. 16:41

1. Nest 프로젝트 생성

$ nest new swagger-test
⚡  We will scaffold your app in a few seconds..

? Which package manager would you ❤️  to use? (Use arrow keys)
❯ npm 
  yarn 
  pnpm 

2. NestJS Swagger D/I

$ npm i @nestjs/swagger

3. 프로젝트 Swagger 적용

  1. Swagger Document 적용 방법
    • main.ts 직접 적용
    • 별도 document 객체 정의 후 main.ts에 설정 import: 단일 책임 원칙을 위해 개인적으로 추천

  1. main.ts 직접 적용 방법
    ./src/main.ts
    import { NestFactory } from '@nestjs/core';
    import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
    import { AppModule } from './app.module';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
    
      const config = new DocumentBuilder()
        .setTitle('Swagger Example')
        .setDescription('Swagger study API description')
        .setVersion('1.0.0')
        .addTag('swagger')
        .build();
    
      // config를 바탕으로 swagger document 생성
      const document = SwaggerModule.createDocument(app, config);
      // Swagger UI에 대한 path를 연결함
      // .setup('swagger ui endpoint', app, swagger_document)
      SwaggerModule.setup('api', app, document);
    
      await app.listen(3000);
    }
    bootstrap();
    3. 별도 document 객체 정의 후 main.ts에 설정 `import`./src/swagger.documnet.ts
import {DocumentBuilder} from "@nestjs/swagger";

export class BaseAPIDocument {
    public builder = new DocumentBuilder();

    public initializeOptions() {
        return this.builder
            .setTitle('Swagger Example')
            .setDescription('Swagger study API description')
            .setVersion('1.0.0')
            .addTag('swagger')
            .build();
    }
}
./src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import {BaseAPIDocument} from "./swagger.documnet";
import {SwaggerModule} from "@nestjs/swagger";

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // BaseAPIDocument 객체 내 선언된 설정 값을 리턴 받아 config 대입
  const config = new BaseAPIDocument().initializeOptions();

  // config를 바탕으로 swagger document 생성
  const document = SwaggerModule.createDocument(app, config);

  // .setup('swagger ui endpoint', app, swagger_document)
  SwaggerModule.setup('api', app, document);

  await app.listen(3000);
}
bootstrap();

4. 프로젝트 Swagger 적용 확인

  1. CMD NestJS 프로젝트 실행 명령어
    $ npm run start:dev
  2. http://{hostname}:3000/api 결과 확인

5. Decorator 적용

1. endpoint

  1. @ApiTags
    • controller에 @ApiTags를 사용하면 해당 controller에 속해 있는 모든 메소드(API endpoint)들이 작성한 태그명 하위에 표기됩니다.
    • 미작성시 default 태그에 표기 됨
      app.controller.ts
      import {Controller, Delete, Get, Post, Put} from '@nestjs/common';
      import { AppService } from './app.service';
      import {ApiTags} from "@nestjs/swagger";
      
      @ApiTags('swagger') // swagger.document 에서 빌드 된 .addTag('swagger') 에 연결
      @Controller('swagger')
      export class AppController {
        constructor(private readonly appService: AppService) {}
        @Get()
        getSwagger() {
          return 'this is swagger list page';
        }
      
        @Post()
        postSwagger() {
          return 'this is swagger insert page';
        }
      
        @Put()
        putSwagger() {
          return 'this is swagger update page';
        }
      
        @Delete()
        deleteSwagger() {
          return 'this is swagger delete page';
        }
      }

- http://{hostname}:3000/api 결과 확인

2. @ApiOperation
   - API 동작에 대한 설명 추가

app.controller.ts

import {Controller, Delete, Get, Post, Put} from '@nestjs/common';
import { AppService } from './app.service';
import {ApiOperation, ApiTags} from "@nestjs/swagger";

@ApiTags('swagger') // swagger.document 에서 빌드 된 .addTag('swagger') 에 연결
@Controller('swagger')
export class AppController {
  constructor(private readonly appService: AppService) {}

  @ApiOperation({ summary: 'swagger get endpoint'}) // api 설명
  @Get()
  getSwagger() {
    return 'this is swagger list page';
  }

  @ApiOperation({ summary: 'swagger post endpoint'}) // api 설명
  @Post()
  postSwagger() {
    return 'this is swagger insert page';
  }

  @ApiOperation({ summary: 'swagger put endpoint'}) // api 설명
  @Put()
  putSwagger() {
    return 'this is swagger update page';
  }

  @ApiOperation({ summary: 'swagger delete endpoint'}) // api 설명
  @Delete()
  deleteSwagger() {
    return 'this is swagger delete page';
  }
}
  • http://{hostname}:3000/api 결과 확인

  1. ApiResponse, Api*Response
    • @ApiResponse를 사용해 각 응답 상태를 표기할 수 있습니다. status 프로퍼티를 활용 한 응답 코드를 함께 작성해야 합니다.
    • status 에 따른 @Api*Response 사용해 status 프로퍼티를 미기재 할 수도 있습니다.
    • type
  • app.controller.ts: getSwagger(), postSwagger() 수정
    import {Controller, Delete, Get, Post, Put, Query, Req} from '@nestjs/common';
    import { AppService } from './app.service';
    import {
      ApiForbiddenResponse,
      ApiNotFoundResponse,
      ApiOkResponse,
      ApiOperation, ApiQuery,
      ApiResponse,
      ApiTags
    } from "@nestjs/swagger";
    
    @ApiTags('swagger') // swagger.document 에서 빌드 된 .addTag('swagger') 에 연결
    @Controller('swagger')
    export class AppController {
      constructor(private readonly appService: AppService) {}
    
      @ApiForbiddenResponse({
        description: 'Forbidden',
      })
      @ApiOkResponse({
        description: 'Success',
      })
      @ApiNotFoundResponse({
        description: 'Not Found',
      })
      @ApiQuery({
        name: 'name',
        type: 'string',
        description: '직원명',
      })
      @ApiQuery({
        name: 'depart',
        enum: ['part_1', 'part_2'],
        description: '부서명',
      })
      @ApiOperation({ summary: 'swagger get endpoint'}) // api 설명
      @Get()
      getSwagger(@Query('name') name: string, @Query('depart') depart: string) {
        return `this is swagger list page \nname: ${name}\ndepartment: ${depart}`;
      }
    
      @ApiResponse({
        status: 200,
        description: 'Success',
      })
      @ApiResponse({
        status: 403,
        description: 'Forbidden',
      })
      @ApiResponse({
        status: 404,
        description: 'Not Found',
      })
      @ApiParam({
        name: 'name',
        type: 'string',
        description: '직원명',
      })
      @ApiParam({
        name: 'depart',
        enum: ['part_1', 'part_2'],
        description: '부서명',
      })
      @ApiOperation({ summary: 'swagger post endpoint'}) // api 설명
      @Post()
      postSwagger(@Req() req: Request) {
        return `this is swagger insert page \nname: ${req.body['name']}\ndepartment: ${req.body['depart']}`;
      }
    
      // ... 생략 ...
        
    }

- http://{hostname}:3000/api 결과 확인


4. `@ApiQuery`, `@ApiParam`
    - `@ApiQuery`: QueryString 으로 받을 값에 대한 명세 표시
    - `@ApiParam`: Parameter 로 받을 값에 대한 명세 표시
    - `name`: 변수 이름
    - `type`: 데이터 타입
    - `enum`: 변수 값 제한으로 선택 박스 형태의 문자열 표시
- app.controller.ts: getSwagger(), postSwagger() 수정

import {Controller, Delete, Get, Post, Put, Query, Req} from '@nestjs/common';
import { AppService } from './app.service';
import {
  ApiForbiddenResponse,
  ApiNotFoundResponse,
  ApiOkResponse,
  ApiOperation, ApiQuery,
  ApiResponse,
  ApiTags
} from "@nestjs/swagger";

@ApiTags('swagger') // swagger.document 에서 빌드 된 .addTag('swagger') 에 연결
@Controller('swagger')
export class AppController {
  constructor(private readonly appService: AppService) {}

  @ApiForbiddenResponse({
    description: 'Forbidden',
  })
  @ApiOkResponse({
    description: 'Success',
  })
  @ApiNotFoundResponse({
    description: 'Not Found',
  })
  @ApiQuery({
    name: 'name',
    type: 'string',
    description: '직원명',
  })
  @ApiQuery({
    name: 'depart',
    enum: ['part_1', 'part_2'],
    description: '부서명',
  })
  @ApiOperation({ summary: 'swagger get endpoint'}) // api 설명
  @Get()
  getSwagger(@Query('name') name: string, @Query('depart') depart: string) {
    return `this is swagger list page \nname: ${name}\ndepartment: ${depart}`;
  }

  @ApiResponse({
    status: 200,
    description: 'Success',
  })
  @ApiResponse({
    status: 403,
    description: 'Forbidden',
  })
  @ApiResponse({
    status: 404,
    description: 'Not Found',
  })
  @ApiParam({
    name: 'name',
    type: 'string',
    description: '직원명',
  })
  @ApiParam({
    name: 'depart',
    enum: ['part_1', 'part_2'],
    description: '부서명',
  })
  @ApiOperation({ summary: 'swagger post endpoint'}) // api 설명
  @Post()
  postSwagger(@Req() req: Request) {
    return `this is swagger insert page \nname: ${req.body['name']}\ndepartment: ${req.body['depart']}`;
  }

  // ... 생략 ...

}
  • http://{hostname}:3000/api 결과 확인

  1. @ApiProperty: DTO 모델 객체 생성
    • DTO 모델에 사용되는 객체를 Swagger 에 작성할 수 있습니다.
    • DTO 객체 생성 후 해당 객체는 반드시 Controller객체 내 request, response 중 하나에 사용이 되어야 Swagger에 노출 됩니다.
    • example 프로퍼티: 해당 모델의 예시값
    • description: 설명
  • ./src/create-swagger.dto.ts
    import {ApiProperty} from "@nestjs/swagger";
    
    export class CreateSwaggerDto {
        @ApiProperty({
            example: 'swagger',
            description: 'this is name of swagger study',
        })
        name: string;
    
        @ApiProperty({
            example: 'swagger detail',
            description: 'this is detail of swagger study',
        })
        detail: string;
    }
    - Swagger 노출 결과
  • 6. `@ApiBody`
       - Body로 받을 값에 대한 명세
       - `type` Body로 전달 받은 데이터 매핑 목적의 DTO
    - app.controller.ts: putSwagger() 수정
import {Controller, Delete, Get, Post, Put, Query, Req} from '@nestjs/common';
import { AppService } from './app.service';
import {
  ApiForbiddenResponse,
  ApiNotFoundResponse,
  ApiOkResponse,
  ApiOperation, ApiQuery,
  ApiResponse,
  ApiTags
} from "@nestjs/swagger";

@ApiTags('swagger') // swagger.document 에서 빌드 된 .addTag('swagger') 에 연결
@Controller('swagger')
export class AppController {
  constructor(private readonly appService: AppService) {}

  // ... 생략 ...

  @ApiBody({
    type: CreateSwaggerDto,
    description: 'put swagger dto',
  })
  @ApiOperation({ summary: 'swagger put endpoint'}) // api 설명
  @Put()
  putSwagger(@Body() createSwaggerDto: CreateSwaggerDto) {
    return `this is swagger update page\n${JSON.stringify(createSwaggerDto)};`
  }

  // ... 생략 ...

}

 

  • http://{hostname}:3000/api 결과 확인

데코레이션 리스트
Decorator Level Summary
@ApiBasicAuth() Method / Controller  
@ApiBearerAuth() Method / Controller  
@ApiBody() Method  
@ApiConsumes() Method / Controller  
@ApiCookieAuth() Method / Controller  
@ApiExcludeController() Controller  
@ApiExcludeEndpoint() Method  
@ApiExtension() Method  
@ApiExtraModels() Method / Controller  
@ApiHeader() Method / Controller  
@ApiHideProperty() Model  
@ApiOAuth2() Method / Controller  
@ApiOperation() Method  
@ApiParam() Method  
@ApiProduces() Method / Controller  
@ApiProperty() Model  
@ApiPropertyOptional() Model  
@ApiQuery() Method  
@ApiResponse() Method / Controller  
@ApiSecurity() Method / Controller  
@ApiTags() Method / Controller 태그(카테고리)매핑
728x90

'NodeJS > NestJS' 카테고리의 다른 글

[NestJS] 모듈 추가  (0) 2023.10.20
Comments