ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,48 @@
+package christmas.domain.entity;
+
+import christmas.domain.util.Util;
+
+import java.util.Arrays;
+
+import static christmas.system.IOMessage.EMPTY_STRING;
+import static christmas.system.IOMessage.QUANTITY_UNIT;
+
+public enum BonusMenu {
+    CHAMPAGNE(Menu.CHAMPAGNE, 1);
+
+    private final Menu menu;
+    private final int quantity;
+
+    BonusMenu(Menu menu, int quantity) {
+        this.menu = menu;
+        this.quantity = quantity;
+    }
+
+    public static int calculateTotalPriceForAllMenus() {
+        return Arrays.stream(BonusMenu.values())
+                .mapToInt(BonusMenu::getTotalPrice)
+                .sum();
+    }
+
+    public static String generateAllMenuDetails() {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (BonusMenu bonusMenu : BonusMenu.values()) {
+            stringBuilder.append(bonusMenu.toString()).append(System.lineSeparator());
+        }
+        return stringBuilder.toString();
+    }
+
+    @Override
+    public String toString() {
+        return getName() + EMPTY_STRING + Util.createFormattedAmount(quantity) + QUANTITY_UNIT;
+    }
+
+    private String getName() {
+        return menu.getMenuName();
+    }
+
+    private int getTotalPrice() {
+        return menu.getMenuPrice() * quantity;
+    }
+
+}

리뷰: 이부분은 출력 부분과 관계 있어서 OutputView가 일하게 하는 것은 어떨까요?
@@ -0,0 +1,65 @@
+package christmas.domain.manager;
+
+
+import christmas.domain.entity.Day;
+import christmas.domain.entity.Order;
+
+import static christmas.domain.entity.MenuType.*;
+import static christmas.system.Constant.ZERO;
+
+public class DiscountManager {
+
+    private final int DISCOUNT_AMOUNT = 2023;
+    private final int INITIAL_DISCOUNT_AMOUNT = 1000;
+    private final int DAILY_DISCOUNT_INCREASE = 100;
+
+    public DiscountManager() {
+    }
+
+    public int calculateDDayDiscount(Day day) {
+        if (day.isChristmasSeason()) {
+            return calculateDDayAmount(day);
+        }
+        return ZERO;
+    }
+
+    public int calculateWeekDayDiscount(Day day, Order order) {
+        if (day.isWeekday()) {
+            return calculateWeekDayAmount(order);
+        }
+        return ZERO;
+    }
+
+    public int calculateWeekendDiscount(Day day, Order order) {
+        if (day.isWeekend()) {
+            return calculateWeekendAmount(order);
+        }
+        return ZERO;
+    }
+
+    public int calculateSpecialDayDiscount(Day day) {
+        int STAR_DISCOUNT = 1000;
+        if (day.isSpecialDay()) {
+            return STAR_DISCOUNT;
+        }
+        return ZERO;
+    }
+
+    private int calculateDDayAmount(Day day) {
+        return INITIAL_DISCOUNT_AMOUNT + DAILY_DISCOUNT_INCREASE * (day.getDay() - 1);
+    }
+
+    private int calculateWeekDayAmount(Order order) {
+        return order.getOrderItems().stream()
+                .filter(orderItem -> orderItem.getMenuType() == DESSERT)
+                .mapToInt(orderItem -> DISCOUNT_AMOUNT * orderItem.getQuantity())
+                .sum();
+    }
+
+    private int calculateWeekendAmount(Order order) {
+        return order.getOrderItems().stream()
+                .filter(orderItem -> orderItem.getMenuType() == MAIN)
+                .mapToInt(orderItem -> DISCOUNT_AMOUNT * orderItem.getQuantity())
+                .sum();
+    }
+}

