본문 바로가기

STUDY/Node.js

NestJS | API 만들기 (3) - Exception, Validation

Built-in HTTP exceptions

Nest가 기본적으로 제공하는 exception들이 있다.(HttpException을 기반으로 하는)

  • BadRequestException
  • UnauthorizedException
  • NotFoundException
  • ForbiddenException
  • NotAcceptableException
  • RequestTimeoutException

이외에도 여러 exception을 제공한다. https://docs.nestjs.com/exception-filters

서비스에서 Exception 처리하기!

가장 기본적인 exception처리를 해보자..
UserService에서 id로 찾은 user가 존재하지 않을 경우 NotFoundExcption을 발생하도록 한다.

Promise<User>가 반환값이기 떄문에, 리포지토리에서 find할 때는 await을 꼭 붙여주도록 하자

@Injectable()
export class UserService {
  constructor(private userRepository: UserRepository) {}

  findAll(): Promise<User[]> {
    return this.userRepository.find();
  }

  async findById(id: string): Promise<User> {
    const findUser = await this.userRepository.findOne(id);
    if (!findUser) {
      throw new NotFoundException(
        `id: ${id} 에 해당하는 유저가 존재하지 않습니다`,
      );
    }

    return findUser;
  }
}

 

이렇게 존재하지 않는 id로 조회를 할 경우, NotFoundException이 발생한다.

유효성 검사

ValidationPipe로 유효성 검사

path에서 값을 가져올 때, 기본 type은 string이다. 이것을 number로만 입력하도록 제한할 필요가 있다.


우선, ValidationPipe설정에 transform을 추가한다.
main.ts에서 transfrom: true로 설정하면, string으로 넘어오는 값을 알아서 number로 변환해준다.

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(
    new ValidationPipe({
      transform: true,
      whitelist: true,
      forbidNonWhitelisted: true,
    }),
  );
  await app.listen(3000);
}
bootstrap();

 

그런데 이렇게만 하면 문자열을 입력했을 때 데이터베이스에서 조회하는 과정에서 NaN에러가 발생한다.
그래서 ParseIntPipe@Param데코레이터에 추가한다.

import {
  Controller,
  Get,
  Param,
  ParseIntPipe
} from '@nestjs/common';
import { ResponseUserDto } from './dto/response.dto';
import { UserService } from './service/user.service';

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

  @Get()
  async getUsers(): Promise<ResponseUserDto[]> {
    return await this.userService.findAll();
  }

  @Get('/:id')
  async getUser(
    @Param('id', new ParseIntPipe()) userId: number,
  ): Promise<ResponseUserDto> {
    return await this.userService.findById(userId);
  }
}