[ NestJS ] 파이프 디자인 패턴에 대해서 알아보자
🌈 프로그래밍/Nest JS

[ NestJS ] 파이프 디자인 패턴에 대해서 알아보자

반응형

 

이번 포스팅에서는 지난번에 간략하게 파이프 패턴에 대해서 알아보았었는데

좀 더 자세하게 알아보려고 한다.

우선 NestJS에서 정의하고 있는 파이프에 대해한 내용은 다음과 같다.

파이프의 정의?

 

NestJS에서의 파이프는 클라이언트 요청에서 들어오는 데이터를 유효성 검사 및 변환을 수행하여
서버가 원하는 데이터를 얻을 수 있도록 도와주는 역할을 합니다.

그렇다면 여기서 드는 의문점이 있다.

바로 파이프라는 이름에 대한 의문점이다.

아니, 클라이언트의 요청에 대한 데이터를 유효성 검사와 변환을 하기 위한 것인데..

Data Transform 또는 Data Validation이라고 이름을 짓지 않은 이유가 뭘까??

 

우선, 왜 이름이 파이프인지 생각하기 이전에 상상을 해보자.

클라이언트의 요청이 데이터와 함께 들어왔고 그 요청에 대한 로직이 있다고 해보자.

그 로직에서는 데이터에 대한 유효성 검증도 하고, 가공도 하고 변환도 한다고 한다.

이 모든 과정을 수행 후에 정말 우리가 원하는 비즈니스 로직이 수행된다.

바로 아래의 그림처럼 말이다.

위의 모놀리식 모듈과 아래의 모놀리식 모듈은 각각 독립되어 있으며 Task A와 Task B는 각 모듈에 있어서 결과적으로 같은 일(데이터 처리 또는 가공 또는 변환)을 하는 부분이 중복되어진다.

즉, 재사용성과 확장성을 고려하지 않은 모습이다.

따라서 이러한 문제를 해결하고 코드의 재사용 가능성을 높이는 설루션이 필요한데 그 솔루션이 바로 파이프 & 필터 디자인 패턴이다.

 

아래의 그림을 보자.

아까의 모놀리식 모듈과는 다른 모습이다.

개별적인 파이프를 만들어서 변환 및 유효성 검증을 하는 파이프로 나누고 데이터를 순차적으로 통과시킨다.

통과된 데이터는 그다음 Task를 수행하게 되고 계속해서 변환 및 검증이 이루어진다.

이렇게 만든다면 각각의 Task(Pipe)에 대한 순서 변환과 특정 Task에 대한 수정 및 추가가 용이하고,

다른 모듈에서도 쉽에 가져다가 쓸 수 있는 장점이 있다.

 

아래에는 NestJS에서의 직접 커스터마이징 한 파이프 패턴에 대해서 간략하게 코드와 함께 설명을 해보려고 한다.

프로젝트 폴더에서 common/pipes 폴더를 생성하고

positiveInt.pipe.ts

// 새로운 커스텀 파이프를 만들어보자
// positiveInt 파이프는 ParseInt 파이프를 거친 후 정수가 양수인지 확인하는 파이프
import { ArgumentMetadata, HttpException, Injectable, PipeTransform } from "@nestjs/common";

@Injectable()
export class PositiveIntPipe implements PipeTransform {
    // transform 함수의 결과값이 파이프의 결과값 (Task1, Task2 ...)
    transform(value: number) {
        // console.log("PositiveIntPipe: " + value);
        if (value < 0) {
            // Int로 변환 후 값이 음수이면 Exception을 던짐
            throw new HttpException('value < 0', 400);
        }
        return value;
    }
}

위와 같이 작성한다. 이 파이프는 number를 받아와 그 number가 양의 정수이면 통과를 시켜주고,

0보다 작으면 즉, 음수이거나 0이면 예외처리를 하여 값이 0보다 작다는 예외를 발생시켜준다.

그다음 특정 고양이의 정보를 가져오기 위한 Get 메서드를 사용한 요청을 하나 만들어준다.

 

cats.controller.ts

@Get(':id')
getOneCat(@Param('id', ParseIntPipe, PositiveIntPipe) param: number) {
	return 'get one cat api'
}

위의 요청을 하기 위해서는 localhost:8000/cats/:id로 요청을 보내면 된다.

인자로 Param안에 순차적으로 Task A, Task B와 같은 형태로 Pipe를 연결할 수 있다.

위의 예시에서는 가장 먼저 수행되는 Task는 Nest에서 제공해주는 ParseIntPipe로 받아온 인자를 String 형태에서 Int 형으로 바꿔주는 역할을 한 뒤, 우리가 위에서 만든 PositiveIntPipe에게 결과를 전달해주도록 하는 방법이다.

다음으로는 테스트를 진행해보자.

 

커스텀 파이프 테스트하기

아래와 같이 요청을 보내보도록 하자.

요청을 보내고 콘솔을 확인해보면

요청으로 보낸 데이터 123이 ParseIntPipe를 거쳐서 커스텀 파이프인 PositiveIntPipe에서  값이 전달되어진 모습이다.

다음으로는 예외가 정상적으로 동작하는지 확인해보자.

아래처럼 요청을 보내면

서버로부터 응답이 400으로 떨어지고 예외가 발생한 모습이다. 예외 메시지까지 우리가 작성한 것처럼 보이고,

콘솔도 마찬가지로 값이 잘 전달되어서 왔지만 -123이라는 값은 0보다 작으므로 예외가 발생하였다.

이번 포스팅에서는 파이프 & 필터에 대한 자세한 내용을 다뤄보았고, 커스텀한 파이프를 사용해보는 예제도 함께 살펴보았다.

이상!

 

 

파이프 & 필터 패턴에 대한 MS 공식 문서

https://docs.microsoft.com/en-us/azure/architecture/patterns/pipes-and-filters

 

Pipes and Filters pattern - Azure Architecture Center

Break down a task that performs complex processing into a series of separate elements that can be reused.

docs.microsoft.com

 

 

반응형