리뷰: day 객체에 해당 메서드를 넣어놓으니 읽기도 매우 편해서 좋네요 👍👍
@@ -0,0 +1,12 @@
+package christmas.domain.util;
+
+
+import java.text.DecimalFormat;
+
+public final class Util {
+    public static String createFormattedAmount(int target) {
+        DecimalFormat formatter = new DecimalFormat("###,##0");
+        return formatter.format(target);
+    }
+
+}

리뷰: split 하는 기준이 나중에는 달라질 수 있으니 상수로 만들어 관리하면 나중에 유지보수하기 좋을 것 같아요!
@@ -0,0 +1,54 @@
+package christmas.controller;
+
+import christmas.domain.entity.Day;
+import christmas.domain.entity.Order;
+import christmas.view.InputView;
+import java.util.function.Supplier;
+
+import static christmas.domain.verifier.RuntimeVerifier.RUNTIME_VERIFIER;
+import static christmas.system.IOMessage.ORDER_PROMPT_MESSAGE;
+import static christmas.system.IOMessage.VISIT_DATE_PROMPT_MESSAGE;
+import static christmas.view.InputView.*;
+import static christmas.view.OutputView.*;
+
+public class PlannerSystem {
+
+    private final Day day;
+    private final Order order;
+    private final SettlementSystem settlementSystem;
+
+    public PlannerSystem() {
+        printMessage(VISIT_DATE_PROMPT_MESSAGE);
+        this.day = readDay();
+        printEventNotice();
+        printMessage(ORDER_PROMPT_MESSAGE);
+        this.order = readOrder(InputView::tryReadOrder);
+        this.settlementSystem = new SettlementSystem(day, order);
+    }
+    public void run() {
+        renderResult();
+    }
+
+    private Order readOrder(Supplier<Order> orderSupplier) {
+        while (true) {
+            try {
+                Order order = orderSupplier.get();
+                RUNTIME_VERIFIER.validate(order);
+                return order;
+            } catch (IllegalStateException e) {
+                printMessage(e.getMessage());
+            }
+        }
+    }
+
+    private void renderResult() {
+        renderPlannerResult();
+        settlementSystem.renderSettlementResult();
+
+    }
+
+    private void renderPlannerResult() {
+        printResultStartMessage(day);
+        printOrderList(order);
+    }
+}

리뷰: 사실 이게 system. run()의 여러 기능중에 하나가  renderResult()이라고 생각해서 뺐어요!. 나중에 확장성있게 다른 기능들도 넣을수 있게하기 위해서요!
@@ -0,0 +1,27 @@
+package christmas.system;
+
+public final class IOMessage {
+    public static final String VISIT_DATE_PROMPT_MESSAGE = "안녕하세요! 우테코 식당 12월 이벤트 플래너입니다.\n" +
+            "12월 중 식당 예상 방문 날짜는 언제인가요? (숫자만 입력해 주세요!)";
+
+    public static final String ORDER_PROMPT_MESSAGE = "주문하실 메뉴를 메뉴와 개수를 알려 주세요. (e.g. 해산물파스타-2,레드와인-1,초코케이크-1)";
+
+    public static final String NONE = "없음";
+    public static final String EMPTY_STRING = " ";
+    public static final String MESSAGE_DELIMITER = ": -";
+
+    public static final String QUANTITY_UNIT = "개";
+
+    public static final String MONEY_UNIT = "원";
+
+    public static final String XMAS_DDAY_DISCOUNT = "크리스마스 디데이 할인";
+    public static final String WEEKDAY_DISCOUNT = "평일 할인";
+    public static final String WEEKEND_DISCOUNT = "주말 할인";
+    public static final String SPECIAL_DISCOUNT = "특별 할인";
+    public static final String BONUS_EVENT = "증정 이벤트";
+
+
+    private IOMessage() {
+
+    }
+}

