ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,31 @@
+package christmas.domain.menu;
+
+import christmas.domain.Money;
+import java.util.Collections;
+import java.util.Map;
+
+public record OrderRepository(Map<Menu, Integer> repository) {
+    public static OrderRepository createByString(String orderString) {
+        Map<Menu, Integer> orderRepository = OrderParser.parse(orderString);
+        return new OrderRepository(orderRepository);
+    }
+
+    public int findTotalCountByFoodType(FoodType foodType) {
+        return repository.keySet()
+                .stream()
+                .filter(menu -> menu.isSameType(foodType))
+                .map(repository::get)
+                .reduce(0, Integer::sum);
+    }
+
+    public Money calculateTotalPrice() {
+        return repository.keySet()
+                .stream()
+                .map((menu) -> menu.getPrice().multiply(repository.get(menu)))
+                .reduce(new Money(0), Money::sum);
+    }
+
+    public Map<Menu, Integer> repository() {
+        return Collections.unmodifiableMap(repository);
+    }
+}

리뷰: 귀찮은건 질색이니까요...!
```suggestion
                .mapToInt(repository::get)
                .sum();
```
@@ -0,0 +1,20 @@
+package christmas.domain.discount;
+
+import christmas.domain.menu.Menu;
+import christmas.domain.Money;
+
+public class GiftDiscount {
+    public static final String NAME = "증정 이벤트";
+    private static final Money MIN_PRESENTATION_MONEY = new Money(120000);
+
+    public static Money calculateDiscountAmount(Money totalPrize) {
+        if (totalPrize.isMoreOrEqualThan(MIN_PRESENTATION_MONEY)) {
+            return Menu.CHAMPAGNE.getPrice();
+        }
+        return new Money(0);
+    }
+
+    public static Menu getGift() {
+        return Menu.CHAMPAGNE;
+    }
+}

리뷰: 정말 사소한 가독성을 위한 팁입니다!
```suggestion
    private static final Money MIN_PRESENTATION_MONEY = new Money(120_000);
```
@@ -0,0 +1,41 @@
+package christmas.domain;
+
+import christmas.message.ExceptionMessage;
+import java.util.List;
+
+public record DecemberDate(int dateAmount) {
+    private static final List<Integer> WEEKEND_DATES = List.of(1, 2, 8, 9, 15, 16, 22, 23, 29, 30);
+    private static final int MINIMUM_DATE_AMOUNT = 1;
+    private static final int MAXIMUM_DATE_AMOUNT = 31;
+
+    public DecemberDate {
+        validateDate(dateAmount);
+    }
+
+    private void validateDate(int dateAmount) {
+        if (isOutOfDateRange(dateAmount)) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_DATE);
+        }
+    }
+
+    private boolean isOutOfDateRange(int dateAmount) {
+        return dateAmount < MINIMUM_DATE_AMOUNT || dateAmount > MAXIMUM_DATE_AMOUNT;
+    }
+
+    public boolean isLessThan(DecemberDate date) {
+        return dateAmount < date.dateAmount();
+    }
+
+    public boolean isMoreThan(DecemberDate date) {
+        return dateAmount > date.dateAmount();
+    }
+
+    public boolean isWeekend() {
+        return WEEKEND_DATES.contains(dateAmount);
+    }
+
+    public boolean isWeekday() {
+        return !isWeekend();
+    }
+
+}

리뷰: `DayOfWeek`를 통해 요일 정보를 가져온다면 코드가 조금 더 간결해 질 수 있을 것 같아요!
@@ -0,0 +1,27 @@
+package christmas;
+
+import christmas.domain.Money;
+import christmas.message.ExceptionMessage;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+public class MoneyTest {
+    @DisplayName("금액은 0원 이상인 경우 예외가 발생하지 않는다.")
+    @ParameterizedTest
+    @ValueSource(ints = {0, 10, 100, 1000, 999999, 1000000})
+    void moneySuccessTest(int amount) {
+        Assertions.assertThatNoException()
+                .isThrownBy(() -> new Money(amount));
+    }
+
+    @DisplayName("금액은 0원 미만인 경우 예외가 발생한다.")
+    @ParameterizedTest
+    @ValueSource(ints = {-10, -100, -1000, -999999, -1000000})
+    void moneyFailTest(int amount) {
+        Assertions.assertThatThrownBy(() -> new Money(amount))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessage(ExceptionMessage.INVALID_MONEY);
+    }
+}

