ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,70 @@
+package christmas.domain.order.menu;
+
+import java.util.Arrays;
+import java.util.Map;
+
+public enum Menu {
+
+    // 기타
+    NONE("없음", 0, MenuType.NONE),
+
+    // 에피타이저
+    MUSHROOM_SOUP("양송이 스프", 6_000, MenuType.APPETIZER),
+    TAPAS("타파스", 5_500, MenuType.APPETIZER),
+    CAESAR_SALAD("시저 샐러드", 8_000, MenuType.APPETIZER),
+
+    // 메인
+    T_BONE_STEAK("티본스테이크", 55_000, MenuType.MAIN),
+    BBQ_RIBS("바비큐립", 54_000, MenuType.MAIN),
+    SEAFOOD_PASTA("해산물파스타", 35_000, MenuType.MAIN),
+    CHRISTMAS_PASTA("크리스마스파스타", 25_000, MenuType.MAIN),
+
+    // 디저트
+    CHOCOLATE_CAKE("초코케이크", 15_000, MenuType.DESSERT),
+    ICE_CREAM("아이스크림", 5_000, MenuType.DESSERT),
+
+    // 음료
+    ZERO_COKE("제로콜라", 3_000, MenuType.DRINK),
+    RED_WINE("레드와인", 60_000, MenuType.DRINK),
+    CHAMPAGNE("샴페인", 25_000, MenuType.DRINK);
+
+    private final String name;
+    private final int price;
+    private final MenuType type;
+
+    Menu(String name, int price, MenuType type) {
+        this.name = name;
+        this.price = price;
+        this.type = type;
+    }
+
+    public static Menu findByName(String name) {
+        return Arrays.stream(values())
+                .filter(menu -> menu.name.equals(name))
+                .findAny()
+                .orElse(Menu.NONE);
+    }
+
+    public static boolean isGiftMenu(Menu menu) {
+        return getGiftMenus()
+                .keySet()
+                .stream()
+                .anyMatch(giftMenu -> giftMenu.equals(menu));
+    }
+
+    public static Map<Menu, Quantity> getGiftMenus() {
+        return Map.of(Menu.CHAMPAGNE, Quantity.create(1));
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+
+    public MenuType getType() {
+        return type;
+    }
+}

리뷰: 제 경우 1월 새해 이벤트에 이벤트가 변경될 수 있다 가정해 Menu 인터페이스를 선언한 뒤 에피타이저, 메인, 디저트, 음료별로 ENUM 객체를 각각 따로 선언했습니다!

참고하시면 좋을 것 같아요!

``` java
public interface Menu {

    int discount(int day);

    String getName();

    int getPrice();
}
```

``` java
public enum Appetizer implements Menu {
    MUSHROOM_SOUP("양송이수프", 6000),
    TAPAS("타파스", 5500),
    CAESAR_SALAD("시저샐러드", 8000);

    private final String name;
    private final int price;

    Appetizer(String name, int price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public int discount(int day) {
        return 0;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getPrice() {
        return price;
    }
}
```
@@ -0,0 +1,40 @@
+package christmas.domain.order.menu;
+
+import christmas.validator.OrderValidator;
+
+import java.util.Objects;
+
+public class Quantity {
+
+    private final Integer quantity;
+
+    private Quantity(Integer quantity) {
+        validate(quantity);
+        this.quantity = quantity;
+    }
+
+    public static Quantity create(Integer quantity) {
+        return new Quantity(quantity);
+    }
+
+    private void validate(Integer quantity) {
+        OrderValidator.validateIsEachQuantityGreaterThanCondition(quantity);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Quantity quantity1 = (Quantity) o;
+        return Objects.equals(quantity, quantity1.quantity);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(quantity);
+    }
+
+    public Integer getPrimitiveQuantity() {
+        return quantity;
+    }
+}

리뷰: int가 아닌 Integer로 선언해주시는 이유가 궁금합니다!🤔
@@ -0,0 +1,18 @@
+package christmas.domain.discount;
+
+import christmas.domain.order.Day;
+import christmas.domain.order.Order;
+
+public interface Discount {
+
+    public void calculateDiscountAmount(Order order, Day day);
+
+    public void checkIsAvailableDiscount(Order order, Day day);
+
+    public String getName();
+
+    public int getDiscountAmount();
+
+    public boolean getIsAvailable();
+
+}

리뷰: 다형성을 이용하는 정말 좋은 방법이네요 배우고갑니다!
@@ -0,0 +1,40 @@
+package christmas.domain.order.menu;
+
+import christmas.validator.OrderValidator;
+
+import java.util.Objects;
+
+public class Quantity {
+
+    private final Integer quantity;
+
+    private Quantity(Integer quantity) {
+        validate(quantity);
+        this.quantity = quantity;
+    }
+
+    public static Quantity create(Integer quantity) {
+        return new Quantity(quantity);
+    }
+
+    private void validate(Integer quantity) {
+        OrderValidator.validateIsEachQuantityGreaterThanCondition(quantity);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Quantity quantity1 = (Quantity) o;
+        return Objects.equals(quantity, quantity1.quantity);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(quantity);
+    }
+
+    public Integer getPrimitiveQuantity() {
+        return quantity;
+    }
+}

리뷰: 큰 의미가 있는 것은 아니고, null 처리에 대비하여 Integer를 사용하게 되었습니다. 사실 입력값 검증 로직이 이미 있어서 null이 들어갈 일은 없을 것 같기도 하네요!
@@ -0,0 +1,63 @@
+package christmas.controller;
+
+import christmas.domain.PromotionService;
+import christmas.domain.order.Day;
+import christmas.domain.order.Order;
+import christmas.dto.response.DiscountPreviewResponse;
+import christmas.view.InputView;
+import christmas.view.OutputView;
+
+import java.util.function.Supplier;
+
+public class PromotionController {
+
+    private PromotionController() {
+
+    }
+
+    public static PromotionController create() {
+        return new PromotionController();
+    }
+
+
+    public void run() {
+        printIntroductionMessage();
+
+        Day day = readWithExceptionHandling(PromotionController::readDay);
+        Order order = readWithExceptionHandling(PromotionController::readOrder);
+        PromotionService promotionService = PromotionService.create(order, day);
+        closeRead();
+
+        printDiscountPreviewMessage(promotionService);
+    }
+
+    private static void printIntroductionMessage() {
+        OutputView.printIntroductionMessage();
+    }
+
+    private static <T> T readWithExceptionHandling(Supplier<T> reader) {
+        while (true) {
+            try {
+                return reader.get();
+            } catch (IllegalArgumentException exception) {
+                System.out.println(exception.getMessage());
+            }
+        }
+    }
+
+    private static Day readDay() throws IllegalArgumentException {
+        return Day.create(InputView.readEstimatedVisitingDate());
+    }
+
+    private static Order readOrder() throws IllegalArgumentException {
+        return Order.create(InputView.readOrder());
+    }
+
+    private static void closeRead() {
+        InputView.closeRead();
+    }
+
+    private static void printDiscountPreviewMessage(PromotionService promotionService) {
+        OutputView.printDiscountPreviewMessage(DiscountPreviewResponse.from(promotionService));
+    }
+}

리뷰: 아...! 제가 인텔리제이의 메소드 분리 단축키인 option + command + v를 자주 사용하는데, 그 과정에서 자동으로 static 메소드로 선언된 것 같습니다. 전부 지워야겠네요 😂
@@ -0,0 +1,40 @@
+package christmas.domain.order;
+
+import christmas.validator.OrderValidator;
+
+import java.util.Objects;
+
+public class Day {
+
+    private final Integer day;
+
+    private Day(Integer day) {
+        validate(day);
+        this.day = day;
+    }
+
+    public static Day create(Integer day) {
+        return new Day(day);
+    }
+
+    private void validate(Integer day) {
+        OrderValidator.validateIsDateInRange(day);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Day day1 = (Day) o;
+        return Objects.equals(day, day1.day);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(day);
+    }
+
+    public Integer getPrimitiveDay() {
+        return day;
+    }
+}

리뷰: 각 VO에서 이루어지는 검증을 한 군데에서 모아 관리하면 편리할 것이라 생각하였는데, 말씀주신 것처럼 캡슐화가 깨지는 문제도 있을 뿐더러 OrderValidator 객체가 비대해진다면 결국에 로직을 분리해야할 것이고 이러면 한 곳에서 관리할 수 있다는 장점 또한 사라질 것 같습니다.

결국에는 제일 관련성이 깊은 VO 내부에서 유효성 검사를 하는 것이 맞겠네요! 좋은 조언 감사합니다 😄
@@ -0,0 +1,74 @@
+package christmas.domain.order;
+
+import christmas.domain.order.menu.Menu;
+import christmas.domain.order.menu.Quantity;
+import christmas.dto.request.OrderRequest;
+import christmas.dto.response.OrderResponse;
+import christmas.util.InputUtil;
+import christmas.validator.OrderValidator;
+
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+public class Order {
+
+    Map<Menu, Quantity> Order;
+
+    private Order(List<OrderRequest> orderRequests) {
+        Map<Menu, Quantity> order = InputUtil.parseOrderRequests(orderRequests);
+        validate(order);
+        this.Order = new EnumMap<>(order);
+    }
+
+    public static Order create(List<OrderRequest> orderRequests) {
+        return new Order(orderRequests);
+    }
+
+    private void validate(Map<Menu, Quantity> order) {
+        OrderValidator.validateHasOnlyDrink(order);
+        OrderValidator.validateIsTotalQuantityValid(order);
+    }
+
+    public List<OrderResponse> findOrderResponses() {
+        return Order
+                .entrySet()
+                .stream()
+                .map(entry -> OrderResponse.of(entry.getKey(), entry.getValue()))
+                .toList();
+    }
+
+    public int calculateInitialPrice() {
+        return Order
+                .entrySet()
+                .stream()
+                .mapToInt(entry -> getMenuPrice(entry) * getEachQuantity(entry))
+                .sum();
+    }
+
+    private int getMenuPrice(Map.Entry<Menu, Quantity> entry) {
+        return entry.getKey().getPrice();
+    }
+
+    private Integer getEachQuantity(Map.Entry<Menu, Quantity> entry) {
+        return entry.getValue().getPrimitiveQuantity();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Order order = (Order) o;
+        return Objects.equals(getOrder(), order.getOrder());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getOrder());
+    }
+
+    public Map<Menu, Quantity> getOrder() {
+        return new EnumMap<>(Order);
+    }
+}

