[Nest.js] swagger 적용하기

강버섯·2022년 5월 19일
5

NEST.JS🦁

목록 보기
3/3
post-thumbnail

👉 swagger?

👉 Nest.js에서 swagger 사용하기

✏️ 사용하기 전에

Nest.js를 global로 설치한 후, nest 명령어를 이용하여 swagger를 적용해볼 Nest.js 프로젝트를 생성한다.

# Nest.js 설치
$> npm i -g @nestjs/cli

# Nest.js 프로젝트 생성
$> nest new swagger-study

Nest.js 프로젝트를 생성 완료를 했으면 swagger를 사용하기 위해 dependency를 설치해준다.

$> npm install --save @nestjs/swagger swagger-ui-express

# fastify를 사용하는 경우 swagger-ui 대신 fastify-swagger로 설치
$> npm install --save @nestjs/swagger fastify-swagger

✏️ 프로젝트에 swagger 적용

Swagger를 사용하기 위해서 main.ts 파일에 swagger document를 작성한다.

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();

Swagger에 대한 document를 작성한 후에는 SwaggerModule의 .setup() 을 호출하여 Swagger UI의 path를 연결해준다.
위와 같은 값으로 설정한 후 로컬로 띄운다면, http://localhost:3000/api로 접속하였을 때 Swagger UI를 확인할 수 있다.

Swagger document를 바로 main.ts에 작성하지 않고, 별도의 document로 작성한 뒤 main.ts에 mount 하는 방식으로 진행할 수도 있다.

swagger.documnet.ts 👇

import { DocumentBuilder, SwaggerModule } 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();
  }
}

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 BaseAPIDocumentation().initializeOptions();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api', app, document);

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

Swagger document에 대한 기본 설정을 마친 후 npm run start를 통해 프로젝트를 실행시킨후 Swagger UI endpoint로 들어가면 다음과 같이 작성한 document에 맞는 값으로 설정된 swagger를 확인할 수 있다.

✏️ API 별 상세 swagger 작성

swagger에서는 다양한 decorator를 제공해서 swagger document에 쉽게 api에 대한 설명을 추가할 수 있다.

📁 DTO

API에서 주고 받을 모델에 대한 명세를 @ApiProperty annotation을 통해 swagger document에 작성할 수 있다.
example property를 통해 모델의 property에 대한 예시값을, property에 대한 설명을 description property를 통해 swagger document에서 보여줄 수 있다.

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;
}

📁 endpoint

  • @ApiTags
    swagger에 tag를 생성해준다.
    controller에 @ApiTags를 사용하면 해당 controller에 속해있는 모든 api(method)들이 작성한 tag 하위에 나타나게 된다.
import { Controller, Get, Post } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';

@ApiTags('Swagger') // swagger에 tag를 생성해줌
@Controller('swagger')
export class SwaggerController {
	
  	@ApiOperation({ summary: 'swagger get endpoint'}) // api 설명
    @Get()
    getSwagger() {
		return 'this is get swagger page';
    }
  
  	@Post()
  	postSwagger() {
      return 'this is post swagger paoge';
    }
}

  • @ApiOperation
    API 동작에 대한 설명을 추가할 수 있다.
    summary property를 사용하면 해당 API에 대한 간략한 설명을 작성해볼 수 있다.
import { Controller, Get, Post } from '@nestjs/common';
import { ApiOperation , ApiTags } from '@nestjs/swagger';

@ApiTags('Swagger') // swagger에 tag를 생성해줌
@Controller('swagger')
export class SwaggerController {
	
  	@ApiOperation({ summary: 'swagger get endpoint'}) // api 설명
    @Get()
    getSwagger() {
		return 'this is get swagger page';
    }
  
  	@ApiOperation({ summary: 'swagger post endpoint' })
  	@Post()
  	postSwagger() {
      return 'this is post swagger paoge';
    }
}

  • @ApiResponse
    API의 Response 값에 대한 예시를 swagger 문서에 표시할 수 있다.
import { Controller, Get, Post } from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';

@ApiTags('Swagger')
@Controller('swagger')
export class SwaggerController {
  @ApiOperation({ summary: 'swagger get endpoint' })
  // response 값에 대한 예시 표시
  @ApiResponse({
    status: 403,
    description: 'Forbidden',
  })
  @Get()
  getSwagger() {
    return 'this is get swagger page';
  }