리뷰: `@ParaneterizedTest`를 사용할때도 각각의 테스트 케이스 이름을 예쁘게 보여줄 수 있다는 사실, 알고 계셨나요?!
```suggestion
    @ParameterizedTest(name = "{0} 금액이 0원 미만이라면 예외가 발생한다.")
```
@@ -0,0 +1,33 @@
+package christmas.domain;
+
+public enum EventBadge {
+    SANTA("산타", new Money( 20000)),
+    TREE("트리", new Money( 10000)),
+    STAR("별", new Money(5000)),
+    NONE("없음", new Money(0));
+
+    private final String name;
+    private final Money price;
+
+    EventBadge(String name, Money price) {
+        this.name = name;
+        this.price = price;
+    }
+
+    public static EventBadge findByTotalDiscountPrice(Money totalDiscountMoney) {
+        if (totalDiscountMoney.isMoreOrEqualThan(SANTA.price)) {
+            return SANTA;
+        }
+        if (totalDiscountMoney.isMoreOrEqualThan(TREE.price)) {
+            return TREE;
+        }
+        if (totalDiscountMoney.isMoreOrEqualThan(STAR.price)) {
+            return STAR;
+        }
+        return NONE;
+    }
+
+    public String getName() {
+        return name;
+    }
+}

리뷰: @zangsu 아하 그런 관례가 있었군요! 감사합니다! ☺️
@@ -0,0 +1,55 @@
+package christmas.domain.menu;
+
+import christmas.message.ExceptionMessage;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.Map;
+
+public class OrderParser {
+    private static final int MAX_MENU_COUNT = 20;
+    private static final String DELIMITER_MENU_ORDER = ",";
+
+    private OrderParser() {
+        // 불필요한 인스턴스 생성 방지
+    }
+
+    public static Map<Menu, Integer> parse(String inputValue) {
+        Map<Menu, Integer> orderRepository = new EnumMap<>(Menu.class);
+        Arrays.stream(inputValue.split(DELIMITER_MENU_ORDER))
+                        .forEach(menuString -> addMenuToOrderRepository(orderRepository, menuString));
+        validateOnlyDrink(orderRepository);
+        validateMaxMenuCount(orderRepository);
+        return orderRepository;
+    }
+
+    private static void addMenuToOrderRepository(Map<Menu, Integer> orderRepository, String menuString) {
+        Order order = Order.createByString(menuString);
+        validateDuplicateMenu(orderRepository, order.menu());
+        orderRepository.put(order.menu(), order.count());
+    }
+
+    private static void validateDuplicateMenu(Map<Menu, Integer> result, Menu menu) {
+        if (result.containsKey(menu)) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+        }
+    }
+
+    private static void validateOnlyDrink(Map<Menu, Integer> result) {
+        int drinkMenuCount = (int) result.keySet()
+                .stream()
+                .filter(menu -> menu.isSameType(FoodType.DRINK))
+                .count();
+        if (drinkMenuCount == result.size()) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+        }
+    }
+
+    private static void validateMaxMenuCount(Map<Menu, Integer> result) {
+        Integer totalMenuCount = result.values()
+                .stream()
+                .reduce(0, Integer::sum);
+        if (totalMenuCount > MAX_MENU_COUNT) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+        }
+    }
+}

리뷰: @zangsu `allMatch` 를 활용하면 되군요! 감사합니다! 아직 스트림에 대해선 배울게 많은것 같네요! ㅎㅎ
@@ -0,0 +1,41 @@
+package christmas.domain;
+
+import christmas.message.ExceptionMessage;
+import java.util.List;
+
+public record DecemberDate(int dateAmount) {
+    private static final List<Integer> WEEKEND_DATES = List.of(1, 2, 8, 9, 15, 16, 22, 23, 29, 30);
+    private static final int MINIMUM_DATE_AMOUNT = 1;
+    private static final int MAXIMUM_DATE_AMOUNT = 31;
+
+    public DecemberDate {
+        validateDate(dateAmount);
+    }
+
+    private void validateDate(int dateAmount) {
+        if (isOutOfDateRange(dateAmount)) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_DATE);
+        }
+    }
+
+    private boolean isOutOfDateRange(int dateAmount) {
+        return dateAmount < MINIMUM_DATE_AMOUNT || dateAmount > MAXIMUM_DATE_AMOUNT;
+    }
+
+    public boolean isLessThan(DecemberDate date) {
+        return dateAmount < date.dateAmount();
+    }
+
+    public boolean isMoreThan(DecemberDate date) {
+        return dateAmount > date.dateAmount();
+    }
+
+    public boolean isWeekend() {
+        return WEEKEND_DATES.contains(dateAmount);
+    }
+
+    public boolean isWeekday() {
+        return !isWeekend();
+    }
+
+}

