Skip to content
Jwoo Blog
LinkedInGitHub

NestJS - Swagger를 사용합시다.

NestJS, swagger5 min read

나는 swagger를 꽤 좋아하는 편이다.
귀찮은 문서 작업을 자동화해 주는 데다가, API 테스트도 쉽게 할 수 있다.
프로젝트 첫 시작에서 멈춰있게 되는 일반 문서와 달리 관리가 편하고, 프론트 분들과 협업하기 딱 맞는다는 생각이 든다.
그래서 나는 프로젝트를 시작할 때, swagger를 도입하자고 적극 주장하는 편이다.

swagger를 사용하는 방법에는 크게 2가지가 있다.
하나는 YAML 파일이나 JSON 형태로 정의하는 것이고,

Swagger OpenAPI Guide - Base Structure swagger-guide

하나는 사용하는 프레임워크 단에서 swagger를 지원하는 라이브러리를 사용하는 것이다.

NestJS Docs - OpenAPI nestjs-swagger

그 중 나는 가독성이나 유지보수 측면에서 후자를 선호하며, 이 아래부터는 NestJS에서 Swagger를 다루는 방법을 간단히 소개한다.


패키지 설치

yarn add @nestjs/swagger

이 글에서 사용하고 있는 @nestjs/swagger 버전은 7.2.0 이다.


NestJs 설정

main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Logger } from '@nestjs/common';
import { DocumentBuilder, SwaggerCustomOptions, SwaggerModule } from '@nestjs/swagger';
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
...
// swagger 설정
const swaggerConfig = new DocumentBuilder()
.setTitle('Together')
.setDescription('The together API description')
.setVersion('1.0')
.addBearerAuth({
type: 'http',
scheme: 'bearer',
name: 'JWT',
in: 'header',
})
.build();
const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig);
const swaggerCustomOptions: SwaggerCustomOptions = {
swaggerOptions: {
persistAuthorization: true,
},
};
SwaggerModule.setup('swagger', app, swaggerDocument, swaggerCustomOptions);
const port = process.env.BACK_PORT || 9999;
await app.listen(port);
Logger.log(`Server running on ${port}`);
}
bootstrap();

swaggerConfig

const swaggerConfig = new DocumentBuilder()
.setTitle('Together')
.setDescription('The together API description')
.setVersion('1.0')
.addBearerAuth({
type: 'http',
scheme: 'bearer',
name: 'JWT',
in: 'header',
})
.build();
const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig);

DocumentBuilder 로 swagger 문서를 구성할 수 있고, 메서드로 기본 설정을 해줄 수 있다.
여기서 addBearerAuth 설정은 jwt를 이용한 api를 swagger에서 사용할 수 있게 도와준다.
그리고 SwaggerModulecreateDocument 함수를 통해 swagger 문서를 생성하게 된다.

참고로 DocumentBuilder 클래스의 함수는 다음과 같다.


DocumentBuilder

import { OpenAPIObject } from './interfaces';
import { ExternalDocumentationObject, ParameterObject, SecurityRequirementObject, SecuritySchemeObject, ServerVariableObject } from './interfaces/open-api-spec.interface';
export declare class DocumentBuilder {
private readonly logger;
private readonly document;
setTitle(title: string): this;
setDescription(description: string): this;
setVersion(version: string): this;
setTermsOfService(termsOfService: string): this;
setContact(name: string, url: string, email: string): this;
setLicense(name: string, url: string): this;
addServer(url: string, description?: string, variables?: Record<string, ServerVariableObject>): this;
setExternalDoc(description: string, url: string): this;
setBasePath(path: string): this;
addTag(name: string, description?: string, externalDocs?: ExternalDocumentationObject): this;
addExtension(extensionKey: string, extensionProperties: any): this;
addSecurity(name: string, options: SecuritySchemeObject): this;
addGlobalParameters(...parameters: ParameterObject[]): this;
addSecurityRequirements(name: string | SecurityRequirementObject, requirements?: string[]): this;
addBearerAuth(options?: SecuritySchemeObject, name?: string): this;
addOAuth2(options?: SecuritySchemeObject, name?: string): this;
addApiKey(options?: SecuritySchemeObject, name?: string): this;
addBasicAuth(options?: SecuritySchemeObject, name?: string): this;
addCookieAuth(cookieName?: string, options?: SecuritySchemeObject, securityName?: string): this;
build(): Omit<OpenAPIObject, 'paths'>;
}

swaggerOptions

const swaggerOptions: SwaggerCustomOptions = {
swaggerOptions: {
persistAuthorization: true,
},
};

SwaggerCustomOptions 는 swagger의 상세 설정을 도와준다.
swaggerOptions: { persistAuthorization: true } 은 BearerToken과 관련된 옵션으로, 새로고침을 해도 swagger에 저장한 BearerToken 값이 날아가지 않게 해준다.

참고로 SwaggerCustomOptions 인터페이스는 아래와 같다.


SwaggerCustomOptions

import { SwaggerUiOptions } from './swagger-ui-options.interface';
import { OpenAPIObject } from './open-api-spec.interface';
export interface SwaggerCustomOptions {
useGlobalPrefix?: boolean;
explorer?: boolean;
swaggerOptions?: SwaggerUiOptions;
customCss?: string;
customCssUrl?: string | string[];
customJs?: string | string[];
customJsStr?: string | string[];
customfavIcon?: string;
customSwaggerUiPath?: string;
swaggerUrl?: string;
customSiteTitle?: string;
validatorUrl?: string;
url?: string;
urls?: Record<'url' | 'name', string>[];
jsonDocumentUrl?: string;
yamlDocumentUrl?: string;
patchDocumentOnRequest?: <TRequest = any, TResponse = any>(req: TRequest, res: TResponse, document: OpenAPIObject) => OpenAPIObject;
}

createDocument & setup

SwaggerModule.setup('swagger', app, swaggerDocument, swaggerCustomOptions);

SwaggerModulesetup 함수는 swagger ui를 볼 수 있는 path를 설정해준다. 위의 코드는 {백엔드 주소}/swagger 로 들어가면 생성된 swagger 문서를 확인할 수 있다.

swagger

NestJS swagger는 기본적으로 Controller 기반으로 api 주소를 맵핑해준다.
하지만 그 외의 request나 response 형태는 데코레이터를 통해 추가로 설정해주어야 한다.
NestJS swagger의 다양한 사용법은 NestJS 공식 문서에서 볼 수 있다.

참고

NestJS 공식 문서 - OpenAPI
[nestjs]swagger를 이용하여 api 문서화