본문 바로가기
JavaScript│Node js

Nestjs 외부 모듈에 정의된 타입 사용하기

by 자유코딩 2020. 1. 9.

이 글을 통해서 얻으실 수 있는 것

npm 외부 모듈에 타입을 정의하고 Nestjs 프로젝트에서 사용하는 방법

 

Typescript 를 사용할 때 좋은 장점은 프론트의 Reactjs 앱과 같은 타입을 공유 할 수 있다는 것입니다.

외부 모듈에 타입을 정의하고 가져다 쓰는 방법을 소개합니다.

 

시행착오를 조금 겪었습니다.

처음엔 interface를 써서 타입을 정의하려고 해봤습니다.

하지만 nest js 에서는 interface 는 @ApiBody에서 type 으로 쓸 수 없습니다.

class나 enum 만 @ApiBody의 type 으로 사용 가능합니다.

@Inject를 해서 사용하는 것도 고려해봤지만

interface 는 @Inject 해서 컨트롤러의 타입으로 쓸 수 없습니다.

 

그래서 결론은 아래 내용처럼 class 를 사용해서 구현했습니다.

 

외부 모듈 쪽 코드부터 보겠습니다.

외부 모듈에는 필수적으로 아래 항목들을 설치해야 합니다.

npm install @nestjs/swagger
npm install @nestjs/common
npm install rxjs

@nestjs/swagger 만 설치하면 될거라고 생각했는데 3가지 모두 설치해야 합니다.

더불어 타입스크립트의 버전이 너무 낮으면 안 되는 이슈가 있었습니다.

3.7.4인 현재 버전의 타입스크립트에서는 잘 됩니다.

 

저는 여기에 class-validator 도 적용해서 코드를 작성해봤습니다.

https://www.npmjs.com/package/class-validator

 

class-validator

Class-based validation with Typescript / ES6 / ES5 using decorators or validation schemas. Supports both node.js and browser

www.npmjs.com

class-validator 는 @ 애너테이션을 사용해서 필드 값을 검증할 때 사용합니다.

import { ApiProperty } from '@nestjs/swagger/dist/decorators/api-property.decorator';
import { IsInt, Min, Length } from 'class-validator';

 

 

export class NestJSType {
  @ApiProperty({
    type: () => Number,
    description: 'width of nest',
    title: 'width'
  })
  @IsInt()
  public width: Number;

  @ApiProperty({
    type: Number,
    description: 'height of nest',
    title: 'height'
  })
  @Min(10)
  public height: Number;

  @ApiProperty({
    type: () => String,
    description: 'name of nest',
    title: 'name'
  })
  @Length(1, 5)
  public name: String;

  constructor(width: Number, height: Number, name: String) {
    this.width = width;
    this.height = height;
    this.name = name;
  }
}

클래스를 정의하고 필드마다 @ApiProperty 라고 적어줍니다.

외부 모듈에 작성하는게 아닌 경우에는 type: <클래스이름> 으로 작성하면 됩니다.

 

하지만 외부 모듈인 경우에는

type: () => 클래스이름

으로 정의해야 합니다.

 

이제 서버쪽 코드에서는 이렇게 작성하면 됩니다.

@ApiTags('user')
@Controller('user')
export class UserController {
    constructor(private readonly userService: UserService) { }

    @Get()
    getUser(): string {
        return 'user';
    }

    /**
     * 주석 달기
     * @param body [ payload ]
     */
    @Post()
    @ApiBody({ type: NestJSType })
    async postUser(@Body() body: NestJSType) {
        const {
            height,
            width,
            name,
        } = body;
        // const nestObj: NestJSType();

        const nestObj = new NestJSType(
            width,
            height,
            name,
        );
        try {
            // tslint:disable-next-line: no-console
            console.log(nestObj);
            const result = await validate(nestObj);
            // tslint:disable-next-line: no-console
            console.log('validate ', result);
            const valid = await validateOrReject(nestObj);
            // tslint:disable-next-line: no-console
            console.log('valid of reject ', valid);
        } catch (errors) {
            throw new HttpException({
                status: HttpStatus.BAD_REQUEST,
                errors,
            }, 400);
        }
        return 'user;';
    }
 }

class-validator 를 사용해서 검증하고 싶다면 validateOrReject 를 사용하면 됩니다.

try-catch 와 함께 사용하면 알아서 Exception 을 발생시키기 때문에 편리합니다.

 

댓글