리뷰: 나름 고민했던 부분이였는데 역시 피드백 해주셨네요! ㅎㅎ 감사합니다!
@@ -0,0 +1,27 @@
+package christmas;
+
+import christmas.domain.Money;
+import christmas.message.ExceptionMessage;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+public class MoneyTest {
+    @DisplayName("금액은 0원 이상인 경우 예외가 발생하지 않는다.")
+    @ParameterizedTest
+    @ValueSource(ints = {0, 10, 100, 1000, 999999, 1000000})
+    void moneySuccessTest(int amount) {
+        Assertions.assertThatNoException()
+                .isThrownBy(() -> new Money(amount));
+    }
+
+    @DisplayName("금액은 0원 미만인 경우 예외가 발생한다.")
+    @ParameterizedTest
+    @ValueSource(ints = {-10, -100, -1000, -999999, -1000000})
+    void moneyFailTest(int amount) {
+        Assertions.assertThatThrownBy(() -> new Money(amount))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessage(ExceptionMessage.INVALID_MONEY);
+    }
+}

리뷰: 와,, 이런 기능도 있었군요! 감사합니다! ㅎㅎ
@@ -0,0 +1,33 @@
+package christmas.domain;
+
+public enum EventBadge {
+    SANTA("산타", new Money( 20000)),
+    TREE("트리", new Money( 10000)),
+    STAR("별", new Money(5000)),
+    NONE("없음", new Money(0));
+
+    private final String name;
+    private final Money price;
+
+    EventBadge(String name, Money price) {
+        this.name = name;
+        this.price = price;
+    }
+
+    public static EventBadge findByTotalDiscountPrice(Money totalDiscountMoney) {
+        if (totalDiscountMoney.isMoreOrEqualThan(SANTA.price)) {
+            return SANTA;
+        }
+        if (totalDiscountMoney.isMoreOrEqualThan(TREE.price)) {
+            return TREE;
+        }
+        if (totalDiscountMoney.isMoreOrEqualThan(STAR.price)) {
+            return STAR;
+        }
+        return NONE;
+    }
+
+    public String getName() {
+        return name;
+    }
+}

리뷰: enum안에 객체를 넣고 싶었는데 방법이 있었군요 배워갑니다!
@@ -0,0 +1,41 @@
+package christmas.domain;
+
+import christmas.message.ExceptionMessage;
+import java.util.List;
+
+public record DecemberDate(int dateAmount) {
+    private static final List<Integer> WEEKEND_DATES = List.of(1, 2, 8, 9, 15, 16, 22, 23, 29, 30);
+    private static final int MINIMUM_DATE_AMOUNT = 1;
+    private static final int MAXIMUM_DATE_AMOUNT = 31;
+
+    public DecemberDate {
+        validateDate(dateAmount);
+    }
+
+    private void validateDate(int dateAmount) {
+        if (isOutOfDateRange(dateAmount)) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_DATE);
+        }
+    }
+
+    private boolean isOutOfDateRange(int dateAmount) {
+        return dateAmount < MINIMUM_DATE_AMOUNT || dateAmount > MAXIMUM_DATE_AMOUNT;
+    }
+
+    public boolean isLessThan(DecemberDate date) {
+        return dateAmount < date.dateAmount();
+    }
+
+    public boolean isMoreThan(DecemberDate date) {
+        return dateAmount > date.dateAmount();
+    }
+
+    public boolean isWeekend() {
+        return WEEKEND_DATES.contains(dateAmount);
+    }
+
+    public boolean isWeekday() {
+        return !isWeekend();
+    }
+
+}

