@@ -0,0 +1,96 @@
+package christmas.domain.order;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+
+import christmas.domain.menu.Category;
+import christmas.exception.OrderException;
+import christmas.exception.message.OrderExceptionMessage;
+
+import static christmas.constant.OrderConstant.MAX_TOTAL_ORDER_COUNT;
+
+public record Bill(int totalPrice, EnumMap<Category, List<OrderInfo>> orderDetail) {
+    public static Bill of(List<RequestOrder> requestOrderList) {
+        EnumMap<Category, List<OrderInfo>> orderMenuBoard = confirmOrders(requestOrderList);
+
+        validate(orderMenuBoard);
+
+        int totalPrice = calculateTotalPrice(orderMenuBoard);
+        return new Bill(totalPrice, orderMenuBoard);
+    }
+
+    private static EnumMap<Category, List<OrderInfo>> confirmOrders(List<RequestOrder> requestOrderList) {
+        EnumMap<Category, List<OrderInfo>> orderMenuBoard = initOrderMenuBoard();
+
+        for (RequestOrder requestOrder : requestOrderList) {
+            confirmOrder(requestOrder, orderMenuBoard);
+        }
+        return orderMenuBoard;
+    }
+
+    private static void confirmOrder(RequestOrder requestOrder, EnumMap<Category, List<OrderInfo>> orderMenuBoard) {
+        String orderName = requestOrder.orderName();
+        int orderAmount = requestOrder.amount();
+
+        OrderResult orderResult = OrderResult.of(orderName, orderAmount);
+        orderMenuBoard.get(orderResult.category()).add(orderResult.orderInfo());
+    }
+
+
+    private static EnumMap<Category, List<OrderInfo>> initOrderMenuBoard() {
+        EnumMap<Category, List<OrderInfo>> orderMenuBoard = new EnumMap<>(Category.class);
+
+        for (Category category : Category.values()) {
+            orderMenuBoard.put(category, new ArrayList<>());
+        }
+        return orderMenuBoard;
+    }
+
+    private static void validate(EnumMap<Category, List<OrderInfo>> orderMenuBoard) {
+        int totalAmount = countTotalOrderMenu(orderMenuBoard);
+        validateTotalAmountInRange(totalAmount);
+        validateMenuIsOnlyDrink(orderMenuBoard.get(Category.DRINK), totalAmount);
+    }
+
+    private static void validateTotalAmountInRange(int totalAmount) {
+        if (totalAmount > MAX_TOTAL_ORDER_COUNT) {
+            throw new OrderException(OrderExceptionMessage.OVERALL_ORDER_COUNT);
+        }
+    }
+
+    private static void validateMenuIsOnlyDrink(List<OrderInfo> orderDrinks, int totalOrderCount) {
+        int drinkOrderCount = countOrderMenus(orderDrinks);
+        if (drinkOrderCount == totalOrderCount) {
+            throw new OrderException(OrderExceptionMessage.ONLY_DRINK);
+        }
+    }
+
+
+    private static Integer countTotalOrderMenu(EnumMap<Category, List<OrderInfo>> orderBoard) {
+        int totalOrderCount = 0;
+        for (List<OrderInfo> orderInfos : orderBoard.values()) {
+            totalOrderCount += countOrderMenus(orderInfos);
+        }
+        return totalOrderCount;
+    }
+
+    private static Integer countOrderMenus(List<OrderInfo> orderInfos) {
+        int orderCount = 0;
+        for (OrderInfo orderInfo : orderInfos) {
+            orderCount += orderInfo.amount();
+        }
+        return orderCount;
+    }
+
+    private static Integer calculateTotalPrice(EnumMap<Category, List<OrderInfo>> orderBoard) {
+        int totalPrice = 0;
+        for (List<OrderInfo> orderInfos : orderBoard.values()) {
+            for (OrderInfo orderInfo : orderInfos) {
+                int price = orderInfo.menu().price();
+                totalPrice += orderInfo.amount() * price;
+            }
+        }
+        return totalPrice;
+    }
+}
\ No newline at end of file

리뷰: 지역변수 재할당은 자바가 싫어하는 문법이라고 알고 있어요!
스트림 문법을 통해 필터링해서 더하는 로직을 설계한다면,
불필요한 지역변수 재할당을 피할 수 있을 것 같아요!