리뷰: 저도 지금 봤네요ㅋㅋㅠㅠ private 선언해야 되는데 까먹은 것 같습니다 🤣
@@ -0,0 +1,70 @@
+package christmas.domain.order.menu;
+
+import java.util.Arrays;
+import java.util.Map;
+
+public enum Menu {
+
+    // 기타
+    NONE("없음", 0, MenuType.NONE),
+
+    // 에피타이저
+    MUSHROOM_SOUP("양송이 스프", 6_000, MenuType.APPETIZER),
+    TAPAS("타파스", 5_500, MenuType.APPETIZER),
+    CAESAR_SALAD("시저 샐러드", 8_000, MenuType.APPETIZER),
+
+    // 메인
+    T_BONE_STEAK("티본스테이크", 55_000, MenuType.MAIN),
+    BBQ_RIBS("바비큐립", 54_000, MenuType.MAIN),
+    SEAFOOD_PASTA("해산물파스타", 35_000, MenuType.MAIN),
+    CHRISTMAS_PASTA("크리스마스파스타", 25_000, MenuType.MAIN),
+
+    // 디저트
+    CHOCOLATE_CAKE("초코케이크", 15_000, MenuType.DESSERT),
+    ICE_CREAM("아이스크림", 5_000, MenuType.DESSERT),
+
+    // 음료
+    ZERO_COKE("제로콜라", 3_000, MenuType.DRINK),
+    RED_WINE("레드와인", 60_000, MenuType.DRINK),
+    CHAMPAGNE("샴페인", 25_000, MenuType.DRINK);
+
+    private final String name;
+    private final int price;
+    private final MenuType type;
+
+    Menu(String name, int price, MenuType type) {
+        this.name = name;
+        this.price = price;
+        this.type = type;
+    }
+
+    public static Menu findByName(String name) {
+        return Arrays.stream(values())
+                .filter(menu -> menu.name.equals(name))
+                .findAny()
+                .orElse(Menu.NONE);
+    }
+
+    public static boolean isGiftMenu(Menu menu) {
+        return getGiftMenus()
+                .keySet()
+                .stream()
+                .anyMatch(giftMenu -> giftMenu.equals(menu));
+    }
+
+    public static Map<Menu, Quantity> getGiftMenus() {
+        return Map.of(Menu.CHAMPAGNE, Quantity.create(1));
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+
+    public MenuType getType() {
+        return type;
+    }
+}

리뷰: 메뉴 Enum에도 이런 식으로 인터페이스를 적용할 수 있는데 생각하지 못했네요! 참고하겠습니다...!
@@ -0,0 +1,31 @@
+package christmas.model.badge.enums;
+
+import java.util.Arrays;
+
+public enum BadgeInfo {
+
+    SANTA_BADGE("산타", 20_000),
+    TREE_BADGE("트리", 10_000),
+    START_BADGE("별", 5_000),
+    NON_BADGE("없음", 0);
+
+    private final String name;
+
+    private final int price;
+
+    BadgeInfo(String name, int price) {
+        this.name = name;
+        this.price = price;
+    }
+
+    public static BadgeInfo findBadgeByPrice(int totalPrice) {
+        return Arrays.stream(values())
+                .filter(badge -> totalPrice >= badge.price)
+                .findFirst()
+                .orElse(NON_BADGE);
+    }
+
+    public String getName() {
+        return name;
+    }
+}

리뷰: 실수를 미션이 끝나고 발견했습니다 ^^..
START -> STAR
@@ -0,0 +1,32 @@
+package christmas.model.discount;
+
+
+import static christmas.exception.ErrorType.INVALID_ORDER_AMOUNT;
+import static christmas.model.discount.enums.DiscountAmount.CAN_GIVEAWAY_DISCOUNT;
+import static christmas.model.discount.enums.DiscountAmount.NON_DISCOUNT;
+
+import christmas.model.order.enums.MenuInfo;
+
+public class GiveawayDiscount implements Discount {
+
+    private final int totalOrderAmount;
+
+    public GiveawayDiscount(int totalOrderAmount) {
+        validateOrderAmount(totalOrderAmount);
+        this.totalOrderAmount = totalOrderAmount;
+    }
+
+    private void validateOrderAmount(int totalOrderAmount) {
+        if (totalOrderAmount < NON_DISCOUNT.getDiscount()) {
+            throw new IllegalArgumentException(INVALID_ORDER_AMOUNT.getMessage());
+        }
+    }
+
+    @Override
+    public int calculateDiscount() {
+        if (totalOrderAmount >= CAN_GIVEAWAY_DISCOUNT.getDiscount()) {
+            return MenuInfo.CHRISTMAS_PASTA.getPrice();
+        }
+        return NON_DISCOUNT.getDiscount();
+    }
+}

리뷰: 실수를 미션이 끝나고 발견했습니다 ^^..
파스타 -> 샴페인 (가격이 똑같아서 눈치채지 못했네요 (__))
@@ -0,0 +1,61 @@
+package christmas.model.order.enums;
+
+import static christmas.exception.ErrorType.INVALID_MENU_NOT_EXIST;
+
+import java.util.Arrays;
+
+public enum MenuInfo {
+
+    MUSHROOM_SOUP("양송이수프", 6_000, Category.APPETIZER),
+    TAPAS("타파스", 5_500, Category.APPETIZER),
+    CAESAR_SALAD("시저샐러드", 8_000, Category.APPETIZER),
+
+    T_BONE_STEAK("티본스테이크", 55_000, Category.MAIN_COURSE),
+    BARBECUE_RIBS("바비큐립", 54_000, Category.MAIN_COURSE),
+    SEAFOOD_PASTA("해산물파스타", 35_000, Category.MAIN_COURSE),
+    CHRISTMAS_PASTA("크리스마스파스타", 25_000, Category.MAIN_COURSE),
+
+    CHOCOLATE_CAKE("초코케이크", 15_000, Category.DESSERT),
+    ICE_CREAM("아이스크림", 5_000, Category.DESSERT),
+
+    ZERO_COLA("제로콜라", 3_000, Category.BEVERAGE),
+    RED_WINE("레드와인", 60_000, Category.BEVERAGE),
+    CHAMPAGNE("샴페인", 25_000, Category.BEVERAGE);
+
+    private final String name;
+
+    private final int price;
+
+    private final Category category;
+
+    MenuInfo(String name, int price, Category category) {
+        this.name = name;
+        this.price = price;
+        this.category = category;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+
+    public Category getCategory() {
+        return category;
+    }
+
+    public static boolean isExistMenu(String name) {
+        return Arrays.stream(MenuInfo.values())
+                .map(MenuInfo::getName)
+                .anyMatch(existMenu -> existMenu.equals(name));
+    }
+
+    public static MenuInfo findByMenuName(String name) {
+        return Arrays.stream(MenuInfo.values())
+                .filter(menuInfo -> menuInfo.getName().equals(name))
+                .findFirst()
+                .orElseThrow(() -> new IllegalArgumentException(INVALID_MENU_NOT_EXIST.getMessage()));
+    }
+}

리뷰: 메뉴 종류별 주문 수량을 저장하는 Map을 만드는 메소드가 있어도 좋을 것 같습니다.
@@ -0,0 +1,54 @@
+package christmas.model.calendar;
+
+import static christmas.model.calendar.enums.CalendarDate.CHRISTMAS;
+import static christmas.model.calendar.enums.CalendarDate.EVENT_MONTH;
+import static christmas.model.calendar.enums.CalendarDate.EVENT_YEAR;
+import static christmas.model.calendar.enums.CalendarDate.FRIDAY;
+import static christmas.model.calendar.enums.CalendarDate.SATURDAY;
+import static christmas.model.calendar.enums.CalendarDate.SUNDAY;
+
+import java.time.LocalDate;
+
+public abstract class EventCalendar implements Calendar {
+
+    protected final LocalDate eventDate;
+
+    public EventCalendar(int visitDay) {
+        validate(visitDay);
+        this.eventDate = LocalDate.of(EVENT_YEAR.getNumber(), EVENT_MONTH.getNumber(), visitDay);
+    }
+
+    protected abstract void validateDayRange(int visitDay);
+
+    @Override
+    public boolean isWeekend() {
+        int visitDay = getDayOfWeek();
+        return visitDay == FRIDAY.getNumber() || visitDay == SATURDAY.getNumber();
+    }
+
+    @Override
+    public boolean isSpecialDay() {
+        return isChristmas() || isSunday();
+    }
+
+    @Override
+    public int getDayOfMonth() {
+        return eventDate.getDayOfMonth();
+    }
+
+    private void validate(int visitDay) {
+        validateDayRange(visitDay);
+    }
+
+    private boolean isChristmas() {
+        return getDayOfMonth() == CHRISTMAS.getNumber();
+    }
+
+    private boolean isSunday() {
+        return getDayOfWeek() == SUNDAY.getNumber();
+    }
+
+    private int getDayOfWeek() {
+        return eventDate.getDayOfWeek().getValue();
+    }
+}

리뷰: `DayOfWeek`는 `enum` 타입이기에 다음과 같이 직접적인 동등성 비교도 가능하며, 이 경우가 가독성도 더 좋아질 것 같습니다!
```suggestion
        DayOfWeek week = eventDate.getDayOfWeek();
        return week == DayOfWeek.FRIDAY || week == DayOfWeek.SATURDAY;
```
@@ -0,0 +1,14 @@
+package christmas.model.calendar;
+
+import static christmas.model.calendar.enums.CalendarDate.CHRISTMAS;
+
+public class CalendarFactory {
+
+    public static Calendar createCalendar(int day) {
+        if (day <= CHRISTMAS.getNumber()) {
+            return new ChristmasEventCalendar(day);
+        }
+
+        return new GeneralEventCalendar(day);
+    }
+}

리뷰: 아하, 입력 날짜가 크리스마스 이후인지의 여부에 따라 각각 다른 `Calendar` 클래스를 사용하도록 하셨네요.
이렇게도 구현을 할 수 있었군요!
@@ -0,0 +1,31 @@
+package christmas.model.badge.enums;
+
+import java.util.Arrays;
+
+public enum BadgeInfo {
+
+    SANTA_BADGE("산타", 20_000),
+    TREE_BADGE("트리", 10_000),
+    START_BADGE("별", 5_000),
+    NON_BADGE("없음", 0);
+
+    private final String name;
+
+    private final int price;
+
+    BadgeInfo(String name, int price) {
+        this.name = name;
+        this.price = price;
+    }
+
+    public static BadgeInfo findBadgeByPrice(int totalPrice) {
+        return Arrays.stream(values())
+                .filter(badge -> totalPrice >= badge.price)
+                .findFirst()
+                .orElse(NON_BADGE);
+    }
+
+    public String getName() {
+        return name;
+    }
+}

리뷰: 뱃지를 얻을 수 있는 하한가 금액만 설정해 두고, `enum`의 순서를 활용하셨네요!
`enum`의 순서에 영향을 받는 로직을 작성하는 것이 옳은가 에 대한 확신이 없어 이렇게 구현하지 못했는데, 이렇게 구현하는 것이 훨씬 간결하고 좋았을 것도 같군요!
@@ -0,0 +1,20 @@
+package christmas.model.badge;
+
+import christmas.model.badge.enums.BadgeInfo;
+
+public class Badge {
+
+    private final BadgeInfo badgeInfo;
+
+    public Badge(int totalDiscountAmount) {
+        this.badgeInfo = selectBadge(totalDiscountAmount);
+    }
+
+    public String getBadgeName() {
+        return badgeInfo.getName();
+    }
+
+    private BadgeInfo selectBadge(int totalDiscountAmount) {
+        return BadgeInfo.findBadgeByPrice(totalDiscountAmount);
+    }
+}

리뷰: 해당 클래스는 어떻게 보면 `BadgeInfo`를 래핑하고 있는 래핑 클래스처럼 보이는데요.
이 클래스를 사용하는 것에는 어떤 이점이 있을 수 있을까요?
@@ -0,0 +1,15 @@
+package christmas.model.order.enums;
+
+public enum Category {
+
+    APPETIZER("에피타이저"),
+    MAIN_COURSE("메인"),
+    DESSERT("디저트"),
+    BEVERAGE("음료");
+
+    private final String category;
+
+    Category(String category) {
+        this.category = category;
+    }
+}

리뷰: 해당 필드는 확장성을 위한 필드인가요?
@@ -0,0 +1,51 @@
+package christmas.model.order;
+
+import static christmas.exception.ErrorType.INVALID_MENU_NAME;
+
+import christmas.model.order.enums.Category;
+import christmas.model.order.enums.MenuInfo;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class OrderMenu {
+
+    private final Map<MenuName, MenuQuantity> orderMenu;
+
+    public OrderMenu() {
+        this.orderMenu = new HashMap<>();
+    }
+
+    public Map<MenuName, MenuQuantity> getOrderMenu() {
+        return Collections.unmodifiableMap(orderMenu);
+    }
+
+    public int getMenuQuantity(MenuName menuName) {
+        return orderMenu.get(menuName).getQuantity();
+    }
+
+    public boolean containMainMenu(MenuName menuName) {
+        String menu = menuName.getName();
+        return MenuInfo.findByMenuName(menu).getCategory() == Category.MAIN_COURSE;
+    }
+
+    public boolean containDesertMenu(MenuName menuName) {
+        String menu = menuName.getName();
+        return MenuInfo.findByMenuName(menu).getCategory() == Category.DESSERT;
+    }
+
+    public void addMenu(MenuName menuName, MenuQuantity menuQuantity) {
+        validate(menuName);
+        orderMenu.put(menuName, menuQuantity);
+    }
+
+    private void validate(MenuName menuName) {
+        validateDuplicateMenuName(menuName);
+    }
+
+    private void validateDuplicateMenuName(MenuName menuName) {
+        if (orderMenu.containsKey(menuName)) {
+            throw new IllegalArgumentException(INVALID_MENU_NAME.getMessage());
+        }
+    }
+}

리뷰: 이름은 `MainMenu`를 포함하는지를 판단하는 메서드처럼 느껴지는데, 아래의 로직은 입력받은 메뉴가 메인메뉴인지를 판단하네요.
`contain~`보다 `is~`의 네이밍이 조금 더 적절할 수 있을 것 같습니다!
@@ -0,0 +1,64 @@
+package christmas.model.result;
+
+import static christmas.model.discount.enums.DiscountAmount.NON_DISCOUNT;
+
+public class DiscountResult {
+
+    private int christmasDiscount;
+
+    private int weeksDaysDiscount;
+
+    private int weekendDiscount;
+
+    private int specialDiscount;
+
+    private int giveawayDiscount;
+
+    public DiscountResult() {
+        this.christmasDiscount = NON_DISCOUNT.getDiscount();
+        this.weeksDaysDiscount = NON_DISCOUNT.getDiscount();
+        this.weekendDiscount = NON_DISCOUNT.getDiscount();
+        this.specialDiscount = NON_DISCOUNT.getDiscount();
+        this.giveawayDiscount = NON_DISCOUNT.getDiscount();
+    }
+
+    public void updateChristmasDiscount(int christmasDiscount) {
+        this.christmasDiscount = christmasDiscount;
+    }
+
+    public void updateWeeksDaysDiscount(int weeksDaysDiscount) {
+        this.weeksDaysDiscount = weeksDaysDiscount;
+    }
+
+    public void updateWeekendDiscount(int weekendDiscount) {
+        this.weekendDiscount = weekendDiscount;
+    }
+
+    public void updateSpecialDiscount(int specialDiscount) {
+        this.specialDiscount = specialDiscount;
+    }
+
+    public void updateGiveawayDiscount(int giveawayDiscount) {
+        this.giveawayDiscount = giveawayDiscount;
+    }
+
+    public int getChristmasDiscount() {
+        return christmasDiscount;
+    }
+
+    public int getWeeksDaysDiscount() {
+        return weeksDaysDiscount;
+    }
+
+    public int getWeekendDiscount() {
+        return weekendDiscount;
+    }
+
+    public int getSpecialDiscount() {
+        return specialDiscount;
+    }
+
+    public int getGiveawayDiscount() {
+        return giveawayDiscount;
+    }
+}

리뷰: 아하, 처음엔 모든 할인 적용을 0으로 두고 할인을 적용할 수 있을 땐 내부의 값들을 새로 업데이트 해주는군요!
저와는 다른 접근이라서 정말 재미있게 읽었습니다!