리뷰: 7로 나눈 나머지가 1,2인점을 이용해서 구하는 방법은 별로일까요! 그렇게 하면 상수가 필요없어질것같아요!
@@ -0,0 +1,59 @@
+package christmas.domain;
+
+import christmas.domain.discount.DiscountRepository;
+import christmas.domain.discount.GiftDiscount;
+import christmas.domain.menu.Menu;
+import christmas.domain.menu.OrderRepository;
+
+public class Reservation {
+    private final DiscountRepository discountRepository;
+    private final DecemberDate decemberDate;
+    private final OrderRepository orderRepository;
+
+    private Reservation(DecemberDate decemberDate, OrderRepository orderRepository) {
+        this.decemberDate = decemberDate;
+        this.orderRepository = orderRepository;
+        this.discountRepository = DiscountRepository.of(decemberDate, orderRepository);
+    }
+
+    public static Reservation of(DecemberDate decemberDate, OrderRepository menus) {
+        return new Reservation(decemberDate, menus);
+    }
+
+    public Menu calculateGift() {
+        return discountRepository.calculateGift();
+    }
+
+    public Money calculateTotalOriginalMoney() {
+        return orderRepository.calculateTotalPrice();
+    }
+
+    public Money calculateTotalDiscountMoney() {
+        return discountRepository.calculateTotalDiscountMoney();
+    }
+
+    public Money calculateTotalFinalMoney() {
+        Money discountMoney = calculateTotalDiscountMoney();
+        if (discountRepository.hasGiftDiscount()) {
+            discountMoney = discountMoney.minus(GiftDiscount.getGift().getPrice());
+        }
+        return calculateTotalOriginalMoney().minus(discountMoney);
+    }
+
+    public EventBadge calculateEventBadge() {
+        Money totalDiscountMoney = calculateTotalDiscountMoney();
+        return EventBadge.findByTotalDiscountPrice(totalDiscountMoney);
+    }
+
+    public DiscountRepository getDiscountRepository() {
+        return discountRepository;
+    }
+
+    public DecemberDate getDecemberDate() {
+        return decemberDate;
+    }
+
+    public OrderRepository getOrderRepository() {
+        return orderRepository;
+    }
+}

리뷰: 클래스 이름을 지을때 Repository라는 단어가 가지는 관례적인 국룰(?)이 있어서 해당 단어를 쓰신건가요? 아니면 개인적인 생각에서 지으신건가요! (순수 궁금증입니다!)
@@ -0,0 +1,59 @@
+package christmas.domain;
+
+import christmas.domain.discount.DiscountRepository;
+import christmas.domain.discount.GiftDiscount;
+import christmas.domain.menu.Menu;
+import christmas.domain.menu.OrderRepository;
+
+public class Reservation {
+    private final DiscountRepository discountRepository;
+    private final DecemberDate decemberDate;
+    private final OrderRepository orderRepository;
+
+    private Reservation(DecemberDate decemberDate, OrderRepository orderRepository) {
+        this.decemberDate = decemberDate;
+        this.orderRepository = orderRepository;
+        this.discountRepository = DiscountRepository.of(decemberDate, orderRepository);
+    }
+
+    public static Reservation of(DecemberDate decemberDate, OrderRepository menus) {
+        return new Reservation(decemberDate, menus);
+    }
+
+    public Menu calculateGift() {
+        return discountRepository.calculateGift();
+    }
+
+    public Money calculateTotalOriginalMoney() {
+        return orderRepository.calculateTotalPrice();
+    }
+
+    public Money calculateTotalDiscountMoney() {
+        return discountRepository.calculateTotalDiscountMoney();
+    }
+
+    public Money calculateTotalFinalMoney() {
+        Money discountMoney = calculateTotalDiscountMoney();
+        if (discountRepository.hasGiftDiscount()) {
+            discountMoney = discountMoney.minus(GiftDiscount.getGift().getPrice());
+        }
+        return calculateTotalOriginalMoney().minus(discountMoney);
+    }
+
+    public EventBadge calculateEventBadge() {
+        Money totalDiscountMoney = calculateTotalDiscountMoney();
+        return EventBadge.findByTotalDiscountPrice(totalDiscountMoney);
+    }
+
+    public DiscountRepository getDiscountRepository() {
+        return discountRepository;
+    }
+
+    public DecemberDate getDecemberDate() {
+        return decemberDate;
+    }
+
+    public OrderRepository getOrderRepository() {
+        return orderRepository;
+    }
+}