  @ApiOperation({ summary: 'swagger post endpoint' })
  @Post()
  postSwagger() {
    return 'this is post swagger page';
  }
}


@ApiResponse를 사용할 때 schema property를 이용한다면 response로 반환하는 값에 대한 명세를 swagger document에 표시할 수 있다.

@ApiResponse로 사용할 경우에는 status를 지정해서 작성해줘야 하지만 swagger에서 각 status에 따른 api response annotation을 별도로 제공하기 때문에 status에 맞는 annotation 사용을 통해서도 response 예시를 표시할 수 있다.
📁 제공하는 다양한 status별 annotation들

import { Controller, Get, Post } from '@nestjs/common';
import { ApiBody, ApiConsumes, ApiOkResponse, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';

@ApiTags('Swagger')
@Controller('swagger')
export class SwaggerController {
  @ApiOperation({ summary: 'swagger get endpoint' })
  // response 값에 대한 예시 표시
  @ApiResponse({
    status: 403,
    description: 'Forbidden',
  })
  // status 200에 대한 response 표시를 제공
  @ApiOkResponse({
    description: 'Success',
  })
  @Get()
  getSwagger() {
    return 'this is get swagger page';
  }

  @ApiOperation({ summary: 'swagger post endpoint' })
  @Post()
  postSwagger() {
    return 'this is post swagger page';
  }
}

  • @ApiQuery
    Query로 받을 값에 대한 명세를 표시할 수 있다.
    name property를 통해 query를 받은 변수의 이름을 설정할 수 있고, type property를 통해 어떤 type으로 query를 받을 것인지 지정할 수 있다.
    enum property를 이용하면 enum에 지정된 값으로 제한이 된다는 것을 표시할 수 있으며, swagger를 통해 실행을 할 때 enum에 해당하는 값으로 api를 실행해볼 수 있다.
import { Body, Controller, Get, Post } from '@nestjs/common';
import {
  ApiOperation,
  ApiParam,
  ApiTags,
} from '@nestjs/swagger';
import { CreateSwaggerDto } from './dto/CreateSwaggerDto.dto';

@ApiTags('Swagger')
@Controller('swagger')
export class SwaggerController {
  @ApiOperation({ summary: 'swagger get endpoint' })
  @ApiQuery({
    name: 'name',
    enum: ['enum1', 'enum2'],
  })
  @Get()
  getSwagger() {
    return 'this is get swagger page';
  }
}


  • @ApiParam
    Param으로 받을 값에 대한 명세를 표시할 수 있다.
    name property를 이용해서 parameter의 값을 받을 변수의 이름을 지정하고, type property를 통해 param의 type을 명시할 수 있다.
import { Controller, Get, Post } from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';

@ApiTags('Swagger')
@Controller('swagger')
export class SwaggerController {

@ApiTags('Swagger')
@Controller('swagger')
export class SwaggerController {
  @ApiOperation({ summary: 'swagger get endpoint' })
  @ApiParam({
    name: 'swagger param',
    type: 'string',
  })
  @Get()
  getSwagger() {
    return 'this is get swagger page';
  }
}

  • @ApiBody
    Body로 받을 값에 대한 명세를 표시할 수 있다.
    description property를 사용하면 body에 대한 설명을 표시할 수 있고, type property를 통해 입력 받는 type을 표시해줄 수 있다.
    만일 지정한 type(DTO)에 @ApiProperty를 통해 작성해두었다면 입력 받을 type에 대한 세부적인 정보를 swagger document에서 확인할 수 있다.
import { Controller, Get, Post } from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';

@ApiTags('Swagger')
@Controller('swagger')
export class SwaggerController {

  @ApiOperation({ summary: 'swagger post endpoint' })
  @ApiConsumes('multipart/form-data') // Body를 받을 때의 mime type 설정
  // Body에 대한 명세 설정
  @ApiBody({
    description: 'post swagger',
    type: CreateSwaggerDto,
  })
  @Post()
  postSwagger(@Body createSwaggerDto: CreateSwaggerDto) {
    return 'this is post swagger page';
  }
}

위와 같은 decorator 외에도 다양한 decorator를 사용할 수 있으며, 원하는 기능의 decorator를 커스텀하여 사용할 수도 있다.

profile
무럭무럭 버섯농장

0개의 댓글