특정 컨트롤러에서 다중 DTO를 받아 Service 로직에서 맞는 DTO에 따라 동작하게 설계하였는데
## controller
@Post('create')
async create(@Body() body: CreatePaymentPortoneDto | CreatePaymentPaypalDto) {
return await this.paymentService.create(body);
}
내 머리속에 있는 동작대로라면, 맞는 DTO에 body가 매핑되는걸 예상했지만 어림도 없었다.
저 방식대로 설계를 하게되면 서비스 로직에서의 동작 자체는 문제가 없는데, body데이터의 validate가 정상적으로 체크되지 않고 그냥 넘겨버린다….
이유는 body의 타입 선언을 멀티로 하니 타입이 날아가버리는 것 같았다..
그래서 해결방법은, 해당 DTO들의 부모 클래스의 공통 사항을 가지고 체크를 했다.
저장되는 테이블은 동일하지만 결제 타입이 어떤건지 확인하기 위한 컬럼이 있어서 해당 컬럼을 가지고 type cast 를 해주기로 했다.
## controller
@Post('create')
async create(@Body() body: CreatePaymentPortoneDto | CreatePaymentPaypalDto) {
switch (body.payment_type) {
case PaymentType.portone: {
body = Object.setPrototypeOf(body, CreatePaymentPortoneDto.prototype);
await validate(body).then(async (errors) => {
if (errors.length > 0) {
throw new HttpException('Bad Request', HttpStatus.BAD_REQUEST);
} else {
return await this.paymentService.create(body);
}
});
break;
}
case PaymentType.paypal: {
body = Object.setPrototypeOf(body, CreatePaymentPaypalDto.prototype);
await validate(body).then(async (errors) => {
if (errors.length > 0) {
throw new HttpException('Bad Request', HttpStatus.BAD_REQUEST);
} else {
return await this.paymentService.create(body);
}
});
break;
}
default: {
throw new HttpException('Bad Request', HttpStatus.BAD_REQUEST);
}
}
}
위의 방식을 통해 body에 넘어오는 DTO는 명시만 해주고,
하위에서 body의 결제 타입을 체크하고, 해당 타입에 맞게 캐스팅 해주었다.
물론.. 결제 타입에 맞는 DTO와 함수와 endpoint 를 추가해주면 간단히 해결할 수 있는 문제였고, endpoint와 dto를 추가해서 처리하는 방식이 좋은 방향성일지라도, 하나의 endpoint와 같은 서비스 로직 함수로 연결되어야 할 때 해결방안을 찾고싶어서 위와같이 처리해보았다.