리뷰: 분리가 잘되서 그런가 할인 날짜 주문을 한곳에 넣어도 가독성이 매우 깔끔하네요,, 감탄하고갑니다
@@ -0,0 +1,45 @@
+package christmas.domain.menu;
+
+import christmas.message.ExceptionMessage;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public record Order(Menu menu, int count) {
+    private static final String FORMAT_MENU_ORDER = "([가-힣]+)-(\\d+)";
+    private static final Pattern PATTERN_MENU = Pattern.compile(FORMAT_MENU_ORDER);
+    private static final int NAME_INDEX = 1;
+    private static final int COUNT_INDEX = 2;
+
+    public Order {
+        validateNotNull(menu);
+        validateCount(count);
+    }
+
+    public static Order createByString(String menuString) {
+        Matcher matcher = PATTERN_MENU.matcher(menuString);
+        validateFormat(matcher);
+        Menu menu = Menu.findByName(matcher.group(NAME_INDEX));
+        int count = Integer.parseInt(matcher.group(COUNT_INDEX));
+        return new Order(menu, count);
+    }
+
+    private static void validateFormat(Matcher matcher) {
+        if (matcher.matches()) {
+            return;
+        }
+        throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+    }
+
+    private static void validateNotNull(Menu menu) {
+        if (Objects.isNull(menu)) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+        }
+    }
+
+    private static void validateCount(int count) {
+        if (count <= 0) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+        }
+    }
+}

리뷰: 상수와 Matcher를 통해 정규식을 간단하게 표현한게 인상깊어요 !
@@ -0,0 +1,45 @@
+package christmas.domain.menu;
+
+import christmas.message.ExceptionMessage;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public record Order(Menu menu, int count) {
+    private static final String FORMAT_MENU_ORDER = "([가-힣]+)-(\\d+)";
+    private static final Pattern PATTERN_MENU = Pattern.compile(FORMAT_MENU_ORDER);
+    private static final int NAME_INDEX = 1;
+    private static final int COUNT_INDEX = 2;
+
+    public Order {
+        validateNotNull(menu);
+        validateCount(count);
+    }
+
+    public static Order createByString(String menuString) {
+        Matcher matcher = PATTERN_MENU.matcher(menuString);
+        validateFormat(matcher);
+        Menu menu = Menu.findByName(matcher.group(NAME_INDEX));
+        int count = Integer.parseInt(matcher.group(COUNT_INDEX));
+        return new Order(menu, count);
+    }
+
+    private static void validateFormat(Matcher matcher) {
+        if (matcher.matches()) {
+            return;
+        }
+        throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+    }
+
+    private static void validateNotNull(Menu menu) {
+        if (Objects.isNull(menu)) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+        }
+    }
+
+    private static void validateCount(int count) {
+        if (count <= 0) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+        }
+    }
+}

리뷰: 원래 Matcher와 Pattern으로 정규식을 관리하는게 정석인가요? 이런방법이 있었는지 처음알았습니다! 굉장히 깔끔한것같아요
@@ -0,0 +1,41 @@
+package christmas.domain;
+
+import christmas.message.ExceptionMessage;
+import java.util.List;
+
+public record DecemberDate(int dateAmount) {
+    private static final List<Integer> WEEKEND_DATES = List.of(1, 2, 8, 9, 15, 16, 22, 23, 29, 30);
+    private static final int MINIMUM_DATE_AMOUNT = 1;
+    private static final int MAXIMUM_DATE_AMOUNT = 31;
+
+    public DecemberDate {
+        validateDate(dateAmount);
+    }
+
+    private void validateDate(int dateAmount) {
+        if (isOutOfDateRange(dateAmount)) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_DATE);
+        }
+    }
+
+    private boolean isOutOfDateRange(int dateAmount) {
+        return dateAmount < MINIMUM_DATE_AMOUNT || dateAmount > MAXIMUM_DATE_AMOUNT;
+    }
+
+    public boolean isLessThan(DecemberDate date) {
+        return dateAmount < date.dateAmount();
+    }
+
+    public boolean isMoreThan(DecemberDate date) {
+        return dateAmount > date.dateAmount();
+    }
+
+    public boolean isWeekend() {
+        return WEEKEND_DATES.contains(dateAmount);
+    }
+
+    public boolean isWeekday() {
+        return !isWeekend();
+    }
+
+}