리뷰: 생성자를 `private`으로 막아두신 모습이 보기 좋습니다! 😊
@@ -0,0 +1,54 @@
+package christmas.controller;
+
+import christmas.domain.entity.Day;
+import christmas.domain.entity.Order;
+import christmas.view.InputView;
+import java.util.function.Supplier;
+
+import static christmas.domain.verifier.RuntimeVerifier.RUNTIME_VERIFIER;
+import static christmas.system.IOMessage.ORDER_PROMPT_MESSAGE;
+import static christmas.system.IOMessage.VISIT_DATE_PROMPT_MESSAGE;
+import static christmas.view.InputView.*;
+import static christmas.view.OutputView.*;
+
+public class PlannerSystem {
+
+    private final Day day;
+    private final Order order;
+    private final SettlementSystem settlementSystem;
+
+    public PlannerSystem() {
+        printMessage(VISIT_DATE_PROMPT_MESSAGE);
+        this.day = readDay();
+        printEventNotice();
+        printMessage(ORDER_PROMPT_MESSAGE);
+        this.order = readOrder(InputView::tryReadOrder);
+        this.settlementSystem = new SettlementSystem(day, order);
+    }
+    public void run() {
+        renderResult();
+    }
+
+    private Order readOrder(Supplier<Order> orderSupplier) {
+        while (true) {
+            try {
+                Order order = orderSupplier.get();
+                RUNTIME_VERIFIER.validate(order);
+                return order;
+            } catch (IllegalStateException e) {
+                printMessage(e.getMessage());
+            }
+        }
+    }
+
+    private void renderResult() {
+        renderPlannerResult();
+        settlementSystem.renderSettlementResult();
+
+    }
+
+    private void renderPlannerResult() {
+        printResultStartMessage(day);
+        printOrderList(order);
+    }
+}

리뷰: static이 아니게 구현해서 의존관계를 가지게 해야할까 고민해봤습니다. 확실히 의존성 주입이 필요한 관계이다 싶은거는 주입을 시켰는데 inputview와 outputview까지 시켜야하나 해서요. 시키는게 맞을까요?
@@ -0,0 +1,54 @@
+package christmas.controller;
+
+import christmas.domain.entity.Day;
+import christmas.domain.entity.Order;
+import christmas.view.InputView;
+import java.util.function.Supplier;
+
+import static christmas.domain.verifier.RuntimeVerifier.RUNTIME_VERIFIER;
+import static christmas.system.IOMessage.ORDER_PROMPT_MESSAGE;
+import static christmas.system.IOMessage.VISIT_DATE_PROMPT_MESSAGE;
+import static christmas.view.InputView.*;
+import static christmas.view.OutputView.*;
+
+public class PlannerSystem {
+
+    private final Day day;
+    private final Order order;
+    private final SettlementSystem settlementSystem;
+
+    public PlannerSystem() {
+        printMessage(VISIT_DATE_PROMPT_MESSAGE);
+        this.day = readDay();
+        printEventNotice();
+        printMessage(ORDER_PROMPT_MESSAGE);
+        this.order = readOrder(InputView::tryReadOrder);
+        this.settlementSystem = new SettlementSystem(day, order);
+    }
+    public void run() {
+        renderResult();
+    }
+
+    private Order readOrder(Supplier<Order> orderSupplier) {
+        while (true) {
+            try {
+                Order order = orderSupplier.get();
+                RUNTIME_VERIFIER.validate(order);
+                return order;
+            } catch (IllegalStateException e) {
+                printMessage(e.getMessage());
+            }
+        }
+    }
+
+    private void renderResult() {
+        renderPlannerResult();
+        settlementSystem.renderSettlementResult();
+
+    }
+
+    private void renderPlannerResult() {
+        printResultStartMessage(day);
+        printOrderList(order);
+    }
+}

