[Nest.js]07. Swagger

김지엽·2023년 10월 12일
0
post-custom-banner

1. 개요

Swagger 내 코드의 API를 자동으로 문서화 해주는 도구이며 API 테스트도 가능하다. 이전 포스팅까지 모듈을 여러개 구성했기에 API를 문서화 하고, 테스트까지 진행해 볼려고 한다.

2. Swagger 사용하기

- 설치

$ npm install --save @nestjs/swagger

nest 버전 9 밑으로는 추가적으로 fastify 등이 필요로 한다.

- Swagger 세팅

[main.ts]
... 
const config = new DocumentBuilder()
    .setTitle("Webtoon Recommend")
    .setDescription("Webtoon Recommend API description")
    .setVersion("1.0")
    .addTag("webtoon")
    .build();
const document = SwaggerModule.createDocument(app, config);
// 첫번째 인자에 url 뒤에 붙일 path를 입력
SwaggerModule.setup("api", app, document);

...

위와 같이 Swagger를 세팅 해주면 http://localhost:5000/api에 접속했을때 다음과 화면이 보인다.

- ApiProperty

swagger에 처음 접속하면 다음과 같이 dto등의 프로퍼티가 모두 나타나지 않아 있다.

이렇게 되는 이유는 아직 우리가 dto에 ApiProperty 설정을 해주지 않아서 인데 다음과 같이 dto를 수정한다.

[webtoon.dto.ts]
import { IsNotEmpty, IsNumber, IsOptional, IsString } from "class-validator";
import { IsNotEmptyOnAllProperties } from "./dtoFunction";
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";

@IsNotEmptyOnAllProperties()
export class InsertWebtoonDto {
    
    @IsString()
    @ApiProperty({ description: '웹툰 아이디' })
    webtoonId: string;

    @IsString()
    @ApiProperty({ description: '제목' })
    title: string;

    @IsString()
    @ApiProperty({ description: '작가' })
    author: string;
    
    @IsNumber()
    @ApiProperty({ description: '전체 화수' })
    episodeLength: number;

    @IsString()
    @ApiProperty({ description: '썸네일' })
    thumbnail: string;

    @IsString()
    @ApiProperty({ description: '서비스' })
    service: string;

    @IsString()
    @ApiProperty({ description: '업데이트 날짜' })
    updateDay: string;

    @IsString()
    @ApiProperty({ description: '분류' })
    category: string;

    @IsString()
    @ApiProperty({ description: '장르키워드' })
    genres: string;

    @IsNumber()
    @ApiProperty({ description: '장르키워드 개수' })
    genreCount: number;

    @IsString()
    @ApiProperty({ description: '줄거리' })
    description: string;

    @IsNumber()
    @ApiProperty({ description: '팬 수' })
    fanCount: number;

}

export class UpdateWebtoonDto {
    @IsNotEmpty()
    @IsString()
    @ApiProperty({ description: '웹툰 아이디' })
    webtoonId: string;

    @IsOptional()
    @IsString()
    @ApiPropertyOptional({ description: '제목' })
    title?: string;

    @IsOptional()
    @IsString()
    @ApiPropertyOptional({ description: '작가' })
    author?: string;
    
    @IsOptional()
    @IsNumber()
    @ApiPropertyOptional({ description: '전체 화수' })
    episodeLength?: number;

    @IsOptional()
    @IsString()
    @ApiPropertyOptional({ description: '썸네일' })
    thumbnail?: string;

    @IsOptional()
    @IsString()
    @ApiPropertyOptional({ description: '서비스' })
    service?: string;

    @IsOptional()
    @IsString()
    @ApiPropertyOptional({ description: '업데이트 날짜' })
    updateDay?: string;

    @IsOptional()
    @IsString()
    @ApiPropertyOptional({ description: '분류' })
    category?: string;

    @IsOptional()
    @IsString()
    @ApiPropertyOptional({ description: '장르키워드' })
    genres?: string;

    @IsOptional()
    @IsNumber()
    @ApiPropertyOptional({ description: '장르키워드 개수' })
    genreCount?: number;

    @IsOptional()
    @IsString()
    @ApiPropertyOptional({ description: '줄거리' })
    description?: string;

    @IsOptional()
    @IsNumber()
    @ApiPropertyOptional({ description: '팬 수' })
    fanCount?: number;
}

이렇게 dto에 필수 인자는 @ApiProperty()을, 선택적 인자는 @ApiPropertyOptional()을 달아주면 swagger가 이 데이터를 가져온다.

그리고 api 페이지를 다시 새로고침하면 다음과 같이 바뀐다.

이외에도 ApiResponse, ApiBody 등이 있지만 당장은 사용할 이유가 없어 보여서 넣지 않았다.

문제점

- Swagger는 DTO 상속을 인식 못함

swagger를 적용하기 전까지는 dto에 이런 형태로 코드를 작성했다.

@IsNotEmptyOnAllProperties()
export class InsertWebtoonDto {
    
    @IsString()
    webtoonId: string;

    @IsString()
    title: string;

    @IsString()
    author: string;
    
    ...

}

export class UpdateWebtoonDto extends PartialType(InsertWebtoonDto) {
    @IsNotEmpty()
    @IsString()
    webtoonId: string;
}

하지만 이렇게 DTO에서 상속을 이용하면 Swagger는 UpdateWebtoonDto의 webtoonId만을 식별하고 InsertWebtoonDto로부터 상속받은 프로퍼티는 식별하지 못한다.

이런 문제를 해결하기 위해 방법을 찾아봤지만 결국 가장 쉽게하는 것은 상속을 이용하지 않는 것이었다. 상속을 넣지 않으니 문제는 바로 해결되었다.

글을 마치며

코드 리팩토링 전에는 나중에 readme 등에 api문서를 작성할 것을 생각하니 너무 귀찮고 힘들어 보였는데 swagger를 알게 된 것은 엄청난 혁신이었다.

swagger는 내 코드만을 작성하면 api문서를 작성해주기 떄문에 개인 프로젝트는 물론 나중에 팀 프로젝트에서도 큰 역할을 할 것으로 보인다.

앞으로도 swagger와 같은 내가 모르는 아주 편한 도구가 있다면 바로 바로 적용해봐야겠다.

참고

https://docs.nestjs.com/openapi/introduction - nest 공식 문서
https://develop-const.tistory.com/15 - swagger 사용 블로그

profile
욕심 많은 개발자
post-custom-banner

0개의 댓글