@@ -0,0 +1,117 @@
+package christmas.model;
+
+import christmas.domain.Holiday;
+import christmas.domain.Menu;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class Discount {
+
+    private final static int DISCOUNTUNIT = 100;
+    private final static int CHRISTMASDATE = 25;
+    private final static int BASICDISCOUNT = 1000;
+    private final static int PERIOD = 7;
+    private final static int DISCOUNT = 2023;
+    private final static int STARTDISCOUNT = 1000;
+    private final static int NOTDISCOUNT = 0;
+    private final static int CHAMPAGNEEVENT = 120000;
+    private final static String christmasDayDiscount = "크리스마스 디데이 할인";
+    private final static String weekendDiscount = "평일 할인";
+    private final static String holidayDiscount = "주말 할인";
+    private final static String specialDiscount = "특별 할인";
+    private final static String bonusEvent = "증정 이벤트";
+
+    public Map<String, Integer> discountTotal(int date, Map<Menu, Integer> orderMenu, int payAmount) {
+        Map<String, Integer> discountResult = new LinkedHashMap<>();
+        discountInput(date, orderMenu, payAmount, discountResult);
+        return discountResult;
+    }
+
+    private void discountInput(int date, Map<Menu, Integer> orderMenu, int payAmount, Map<String, Integer> discountResult) {
+        if (discountChristmas(date) != 0) {
+            discountResult.put(christmasDayDiscount, discountChristmas(date));
+        }
+        if (discountDay(date).stream().anyMatch(menu -> orderMenu.containsKey(menu))) {
+            weekEndOrHolidayTotalDiscount(date, discountResult, discountDay(date), orderMenu);
+        }
+        if (discountStar(date) != 0) {
+            discountResult.put(specialDiscount, discountStar(date));
+        }
+        if (eventChampagne(payAmount)) {
+            discountResult.put(bonusEvent, Menu.CHAMPAGNE.getPrice());
+        }
+    }
+
+    public int discountTotalAmount(Map<String, Integer> discountTotal) {
+        return discountTotal.values().stream().mapToInt(Integer::intValue).sum();
+    }
+
+    public int discountTotalAmountExceptBonus(Map<String, Integer> discountTotal) {
+        return discountTotal.keySet().stream().filter(key -> !key.equals(bonusEvent))
+                .mapToInt(key -> discountTotal.get(key)).sum();
+    }
+
+    public void weekEndOrHolidayTotalDiscount(int date, Map<String, Integer> discountResult,
+                                              List<Menu> discount, Map<Menu, Integer> orderMenu) {
+        int sum = orderMenu.keySet().stream()
+                .filter(menu -> discount.contains(menu)).mapToInt(key -> orderMenu.get(key) * DISCOUNT).sum();
+        if (weekOrHoliday(date)) {
+            discountResult.put(holidayDiscount, sum);
+            return;
+        }
+        discountResult.put(weekendDiscount, sum);
+    }
+
+    public boolean eventChampagne(int orderAmount) {
+        if (orderAmount >= CHAMPAGNEEVENT) {
+            return true;
+        }
+        return false;
+    }
+
+    public int discountStar(int date) {
+        if (Arrays.stream(Holiday.values()).anyMatch(i -> i.getDate() == date)) {
+            return STARTDISCOUNT;
+        }
+        return NOTDISCOUNT;
+    }
+
+    public int discountChristmas(int date) {
+        int result = 0;
+        if (date <= CHRISTMASDATE) {
+            result = BASICDISCOUNT + DISCOUNTUNIT * (date - 1);
+        }
+        return result;
+    }
+
+    public List<Menu> discountDay(int date) {
+        if (weekOrHoliday(date)) {
+            return discountHoliday();
+        }
+        return discountWeekday();
+    }
+
+    //true : 주말 | false : 평일
+    private boolean weekOrHoliday(int date) {
+        if (date % 7 == 1 || date % 7 == 2) {
+            return true;
+        }
+        return false;
+    }
+
+    private List<Menu> discountWeekday() {
+        return Arrays.stream(Menu.values()).filter(menu -> menu != menu.NONE)
+                .filter(menu -> menu.getType().equals("desert"))
+                .collect(Collectors.toList());
+    }
+
+    private List<Menu> discountHoliday() {
+        return Arrays.stream(Menu.values()).filter(menu -> menu != menu.NONE)
+                .filter(menu -> menu.getType().equals("main"))
+                .collect(Collectors.toList());
+    }
+}

리뷰: 1. Menu.NONE은 static 변수이니, menu.NONE과 같이 인스턴스화한 변수에서 액세스 되면 안됩니다
2. isDesert 와 같이, Menu에게 직접 디저트냐고 물어보면 어떨까요
3. toList()로 축약할 수 있을 것 같아요
```suggestion
        return Arrays.stream(Menu.values())
                .filter(menu -> menu != Menu.NONE)
                .filter(Menu::isDesert)
                .toList();
```