E-commerce Application(Nest js Microservice) - 10. order-service와 catalog-service 통신(3)
#1 에러 케이스
이번 포스트에서는 다음의 케이스들을 다뤄보도록 하겠습니다.
1) ERROR_ORDER인 경우 재주문 요청
1)의 경우 사용자의 UI화면이 존재한다면 주문이 ERROR가 됐으므로 사용자에게 이에 관한 메시지를 보낼 것입니다. 그러면 사용자는 주문 취소 혹은 수량 변경 후 재주문을 해야겠죠. 여기서 2가지 케이스가 생기게 되네요. 이 케이스들을 다음과 같이 나누도록 하겠습니다.
1-1) 주문 취소의 경우 /orders/:orderId/cancel로 요청하기
1-2) 재주문의 경우 /orders/:orderId/reorder로 요청하기, 이 경우에는 기존의 reOrder메서드를 수정하도록 하겠습니다.
#2 1) 케이스
1-1)의 경우 기존에 만들어 두었던 cancelOrder로 대체할 수 있고, 이번 포스트에서는 1-2)의 경우만 다루도록 하겠습니다.
1-2) 재주문의 경우 /orders/:orderId/reorder로 요청하기
- request.update.ts
import { IsNotEmpty, IsNumber, IsString } from "class-validator";
export class RequestUpdate {
    @IsNumber()
    @IsNotEmpty()
    readonly qty: number;
}재주문할 경우 수량 수정을 위한 변수만 갖게 하도록 하겠습니다.
- order.controller.ts
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에 요청받은 정보값들을 담아 서비스단으로 넘기도록 하겠습니다.
- order.service.ts
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에 관한 코드를 변경시키도록 하겠습니다.
#3 auth-service(추후 업로드)
이제 유저 정보를 확인하면 order에 관한 정보를 불러 올 수 있게 코드를 작성해보도록 하겠습니다. user-service.vo 디렉토리에 ResponseOrder라는 파일을 만들도록 하겠습니다.
- response.order.ts
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;
}- user.dto.ts
import { IsNumber, IsString } from 'class-validator';
import { ResponseOrder } from 'src/vo/response.order';
export class UserDto {
    ...
    orders: ResponseOrder[];
}- response.user.ts
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- nestcloud/feign 연동을 지속적으로 해봤는데 잘 되지 않아 문서를 좀 더 찾아본 후 업로드하도록 하겠습니다.
#4 test
모든 코드가 대략적으로 완성된 것 같습니다. 그러면 시나리오를 다음과 같이 몇 가지를 구성해보고 테스트를 진행하도록 하겠습니다.
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가 미숙해서 위의 기능들을 구현할 수 있지만 제가 미처 구현 못한 것일수도 있으므로 위의 기능들과 관련해서 조금 더 공부를 하고 난 뒤 추가적으로 포스트를 한번 작성해보도록 하겠습니다. 감사합니다.
Author And Source
이 문제에 관하여(E-commerce Application(Nest js Microservice) - 10. order-service와 catalog-service 통신(3)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@biuea/E-commerce-ApplicationNest-js-Microservice-10.-order-service와-catalog-service-통신3저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)