Nodejs

 

gRPC 함수 실행하기 - 44.OrderMicroservice 작업하기

1. 기존 구조

기존 OrderService는 사용자(User), 상품(Product), 결제(Payment) 서비스를 메시지 기반(ClientProxy)으로 호출했습니다.

// 기존 메시지 기반 호출 (주석 처리된 부분)
// this.userService.send({ cmd: 'get_user_info' }, { userId });
// this.productService.send({ cmd: 'get_products_info' }, { productIds });
// this.paymentService.send({ cmd: 'make_payment' }, { ...payload });

이 방식은 단순 이벤트 전달에는 유용했지만, 서비스 간 응답을 필요로 하는 주문 생성 프로세스에는 한계가 있었습니다.

 

 

 

2. gRPC 기반으로 전환

gRPC 클라이언트 주입

ClientGrpc를 사용해 User, Product, Payment 서비스와 직접 gRPC 통신을 하도록 수정합니다.

constructor(
  @Inject(USER_SERVICE) private readonly userMicroService: ClientGrpc,
  @Inject(PRODUCT_SERVICE) private readonly productMicroService: ClientGrpc,
  @Inject(PAYMENT_SERVICE) private readonly paymentMicroService: ClientGrpc,

  @InjectModel(Order.name)
  private readonly orderModel: Model<Order>,
) {}

서비스 초기화

모듈 초기화 시점에 각 마이크로서비스의 gRPC Client를 가져옵니다.

onModuleInit() {
  this.userService =
    this.userMicroService.getService<UserMicroservice.UserServiceClient>(
      'UserService',
    );
  this.productService =
    this.productMicroService.getService<ProductMicroservice.ProductServiceClient>(
      'ProductService',
    );
  this.paymentService =
    this.paymentMicroService.getService<PaymentMicroservice.PaymentServiceClient>(
      'PaymentService',
    );
}

 

 

 

 

3. 주문 생성 프로세스

단계별 흐름

  1. 사용자 정보 가져오기

    • JWT 토큰을 파싱하고 사용자 정보를 gRPC로 요청합니다.

    const user = await this.getUserFromToken(meta.user.sub);
    
  2. 상품 정보 가져오기

    • 상품 ID 목록을 넘겨서 상세 정보를 gRPC로 요청합니다.

    const products = await this.getProductsByIds(productIds);
    
  3. 총 금액 계산 및 검증

    • 상품들의 가격 합계를 구하고, 프론트에서 전달된 결제 금액과 비교합니다.

    const totalAmount = this.calculateTotalAmount(products);
    this.validatePaymentAmount(totalAmount, payment.amount);
    
  4. 주문 생성하기

    • DB에 주문 데이터를 저장합니다.

    const customer = this.createCustomer(user);
    const order = await this.createNewOrder(customer, products, address, payment);
    
  5. 결제 시도하기

    • PaymentMicroservice의 makePayment RPC를 호출합니다.

    const processPayment = await this.processPayment(
      order._id.toString(),
      payment,
      user.email,
    );
    
  6. 결과 반환

    • 주문 객체를 DB에서 조회하여 반환합니다.

    return this.orderModel.findById(order._id);
    

 

 

 

 

4. 세부 기능 구현

사용자 정보 가져오기

private async getUserFromToken(userId: string) {
  const uResp = await lastValueFrom(this.userService.getUserInfo({ userId }));
  return uResp;
}

상품 정보 가져오기

private async getProductsByIds(productIds: string[]): Promise<Product[]> {
  const resp = await lastValueFrom(
    this.productService.getProductsInfo({ productIds }),
  );
  return resp.products.map((product) => ({
    productId: product.id,
    name: product.name,
    price: product.price,
  }));
}

결제 처리하기

결제는 주문 생성의 핵심 단계입니다. 결제 실패 시 예외를 발생시키고 주문 상태를 업데이트합니다.

async processPayment(orderId: string, payment: PaymentDto, userEmail: string) {
  try {
    const resp = await lastValueFrom(
      this.paymentService.makePayment({ ...payment, userEmail, orderId }),
    );

    const isPaid = resp.paymentStatus === 'Approved';
    const orderStatus = isPaid
      ? OrderStatus.paymentProcessed
      : OrderStatus.paymentFailed;

    if (orderStatus === OrderStatus.paymentFailed) {
      throw new PaymentFailedException(resp);
    }

    await this.orderModel.findByIdAndUpdate(orderId, {
      status: OrderStatus.paymentProcessed,
    });

    return resp;
  } catch (e) {
    if (e instanceof PaymentFailedException) {
      await this.orderModel.findByIdAndUpdate(orderId, {
        status: OrderStatus.paymentFailed,
      });
    }
    throw e;
  }
}

 

 

 

5. 정리

이번 작업으로 OrderMicroservice도 gRPC 기반으로 전환되었습니다. 이로써 전체 서비스 흐름은 다음과 같이 연결됩니다:

  1. UserMicroservice → 사용자 정보 조회

  2. ProductMicroservice → 상품 정보 조회

  3. PaymentMicroservice → 결제 처리

  4. NotificationMicroservice → 결제/배송 알림

전환 효과

  • 서비스 간 통신의 명확한 계약 보장 (proto 기반)

  • 효율적인 데이터 교환 (HTTP/2 기반 gRPC)

  • 전체 주문-결제-알림 플로우의 견고성과 신뢰성 강화

 

 

about author

PHRASE

Level 60  라이트

바리새파 사람들이 와서 속을 떠보려고 "무엇이든지 이유가 닿기만 하면 남편이 아내를 버려도 좋습니까?" 하고 물었다. 그러자 예수께서는 "처음부터 창조주께서 사람을 남자와 여자로 만드셨다"는 것과 또 '그러므로 남자는 부모를 떠나 제 아내와 합하여 한 몸을 이루리라.'고 하신 말씀을 아직 읽어보지 못하였느냐? 따라서 그들은 이제 둘이 아니라 한 몸이다. 그

댓글 ( 0)

댓글 남기기

작성