리뷰: 헐 몰랐습니다. 감사합니다.!!
@@ -0,0 +1,32 @@
+package christmas.controller;
+
+import christmas.domain.entity.Day;
+import christmas.domain.entity.DiscountRecord;
+import christmas.domain.entity.Order;
+import christmas.domain.manager.BonusEventManager;
+import christmas.domain.manager.DiscountManager;
+
+import static christmas.domain.entity.EventBadge.createBadge;
+import static christmas.view.OutputView.*;
+
+public class SettlementSystem {
+
+    private final Order order;
+    private final DiscountRecord discountRecord;
+
+    public SettlementSystem(Day day, Order order) {
+        DiscountManager discountManager = new DiscountManager();
+        BonusEventManager bonusEventManager = new BonusEventManager();
+        this.order = order;
+        this.discountRecord = DiscountRecord.create(day, order, discountManager, bonusEventManager);
+    }
+
+    public void renderSettlementResult() {
+        printOriginalTotalAmount(order);
+        printBonusMenu(order);
+        printDiscountRecord(discountRecord);
+        printTotalDiscountAmount(discountRecord);
+        printExpectedPayment(order, discountRecord);
+        printEventBadge(createBadge(discountRecord));
+    }
+}

리뷰: 이게 여러가지로 나눠볼려고 했는데 너무 어렵더라구요... 나눠야 깔끔할거 같기는 한데...
그냥 저희가 plannerSystem을 구현하는거였고, 기능들이 다 정산(금융)과 관련된 부분이라서 settlementSystem을 두었습니다.
@@ -0,0 +1,76 @@
+package christmas.domain.entity;
+
+import static christmas.domain.verifier.VisitDateVerifier.VISIT_DATE_VERIFIER;
+import static christmas.system.Constant.CHRISTMAS;
+import static christmas.system.Constant.FIRST_DAY_OF_MONTH;
+
+public class Day {
+
+    private static final int WEEK_LENGTH = 7;
+    private final int day;
+
+    public Day(int day) {
+        VISIT_DATE_VERIFIER.validateInputInDomain(day);
+        this.day = day;
+    }
+
+    public int getDay() {
+        return day;
+    }
+
+    public boolean isChristmasSeason() {
+        if (day >= FIRST_DAY_OF_MONTH && day <= CHRISTMAS) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isWeekday() {
+        if (!(isFriday() || isSaturday())) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isWeekend() {
+        if (isFriday() || isSaturday()) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isSpecialDay() {
+        if (isSunday() || isChristmas()) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isFriday() {
+        if (day % WEEK_LENGTH == 1) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isSaturday() {
+        if (day % WEEK_LENGTH == 2) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isSunday() {
+        if (day % WEEK_LENGTH == 3) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isChristmas() {
+        if (day == CHRISTMAS) {
+            return true;
+        }
+        return false;
+    }
+}

리뷰: 메서드명을 정말 잘 지으신거 같아요! 😁
@@ -0,0 +1,48 @@
+package christmas.domain.entity;
+
+import christmas.domain.util.Util;
+
+import java.util.Arrays;
+
+import static christmas.system.IOMessage.EMPTY_STRING;
+import static christmas.system.IOMessage.QUANTITY_UNIT;
+
+public enum BonusMenu {
+    CHAMPAGNE(Menu.CHAMPAGNE, 1);
+
+    private final Menu menu;
+    private final int quantity;
+
+    BonusMenu(Menu menu, int quantity) {
+        this.menu = menu;
+        this.quantity = quantity;
+    }
+
+    public static int calculateTotalPriceForAllMenus() {
+        return Arrays.stream(BonusMenu.values())
+                .mapToInt(BonusMenu::getTotalPrice)
+                .sum();
+    }
+
+    public static String generateAllMenuDetails() {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (BonusMenu bonusMenu : BonusMenu.values()) {
+            stringBuilder.append(bonusMenu.toString()).append(System.lineSeparator());
+        }
+        return stringBuilder.toString();
+    }
+
+    @Override
+    public String toString() {
+        return getName() + EMPTY_STRING + Util.createFormattedAmount(quantity) + QUANTITY_UNIT;
+    }
+
+    private String getName() {
+        return menu.getMenuName();
+    }
+
+    private int getTotalPrice() {
+        return menu.getMenuPrice() * quantity;
+    }
+
+}

리뷰: 처음에는 그런 방식으로 했었는데,
각 클래스에서, 클래스에 대해 출력할 정보를 만드는거까지는 객체가 담당해야할 몫이지 않을까 해서 바꿨었어요...
출력은 outputview에서 합니다.  이 부분은 다른부분의 의견도 듣고 싶어요!! 
1. outputview에서 getter가 아니더라도, 인자를 통해 출력할 클래스의 정보를 꺼내서 출력 메시지를 만들고 출력까지 하는걸 담당해야할까?
2. 출력해야할 클래스의 정보는 클래스 딴에서 만들고, 출력만 outputview에서 해야하는게 맞을까요?
@@ -0,0 +1,12 @@
+package christmas.domain.util;
+
+
+import java.text.DecimalFormat;
+
+public final class Util {
+    public static String createFormattedAmount(int target) {
+        DecimalFormat formatter = new DecimalFormat("###,##0");
+        return formatter.format(target);
+    }
+
+}

리뷰: 참고하겠습니다. 너무너무 피드백 열심히 해주셔서 감사해요 예슬님 🙃
@@ -0,0 +1,76 @@
+package christmas.domain.entity;
+
+import static christmas.domain.verifier.VisitDateVerifier.VISIT_DATE_VERIFIER;
+import static christmas.system.Constant.CHRISTMAS;
+import static christmas.system.Constant.FIRST_DAY_OF_MONTH;
+
+public class Day {
+
+    private static final int WEEK_LENGTH = 7;
+    private final int day;
+
+    public Day(int day) {
+        VISIT_DATE_VERIFIER.validateInputInDomain(day);
+        this.day = day;
+    }
+
+    public int getDay() {
+        return day;
+    }
+
+    public boolean isChristmasSeason() {
+        if (day >= FIRST_DAY_OF_MONTH && day <= CHRISTMAS) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isWeekday() {
+        if (!(isFriday() || isSaturday())) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isWeekend() {
+        if (isFriday() || isSaturday()) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isSpecialDay() {
+        if (isSunday() || isChristmas()) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isFriday() {
+        if (day % WEEK_LENGTH == 1) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isSaturday() {
+        if (day % WEEK_LENGTH == 2) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isSunday() {
+        if (day % WEEK_LENGTH == 3) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isChristmas() {
+        if (day == CHRISTMAS) {
+            return true;
+        }
+        return false;
+    }
+}

리뷰: 개인적인 의견인데, `isFriday() || isSaturday()`가 `isWeekend()`메서드와 똑같으니, 이걸 활용하는게 어떨까요?

```java
public boolean isWeekday() {
  return !isWeekend();
}
```
이렇게요! 😉
@@ -0,0 +1,59 @@
+package christmas.domain.entity;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static christmas.domain.entity.MenuType.*;
+
+public enum Menu {
+
+    MUSHROOM_SOUP("양송이수프", 6_000, APPETIZER),
+    TAPAS("타파스", 5_500, APPETIZER),
+    CAESAR_SALAD("시저샐러드", 8_000, APPETIZER),
+
+    T_BONE_STEAK("티본스테이크", 55_000, MAIN),
+    BBQ_RIBS("바비큐립", 54_000, MAIN),
+    SEAFOOD_PASTA("해산물파스타", 35_000, MAIN),
+    CHRISTMAS_PASTA("크리스마스파스타", 25_000, MAIN),
+
+    CHOCOLATE_CAKE("초코케이크", 15_000, DESSERT),
+    ICE_CREAM("아이스크림", 5_000, DESSERT),
+
+    ZERO_COLA("제로콜라", 3_000, BEVERAGE),
+    RED_WINE("레드와인", 60_000, BEVERAGE),
+    CHAMPAGNE("샴페인", 25_000, BEVERAGE);
+
+    private static final Map<String, Menu> MENU_MAP = new HashMap<>();
+    private final String menuName;
+    private final int price;
+    private final MenuType menuType;
+
+    Menu(String menuName, int price, MenuType menuType) {
+        this.menuName = menuName;
+        this.price = price;
+        this.menuType = menuType;
+    }
+
+    static {
+        for (Menu menu : Menu.values()) {
+            MENU_MAP.put(menu.menuName, menu);
+        }
+    }
+
+    public static Menu getMenuItemByName(String menuName) {
+        return MENU_MAP.get(menuName);
+    }
+
+    public String getMenuName() {
+        return menuName;
+    }
+
+    public int getMenuPrice() {
+        return price;
+    }
+
+    public MenuType getMenuType() {
+        return menuType;
+    }
+
+}

리뷰: 따로 `HashMap`을 만들어 둔 이유가 궁금합니다! `getMenuItemByName`메서드에서 검색속도를 높이기 위함인가요?
@@ -0,0 +1,12 @@
+package christmas.domain.util;
+
+
+import java.text.DecimalFormat;
+
+public final class Util {
+    public static String createFormattedAmount(int target) {
+        DecimalFormat formatter = new DecimalFormat("###,##0");
+        return formatter.format(target);
+    }
+
+}

리뷰: split을 한 결과가 사이즈가 1이어서 `orderItemSpec[1]`의 접근이 `IndexOutOfBoundsException`을 일으킬 경우는 없나요? 이를 염두해두셨나면 어떻게 검증을 하셨는지 궁금합니다!
@@ -0,0 +1,96 @@
+package christmas.domain.verifier;
+
+
+import christmas.domain.entity.Menu;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static christmas.system.ExceptionMessage.*;
+
+public class OrderMenuVerifier implements Verifier<String> {
+
+    public static final OrderMenuVerifier ORDER_MENU_VERIFIER = new OrderMenuVerifier();
+
+    private final Pattern pattern;
+
+    private OrderMenuVerifier() {
+        this.pattern = Pattern.compile("[가-힣]+-\\d+(,[가-힣]+-\\d+)*");
+    }
+
+    @Override
+    public void validate(final String input) {
+        validateMenuFormat(input);
+    }
+
+    public void validateInputInDomain(final String input) {
+        validateMenuExistence(input);
+        validateDistinctMenu(input);
+        validateMenuQuantity(input);
+    }
+
+    private void validateMenuFormat(final String input) {
+        String[] orders = input.split(",");
+        for (String order : orders) {
+            validateOrderFormat(order);
+        }
+    }
+
+    private void validateMenuExistence(final String input) {
+        String[] orders = input.split(",");
+        for (String order : orders) {
+            validateOrderExistence(order);
+        }
+    }
+
+    private void validateDistinctMenu(final String input) {
+        Set<String> uniqueMenuItems = new HashSet<>();
+        String[] orders = input.split(",");
+        for (String order : orders) {
+            validateDistinctMenu(order, uniqueMenuItems);
+        }
+    }
+
+    private void validateMenuQuantity(final String input) {
+        String[] orders = input.split(",");
+        for (String order : orders) {
+            validateOrderQuantity(order);
+        }
+    }
+
+    private void validateOrderFormat(final String order) {
+        Matcher matcher = pattern.matcher(order);
+        if (!matcher.matches()) {
+            Verifier.throwIllegalArgumentError(INVALID_ORDER_MESSAGE);
+        }
+    }
+
+    private void validateOrderExistence(final String order) {
+        String[] orderInfo = order.split("-");
+        if (Menu.getMenuItemByName(orderInfo[0]) == null) {
+            Verifier.throwIllegalArgumentError(INVALID_ORDER_MESSAGE);
+        }
+    }
+
+    private void validateDistinctMenu(final String order, Set<String> uniqueMenuItems) {
+        String[] orderInfo = order.split("-");
+        if (!uniqueMenuItems.add(orderInfo[0])) {
+            Verifier.throwIllegalArgumentError(INVALID_ORDER_MESSAGE);
+        }
+    }
+
+    private void validateOrderQuantity(final String order) {
+        String[] orderInfo = order.split("-");
+        try {
+            int quantity = Integer.parseInt(orderInfo[1]);
+            if (quantity < 1) {
+                Verifier.throwIllegalArgumentError(INVALID_ORDER_MESSAGE);
+            }
+        } catch (NumberFormatException e) {
+            Verifier.throwIllegalArgumentError(INVALID_ORDER_MESSAGE);
+        }
+    }
+
+
+}

리뷰: 따로 인자에 따라서 패턴이 달라지는 것 같진 않은데, 필드에서 바로 초기화하지 않고, 생성자 내부에서 초기화하신 이유가 궁금합니다! 뭐가 더 좋은 방법인지 저도 잘 모르겠어요.. 😂
@@ -0,0 +1,14 @@
+package christmas.domain.verifier;
+
+public interface Verifier<T> {
+
+    abstract public void validate(T input);
+
+    static void throwIllegalArgumentError(String errorMessage) {
+        throw new IllegalArgumentException(errorMessage);
+    }
+
+    static void throwIllegalStateError(String errorMessage) {
+        throw new IllegalStateException(errorMessage);
+    }
+}

리뷰: 이 인터페이스를 구현한 클래스들은 `check`만 사용하면 필요한 검증이 다 되는 방식이네요! 깔끔하고 좋네요! 😊
@@ -0,0 +1,59 @@
+package christmas.domain.entity;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static christmas.domain.entity.MenuType.*;
+
+public enum Menu {
+
+    MUSHROOM_SOUP("양송이수프", 6_000, APPETIZER),
+    TAPAS("타파스", 5_500, APPETIZER),
+    CAESAR_SALAD("시저샐러드", 8_000, APPETIZER),
+
+    T_BONE_STEAK("티본스테이크", 55_000, MAIN),
+    BBQ_RIBS("바비큐립", 54_000, MAIN),
+    SEAFOOD_PASTA("해산물파스타", 35_000, MAIN),
+    CHRISTMAS_PASTA("크리스마스파스타", 25_000, MAIN),
+
+    CHOCOLATE_CAKE("초코케이크", 15_000, DESSERT),
+    ICE_CREAM("아이스크림", 5_000, DESSERT),
+
+    ZERO_COLA("제로콜라", 3_000, BEVERAGE),
+    RED_WINE("레드와인", 60_000, BEVERAGE),
+    CHAMPAGNE("샴페인", 25_000, BEVERAGE);
+
+    private static final Map<String, Menu> MENU_MAP = new HashMap<>();
+    private final String menuName;
+    private final int price;
+    private final MenuType menuType;
+
+    Menu(String menuName, int price, MenuType menuType) {
+        this.menuName = menuName;
+        this.price = price;
+        this.menuType = menuType;
+    }
+
+    static {
+        for (Menu menu : Menu.values()) {
+            MENU_MAP.put(menu.menuName, menu);
+        }
+    }
+
+    public static Menu getMenuItemByName(String menuName) {
+        return MENU_MAP.get(menuName);
+    }
+
+    public String getMenuName() {
+        return menuName;
+    }
+
+    public int getMenuPrice() {
+        return price;
+    }
+
+    public MenuType getMenuType() {
+        return menuType;
+    }
+
+}

리뷰: 네 맞아요! HashMap을 사용하면 검색속도가 O(1)에 가까운 속도로 매우 향상된다고 합니다.!!
@@ -0,0 +1,14 @@
+package christmas.domain.verifier;
+
+public interface Verifier<T> {
+
+    abstract public void validate(T input);
+
+    static void throwIllegalArgumentError(String errorMessage) {
+        throw new IllegalArgumentException(errorMessage);
+    }
+
+    static void throwIllegalStateError(String errorMessage) {
+        throw new IllegalStateException(errorMessage);
+    }
+}

리뷰: 피드백 정말 감사해요! 세웅님도 크리스마스 코드 리뷰 해드릴려고 하는데  repository가 private인가봐요😂