제목은 거창해 보이지만 사실 단순 ValidationPipe의 option을 재정의할 수 있는 CustomValidationPipe이다.
사이드 프로젝트에서 파일 업로드 API를 구현할 때의 이야기이다.
File Upload API를 구현하면서 생긴 일 (feat. TSID, BigInt)
해당 글과 같은 시점이다.
우리 프로젝트에서 ValidationError의 경우 Global 레벨로 적용한 ValidationPipe의 exceptionFactory를 이용해서 custom한 error를 던지고 있었다.
errors: validationErrors.flatMap((validationError) => {
return {
property: validationError.property,
value: validationError.value,
reason: Object.values(validationError.constraints)[0] || '',
};
}),
// 대충 이런 식.
에러가 발생한 value까지 그대로 출력하고 있었는데, 여기서 예상치 못한 변수가 발생한다.

에러의 일부이다.
스크롤이 끝도 없다.
swagger를 통해 request를 보냈을 때 swagger가 멈춰 버리길래 '뭐지..?' 했는데 이런 문제가 있을 줄은 꿈에도 몰랐다.
그리고 단순히
'음 그러면 해당 요청에선 Validation option을 재정의 하면 되겠다!!'
라고 생각했는데 해당 router 레벨에서 Validation option을 재정의해도 적용이 되지 않았다..
참조 링크1
그리고 나는 바로 구글링을 시작했다.
위의 참조 링크1과 같은 이슈에서 나온 해결 방안인데, 흐름은 이렇다.
import { REWRITE_VALIDATION_OPTIONS } from './constants'; import { ValidatorOptions } from '@nestjs/common/interfaces/external/validator-options.interface'; import { SetMetadata } from '@nestjs/common'; export function RewriteValidationOptions(options: ValidatorOptions) { return SetMetadata(REWRITE_VALIDATION_OPTIONS, options); }
// extends global pipe
import { ValidationPipe, ArgumentMetadata, Injectable } from '@nestjs/common';
import { REWRITE_VALIDATION_OPTIONS } from '../decorators/constants';
@Injectable()
export class MyValidationPipe extends ValidationPipe {
async transform(value: any, metadata: ArgumentMetadata) {
const options = Reflect.getMetadata(REWRITE_VALIDATION_OPTIONS, metadata.metatype);
let originOptions;
if (options) {
originOptions = Object.assign({}, this.validatorOptions);
this.validatorOptions = Object.assign(this.validatorOptions, options);
}
try {
const result = super.transform(value, metadata);
if (originOptions) {
this.validatorOptions = originOptions;
}
return result;
} catch (error) {
throw error;
}
}
}
아무튼 CustomValidationPipe 및 데코레이터를 새로 만들어서 file upload 시에 사용되는 Dto에서는 { validationError: { value: false } }로 option을 재정의 해주었고 클라이언트 측에서 response를 받다가 터져버리는 일을 방지할 수 있게 되었다.