nestjs_pipe로 변환과 유효성 검사 진행하기
nest.js에서 파이프를 왜 사용하는가?
파이프의 사용 목적
- transformation(변환) : 입력 받은 데이터의 형식 변환하기
- validation(유효성 검사) : 원하는 데이터 여부 평가
즉, 받은 데이터가 내가 원하는 형식의 데이터인가 검사하거나 또 이를 변형하고 싶을 때 파이프를 사용한다. 이 두 기능은 경우에 따라 동시에 수행할 수도 있다. 파이프는 @Injectable() 데코레이터로 적용할 수 있다.
pipe pattern
pipe는 일종의 패턴이라고 보면 된다. 주입받은 데이터를 각 개별 단계에서 개별 컴포넌트로 쪼개는 작업을 파이프를 통과하면서 수행한다. 각 단계별 컴포넌트을 주고 받는 과정들을 통해서 우리가 원했던 표준화된 형식의 데이터를 얻을 수 있게 된다. 마치 사람이 음식을 먹은 뒤 음식물이 여러 소화기관을 거치면서 영양분으로 바뀌는 과정과 유사하다.
파라미터 받아오기
본격적으로 들어가기 앞서, 파라미터로 데이터를 받아오는 방법을 복습해보자.
...
@Get(':id')
getOneCat(@Param() param) {
console.log(param);
return 'one cat';
}
...
// { id: '1' }
@Param() 데코레이터의 인자로 아무것도 넣지 않을 경우 기본적으로 id 프로퍼티를 가진 객체가 반환된다.
...
@Get(':id')
getOneCat(@Param('id') param) {
console.log(param);
return 'one cat';
}
...
// 1
반면, @Param 데코레이터에 id를 명시해줄 경우, id 프로퍼티의 '값'만 리턴된다.
파이프로 파라미터 데이터를 문자열에서 정수로 변환(transform)하기
...
@Get(':id')
getOneCat(@Param('id', ParseIntPipe) param) {
console.log(typeof param);
return 'one cat';
}
...
// number
ParseIntPipe를 적용해주니 문자열에서 정수로 자동변환 되었다.
Pipe 이점은 또 하나 더 있다.
변환을 위한 파이프가 일종의 유효성 검사(validation) 기능까지 수행한다. 위에서 파라미터는 숫자가 올 것임을 기대하고 있기 때문에 숫자가 아닌 알파벳이 문자열로 들어올 경우 에러를 발생시킨다.
http://localhost:8000/cats/aaa 라는 숫자 대신 aaa 알파벳을 대입해보면..
Validation에 실패했다는 에러를 자동으로 반환해준다.
복수 파이프 패턴 적용해보기
파이프는 여러개의 처리를 함께 이어 붙여야 파이프 답다고 할 수 있으니, ParseIntPipe 뿐만 아니라 PositiveIntPipe라는 양수를 확인하는 커스텀 파이프도 이어 붙여주자.
...
@Controller('cats')
@UseFilters(HttpExceptionFilter)
export class CatsController {
constructor(private readonly catsService: CatsService) {}
@Get()
getAllCat() {
// Node.js : throw new Error
throw new HttpException('api is not available 😭', 401);
return 'all cat';
}
@Get(':id')
getOneCat(@Param('id', ParseIntPipe, PositiveIntPipe) param) {
console.log(typeof param);
return 'one cat';
}
...
// src/common/pipes/positiveInt.pipe.ts
import { Injectable, PipeTransform, HttpException } from '@nestjs/common';
import { HttpExceptionFilter } from 'src/http-exception.filter';
@Injectable()
export class PositiveIntPipe implements PipeTransform {
// pipe 패턴에서 여러 단계의 컴포턴트들 중 하나라고 보면 된다
transform(value: number) {
// 음수일 경우 에러 발생
if (value < 0) {
throw new HttpException('value > 0', 400);
}
return value;
}
}