리뷰: 아하 그런 방법도 있군요! 배워갑니다!👍
@@ -0,0 +1,59 @@
+package christmas.domain;
+
+import christmas.domain.discount.DiscountRepository;
+import christmas.domain.discount.GiftDiscount;
+import christmas.domain.menu.Menu;
+import christmas.domain.menu.OrderRepository;
+
+public class Reservation {
+    private final DiscountRepository discountRepository;
+    private final DecemberDate decemberDate;
+    private final OrderRepository orderRepository;
+
+    private Reservation(DecemberDate decemberDate, OrderRepository orderRepository) {
+        this.decemberDate = decemberDate;
+        this.orderRepository = orderRepository;
+        this.discountRepository = DiscountRepository.of(decemberDate, orderRepository);
+    }
+
+    public static Reservation of(DecemberDate decemberDate, OrderRepository menus) {
+        return new Reservation(decemberDate, menus);
+    }
+
+    public Menu calculateGift() {
+        return discountRepository.calculateGift();
+    }
+
+    public Money calculateTotalOriginalMoney() {
+        return orderRepository.calculateTotalPrice();
+    }
+
+    public Money calculateTotalDiscountMoney() {
+        return discountRepository.calculateTotalDiscountMoney();
+    }
+
+    public Money calculateTotalFinalMoney() {
+        Money discountMoney = calculateTotalDiscountMoney();
+        if (discountRepository.hasGiftDiscount()) {
+            discountMoney = discountMoney.minus(GiftDiscount.getGift().getPrice());
+        }
+        return calculateTotalOriginalMoney().minus(discountMoney);
+    }
+
+    public EventBadge calculateEventBadge() {
+        Money totalDiscountMoney = calculateTotalDiscountMoney();
+        return EventBadge.findByTotalDiscountPrice(totalDiscountMoney);
+    }
+
+    public DiscountRepository getDiscountRepository() {
+        return discountRepository;
+    }
+
+    public DecemberDate getDecemberDate() {
+        return decemberDate;
+    }
+
+    public OrderRepository getOrderRepository() {
+        return orderRepository;
+    }
+}

리뷰: 관례가 있는지는 모르겠는데 대부분들 Repository 라고 하더라고요! 특정 규칙이 있는지는 저도 잘 모르겠네요! 😂
@@ -0,0 +1,45 @@
+package christmas.domain.menu;
+
+import christmas.message.ExceptionMessage;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public record Order(Menu menu, int count) {
+    private static final String FORMAT_MENU_ORDER = "([가-힣]+)-(\\d+)";
+    private static final Pattern PATTERN_MENU = Pattern.compile(FORMAT_MENU_ORDER);
+    private static final int NAME_INDEX = 1;
+    private static final int COUNT_INDEX = 2;
+
+    public Order {
+        validateNotNull(menu);
+        validateCount(count);
+    }
+
+    public static Order createByString(String menuString) {
+        Matcher matcher = PATTERN_MENU.matcher(menuString);
+        validateFormat(matcher);
+        Menu menu = Menu.findByName(matcher.group(NAME_INDEX));
+        int count = Integer.parseInt(matcher.group(COUNT_INDEX));
+        return new Order(menu, count);
+    }
+
+    private static void validateFormat(Matcher matcher) {
+        if (matcher.matches()) {
+            return;
+        }
+        throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+    }
+
+    private static void validateNotNull(Menu menu) {
+        if (Objects.isNull(menu)) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+        }
+    }
+
+    private static void validateCount(int count) {
+        if (count <= 0) {
+            throw new IllegalArgumentException(ExceptionMessage.INVALID_ORDER);
+        }
+    }
+}

리뷰: 다른분들은 정규표현식을 어떻게 사용하는지 잘 모르겠는데 저는 이러한 방식대로 사용합니다! ㅎㅎ