스파르타 spring 2기 TIL day14

fart man·2025년 12월 23일

장난감 커머스 시스템을 만들면서 배운점

간단한 커머스 시스템을 만드는 과제가 나왔다. 자신 만만하게 뛰어 들었으나 역시나 나의 한게를 뼈저리게 느끼는 기회였다.

에러는 던지자

Go에 익숙하다 보니 에러를 던지기 보다는 돌려주는게 더 낮다는 생각을 했다.
아래 코드를 보자.

  public ProductCustomerException canAddProductToCustomerCart(
      Product product, Customer customer, long orderAmount) {

    // 주문 수량이 0이하일 경우 에러를 돌려주기
    if (orderAmount <= 0) {
      return new ProductCustomerException(
          "주문 수량은 0보다 커야 합니다.",
          product,
          customer,
          ProductCustomerException.Reason.INVALID_ORDER_AMOUNT);
    }

    ProductCustomerException e;

    if ((e = checkProductExist(product, customer)) != null) {
      return e;
    }
    if ((e = checkCustomerExist(product, customer)) != null) {
      return e;
    }
    if ((e = checkProductOutOfStock(product, customer)) != null) {
      return e;
    }
    if ((e = checkOrderExceedsStock(product, customer, orderAmount, true)) != null) {
      return e;
    }

    return null;
  }

난 return하는게 맞다고 생각했다. 실제 행위가 아니고 행위를 할 수 있는지 물어보는 거니까.

하지만 이 코드는 조금만 복잡해져도 문제가 생긴다. 예를 들어 checkProductExistProductCustomerException 이 아닌 다른 Exception을 돌려준다고 생각해 보자.

아니면 그냥 위 check들이 각기 다른 Exception을 돌려준다고 생각해보자. 그럴경우 모든 에러가 ProductCustomerException의 자식이 아닌이상 이렇게 짜야 한다.

  public Exception canAddProductToCustomerCart(
      Product product, Customer customer, long orderAmount) {

    // 주문 수량이 0이하일 경우 에러를 돌려주기
    if (orderAmount <= 0) {
      return new ProductCustomerException(
          "주문 수량은 0보다 커야 합니다.",
          product,
          customer,
          ProductCustomerException.Reason.INVALID_ORDER_AMOUNT);
    }

    Exception e;

    if ((e = checkProductExist(product, customer)) != null) {
      return e;
    }
    if ((e = checkCustomerExist(product, customer)) != null) {
      return e;
    }
    if ((e = checkProductOutOfStock(product, customer)) != null) {
      return e;
    }
    if ((e = checkOrderExceedsStock(product, customer, orderAmount, true)) != null) {
      return e;
    }

    return null;
  }

정말 Go의 문제를 그대로 답습한다. 에러의 타입 정보가 싹다 사라져 버린다. 역시 Java짤때는 Java처럼 짜는게 맞는거 같다.

  public void canAddProductToCustomerCart(UUID productUUID, Customer customer, long orderAmount)
      throws ProductCustomerException {

    // 주문 수량이 0이하일 경우 에러를 돌려주기
    if (orderAmount <= 0) {
      throw new ProductCustomerException(
          "주문 수량은 0보다 커야 합니다.",
          productUUID,
          customer,
          ProductCustomerException.Reason.INVALID_ORDER_AMOUNT);
    }

    checkProductExist(productUUID, customer);
    checkCustomerExist(productUUID, customer);
    checkProductOutOfStock(productUUID, customer);
    checkOrderExceedsStock(productUUID, customer, orderAmount, true);
  }

상품이 삭제되면 어떡하지?

장난감 커머스 시스템을 만들면서 문제가 발생했다. 나는 고객 장바구니 목록을 이 객체로 표현했다.

public record ShoppingCartEntry(UUID productUUID, long orderAmount) {}

나름 썼을 때는 상품자체를 갖고 있는 대신 ID를 쓰는게 맞다고 생가했다. 고객이 갖고 있는 상품이 수정 될 경우 가장 최근의 정보를 가져오라는 뜻이니까.

하지만 API(웃음)를 구현 하면서 문제가 발생했다.

예를 들어 고객이 상품 ID 69420를 구매하고자 했을 때, 상품 ID가 더이상 유효하지 않을경우, 즉 삭제 됬을 경우에는 어떻게 할까?

현재 구조에는 삭제된 상품에 대한 정보를 얻을 방법이 없으므로 고객한테 어떤 상품이 삭제됬는지 알려줄 방법이 없다.

경력자 분(어머니)의 조언

그래서 엄마한테 물어보니까 좋은 답을 주셨다.

우리는 삭제절대 안하고 삭제 됬다고 flag만 줘. 그리고 정말로 삭제 했을 때는 기록을 다 남겨.

이게 맞는 거 같다. 기록을 아예 삭제했을 경우 되찾을 방법이 없으니까.

하지만... 이미 너무 늦었으므로 상품 몇개가 사라졌는지만 알려주기로 했다 ㅠㅠ

0개의 댓글