이번 포스트에서는 다음의 케이스들을 다뤄보도록 하겠습니다.
1) ERROR_ORDER인 경우 재주문 요청
1)의 경우 사용자의 UI화면이 존재한다면 주문이 ERROR가 됐으므로 사용자에게 이에 관한 메시지를 보낼 것입니다. 그러면 사용자는 주문 취소 혹은 수량 변경 후 재주문을 해야겠죠. 여기서 2가지 케이스가 생기게 되네요. 이 케이스들을 다음과 같이 나누도록 하겠습니다.
1-1) 주문 취소의 경우 /orders/:orderId/cancel로 요청하기
1-2) 재주문의 경우 /orders/:orderId/reorder로 요청하기, 이 경우에는 기존의 reOrder메서드를 수정하도록 하겠습니다.
1-1)의 경우 기존에 만들어 두었던 cancelOrder로 대체할 수 있고, 이번 포스트에서는 1-2)의 경우만 다루도록 하겠습니다.
1-2) 재주문의 경우 /orders/:orderId/reorder로 요청하기
import { IsNotEmpty, IsNumber, IsString } from "class-validator";
export class RequestUpdate {
@IsNumber()
@IsNotEmpty()
readonly qty: number;
}
재주문할 경우 수량 수정을 위한 변수만 갖게 하도록 하겠습니다.
import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common';
import { EventPattern } from '@nestjs/microservices';
import { OrderDto } from 'src/dto/order.dto';
import { RequestCreate } from 'src/vo/request.create';
import { RequestUpdate } from 'src/vo/request.update';
import { ResponseOrder } from 'src/vo/response.order';
import { OrderService } from './order.service';
@Controller('orders')
export class OrderController {
constructor(private readonly orderService: OrderService,) {}
...
@Post(':orderId/reorder')
public async reOrder(
@Param('orderId') orderId: string,
@Body() requestUpdate: RequestUpdate
) {
const orderDto = new OrderDto();
orderDto.orderId = orderId;
orderDto.qty = requestUpdate.qty;
return await this.orderService.reOrder(orderDto);
}
...
컨트롤러의 reOrder메서드를 다음과 같이 orderDto에 요청받은 정보값들을 담아 서비스단으로 넘기도록 하겠습니다.
import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { InjectRepository } from '@nestjs/typeorm';
import { OrderDto } from 'src/dto/order.dto';
import { OrderEntity } from 'src/entity/order.entity';
import { ResponseOrder } from 'src/vo/response.order';
import { Repository } from 'typeorm';
import { v4 as uuid } from 'uuid';
@Injectable()
export class OrderService {
constructor(
@InjectRepository(OrderEntity) private orderRepository: Repository<OrderEntity>,
@Inject('order-service') private readonly client: ClientProxy
) {}
...
public async reOrder(orderDto: OrderDto): Promise<ResponseOrder> {
try {
const orderEntity = await this.orderRepository.findOne({ where: { orderId: orderDto.orderId }});
const responseOrder = new ResponseOrder();
orderEntity.qty = orderDto.qty;
orderEntity.totalPrice = (Number(orderEntity.qty) * Number(orderEntity.unitPrice));
orderEntity.status = 'RE_ORDER';
this.client.emit("RE_ORDER", orderEntity);
await this.orderRepository.save(orderEntity);
responseOrder.orderId = orderEntity.orderId;
responseOrder.status = orderEntity.status;
return responseOrder;
} catch(err) {
throw new HttpException(err, HttpStatus.BAD_REQUEST);
}
}
...
}
그러면 서비스에서 비즈니스 로직이 다음과 같이 바뀌게 됩니다. 수량에 대한 변화가 생겼으니 orderEntity.qty의 수량을 변화시켜야 하고, orderEntity.totalPrice 또한 변화가 생겨야겠죠. 이렇게 reOrder에 관한 코드를 변경시키도록 하겠습니다.
이제 유저 정보를 확인하면 order에 관한 정보를 불러 올 수 있게 코드를 작성해보도록 하겠습니다. user-service.vo 디렉토리에 ResponseOrder라는 파일을 만들도록 하겠습니다.
import { IsBoolean, IsNotEmpty, IsNumber, IsString } from "class-validator";
export class ResponseOrder {
@IsString()
orderId: string;
@IsString()
productId: string;
@IsString()
productName: string;
@IsNumber()
qty: number;
@IsNumber()
unitPrice: number;
@IsNumber()
totalPrice: number;
@IsString()
userId: string;
@IsBoolean()
status: string;
}
import { IsNumber, IsString } from 'class-validator';
import { ResponseOrder } from 'src/vo/response.order';
export class UserDto {
...
orders: ResponseOrder[];
}
import { ResponseOrder } from "./response.order";
export class ResponseUser {
email: string;
nickname: string;
encryptedPwd: string;
userId: string;
orders: ResponseOrder[];
}
그리고 ResponseUser에 ResponseOrder Array를 추가하겠습니다. 이 vo들은 user정보를 반환할 때 필요한 vo클래스입니다.
npm install --save nest-feign nest-consul-loadbalance nest-consul consul
모든 코드가 대략적으로 완성된 것 같습니다. 그러면 시나리오를 다음과 같이 몇 가지를 구성해보고 테스트를 진행하도록 하겠습니다.
1) 회원가입 후 product-001의 제품을 10개 주문하기
2) product-001의 제품을 취소하기
3) 취소한 product-001의 제품을 20개로 바꾸어 재주문
4) product-002의 제품을 300개 주문하기
5) ERROR_ORDER상태 값인 product-002의 주문을 10개로 재주문
본 시나리오를 바탕으로 테스트를 진행해보도록 하겠습니다.
1) 회원가입 후 product-001의 제품을 10개 주문하기
2) product-001의 제품을 취소하기
3) 취소한 product-001의 제품을 20개로 바꾸어 재주문
4) product-002의 제품을 300개 주문하기
5) ERROR_ORDER상태 값인 product-002의 주문을 10개로 재주문
모든 시나리오들이 정상적으로 작동할 수 있는 모습을 볼 수 있습니다. 이로써 실제 서비스들에 대한 모든 코드를 구현해 봤습니다.
다른 시리즈인 Spring Cloud기반의 Microservice는 API Gateway Service를 이용해 하나의 포트로 모든 요청을 받고 각 서비스로 요청을 전달하고, 혹은 Spring Security를 이용해 인터셉터도 구현할 수 있습니다.
아직까지 NestJS가 미숙해서 위의 기능들을 구현할 수 있지만 제가 미처 구현 못한 것일수도 있으므로 위의 기능들과 관련해서 조금 더 공부를 하고 난 뒤 추가적으로 포스트를 한번 작성해보도록 하겠습니다. 감사합니다.