인프런 커뮤니티 질문&답변

후니훈님의 프로필 이미지
후니훈

작성한 질문수

탄탄한 백엔드 NestJS, 기초부터 심화까지

exception filter에 잡히질 않습니다

작성

·

270

0

import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
} from '@nestjs/common';
import { Request, Response } from 'express';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();
    const error = exception.getResponse() as
      | string
      | { error: string; statusCode: number; message: string | string[] };

    if (typeof error === 'string') {
      response.status(status).json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
        message: error,
      });
    } else {
      response.status(status).json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
        message: error,
      });
    }
  }
}

안녕하세요 ! 위와 같이 필터 작성이후

main.ts 에서

app.useGlobalFilter(new HttpExceptionFilter());

를 통해 예외가 잘 잡히는것을 확인을 했었습니다.

왜인지는 모르겠으나 cat의 모델 내부 필드중에 imgUrl 부분을 null 을 허용해주기 위해

@IsOptional() 을 붙여주고난 뒤에

중복 회원가입을 진행하려 할 경우 예외에 잡히게끔 하려 HttpException 을 발생 시키게끔 했습니다.

async signUp(body: CatRequestDTO): Promise<Cat> {
    const email = body.email;
    const checkExist = await this.catRepository.findOne({ where: { email } });

    if (!checkExist) {
      const createdCat = this.catRepository.create(body);
      this.catRepository.save(createdCat);
      return createdCat;
    } else {
      throw new HttpException(
        'Already exist Email in DB',
        HttpStatus.BAD_REQUEST,
      );
    }
  }

콘솔창에 에러 메세지와 함께 출력되는것은 확인되나

Filter에서 exception @Catch 로 묶어준것에 잡히지를 않습니다.

 

도통 이유를 못찾겠어서 app.useGlobalFilter(...) 를

catController 쪽에 @UseFilters(new HttpExceptionFilter()) 로도 바꿔보고

메서드에다가 직접적으로도 붙여보았으나 계속 똑같은 현상을 보이는데

왜 인지를 못잡겠습니다. 조언을 좀 주시면 감사하겠습니다.

답변 1

1

안녕하세요, 인프런 AI 인턴이에요.

exception filter를 사용하면 예외를 잡을 수 있지만, imgUrl 필드에서 null을 허용하기 위해 @IsOptional()을 사용한 후 중복 회원 가입 예외가 잡히지 않는다는 문제가 있으시군요.

이 문제는 @IsOptional() 데코레이터가 예외 필터링되지 않아 발생하는 것으로 보입니다. @IsOptional()은 데이터 유효성 검사를 수행하는 class-validator의 기능인데, 이 기능이 예외 필터링과 충돌하는 것 같아요.

해결 방법으로는 imgUrl 필드에 @IsOptional() 대신 데이터 유효성 검사를 직접 수행하는 코드를 추가하는 것입니다. try-catch 문을 사용하여 imgUrl이 null이면 예외를 발생시키고, 이 예외를 HttpException으로 변환하여 필터에 잡히도록 처리하면 될 것 같아요. 아래는 예시 코드입니다.

class YourModel {
  // ...

  @ApiPropertyOptional()
  @IsString()
  imgUrl: string | null;

  // ...
}

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();
    const error = exception.getResponse() as
      | string
      | { error: string; statusCode: number; message: string | string[] };

    if (typeof error === 'string') {
      response.status(status).json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
        message: error,
      });
    } else {
      response.status(status).json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
        message: error,
      });
    }
  }
}

// ...

try {
  // imgUrl이 null인 경우 예외 발생
  if (yourModel.imgUrl === null) {
    throw new Error("imgUrl is required");
  }

  // ...

} catch (error) {
  // 에러를 HttpException으로 변환하여 필터링되도록 처리
  throw new HttpException("Invalid input data", HttpStatus.BAD_REQUEST);
}

이렇게 하면 imgUrl 필드가 null인 경우 예외가 발생하고, HttpExceptionFilter에서 이 예외를 잡아 처리할 수 있을 겁니다. 참고로 위 코드는 예시이므로 실제 상황에 맞게 적절히 수정해야 합니다.

혹시 다른 문제가 발생하거나 추가적인 도움이 필요하시면 언제든지 물어보세요. 도움이 됐길 바랄게요.

후니훈님의 프로필 이미지
후니훈
질문자

너무 감사합니다. 잘 해결되었어요!!

후니훈님의 프로필 이미지
후니훈

작성한 질문수

질문하기