ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,39 @@
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class RacingGame {
+    private List<String> winnernames = new ArrayList<>();
+
+    public void race(List<Car> cars) {
+        for(Car car: cars) {
+            goOrStay(car);
+        }
+    }
+
+    private void goOrStay(Car car) {
+        if(Rule.isGoForward()) {
+            car.goForward();
+        }
+    }
+
+    public List<String> getWinner(List<Car> cars) {
+        int positionOfWinner = findPositionOfWinner(cars);
+        cars = cars.stream().filter(car -> (car.getPosition() == positionOfWinner)).collect(Collectors.toList());
+        for (Car car : cars) {
+            this.winnernames.add(car.getName());
+        }
+        return winnernames;
+    }
+
+    private int findPositionOfWinner(List<Car> cars) {
+        List<Integer> position = new ArrayList<>();
+        int positionOfWinner;
+        for(Car car: cars) {
+            position.add(car.getPosition());
+        }
+        positionOfWinner = Collections.max(position);
+        return positionOfWinner;
+    }
+}
\ No newline at end of file

리뷰: 전체적으로 테스트 코드가 없어서 아쉽네요 ㅠㅠ
@@ -0,0 +1,21 @@
+public class Car {
+    private String name;
+    private int position;
+
+    Car(String name) {
+        this.name = name;
+        this.position = 0;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPosition() {
+        return position;
+    }
+
+    public void goForward() {
+        this.position++;
+    }
+}

리뷰: 불필요한 setter/getter는 객체의 속성을 언제든 변경할 수 있는 상태가 되기 때문에 지양하도록 하는 것 같습니다! 굳이 사용하지 않아도 된다면 반영해보도록 하겠습니다!
@@ -0,0 +1,21 @@
+public class Car {
+    private String name;
+    private int position;
+
+    Car(String name) {
+        this.name = name;
+        this.position = 0;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPosition() {
+        return position;
+    }
+
+    public void goForward() {
+        this.position++;
+    }
+}

리뷰: 게임의 룰을 자동차 모델 클래스가 가지고 있을 필요는 없다고 생각했는데 보다 더 좋은 방법을 아직 생각해보지 못한 것 같습니다. 원래는 Rule 클래스를 따로 만들어 구현하려고 했으나 아직 방법을 고민 중에 있습니다! 고민해서 반영할 수 있도록 노력해보겠습니다
@@ -0,0 +1,21 @@
+public class Car {
+    private String name;
+    private int position;
+
+    Car(String name) {
+        this.name = name;
+        this.position = 0;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPosition() {
+        return position;
+    }
+
+    public void goForward() {
+        this.position++;
+    }
+}

리뷰: 넵 code formatting 하는 습관을 들이겠습니다!
@@ -0,0 +1,21 @@
+public class Car {
+    private String name;
+    private int position;
+
+    Car(String name) {
+        this.name = name;
+        this.position = 0;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPosition() {
+        return position;
+    }
+
+    public void goForward() {
+        this.position++;
+    }
+}

리뷰: magic number 역시 추후에 봤을 때 이해할 수 있도록 상수로 선언하는 습관을 들이겠습니다!
@@ -0,0 +1,68 @@
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Scanner;
+import java.util.stream.Stream;
+
+public class InputView {
+    private static final int MAX_LENGTH = 6;
+    private static final Scanner scanner = new Scanner(System.in);
+
+    public static List<Car> inputCarName() {
+        String name = scanner.nextLine();
+        String[] splittedInputCarName = splitInputCarName(name);
+        String[] trimmedInputCarName = trimInputCarName(splittedInputCarName);
+
+        try {
+            processStreamAboutCheckName(trimmedInputCarName);
+        } catch(IllegalArgumentException e) {
+            System.out.println(e.getMessage());
+            inputCarName();
+        }
+
+        List<Car> cars = new ArrayList<>();
+        for(int i = 0; i< splittedInputCarName.length; i++) {
+            cars.add(new Car(trimmedInputCarName[i]));
+        }
+        return cars;
+    }
+
+    private static String[] splitInputCarName(String name) {
+        return name.split(",");
+    }
+
+    private static String[] trimInputCarName(String[] name) {
+        for(int i = 0; i<name.length; i++) {
+            name[i] = name[i].trim();
+        }
+        return name;
+    }
+
+    private static void checkNameLength(String name) {
+        if(name.length() >= MAX_LENGTH) {
+            throw new IllegalArgumentException("이름은 5자 이하만 가능합니다.");
+        }
+    }
+
+    private static void processStreamAboutCheckName(String[] trimmedInputCarName) {
+        Stream<String> stream = Arrays.stream(trimmedInputCarName);
+        stream.forEach(e -> checkNameLength(e));
+    }
+
+    public static int inputTrial() {
+        return scanner.nextInt();
+    }
+
+    public static void inputCarNamesMessage() {
+        System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
+    }
+
+    public static void inputCountMessage() {
+        System.out.println("시도할 횟수는 몇회인가요?");
+    }
+}
+
+
+
+
+

리뷰: 메서드 체이닝을 적용해서 Arrays.stream(trimmedInputCarName).forEach(~~)
로 이어 붙이시면 어떨까요
@@ -0,0 +1,12 @@
+import java.util.ArrayList;
+
+public class Main {
+    public static void main(String[] args) {
+        RacingGame racing = new RacingGame();
+        ArrayList<Car> cars = new ArrayList<>();
+        cars = racing.registerCarNames(cars, racing.nameSet(InputView.setNames()));
+        int number = InputView.inputNumber();
+        ResultView result = new ResultView();
+        result.resultRacing(number, cars);
+    }
+}

리뷰: 조슈아 블로크의 effective java 에는 '객체는 인터페이스를 사용해 참조하라.'
라는 부분이 있습니다.
한번 읽어보시고 개선해보시면 좋을 것 같아요 ~
jaehun2841.github.io/2019/03/01/effective-java-item64/#%EC%9C%A0%EC%97%B0%ED%95%9C-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-%EC%83%9D%EC%84%B1%ED%95%98%EB%8A%94-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%ED%83%80%EC%9E%85-%EB%B3%80%EC%88%98
@@ -0,0 +1,39 @@
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+
+public class RacingGameTest {
+    RacingGame r;
+    ResultView v;
+
+    @Before
+    public void setUp() {
+        r = new RacingGame();
+        v = new ResultView();
+    }
+
+    @Test
+    public void carNamesInputTest() {
+        String input = "아송, 윈도우, 구름, 그리즈, 키캣";
+        assertEquals("아송 윈도우 구름 그리즈 키캣", r.getInputNames(input));
+    }
+
+    @Test
+    public void winnerTest() {
+        ArrayList<Car> cars = new ArrayList<>();
+        String input = "아송, 윈도우, 구름, 그리즈, 키캣";
+        int number = 1;
+        int[] randomNumbers = {1, 3, 5, 8, 2};
+        cars = r.registerCarNames(cars, r.nameSet(input));
+        assertEquals(" 구름  그리즈 ", r.getWinner(cars, randomNumbers));
+    }
+
+    @After
+    public void tearDown() {
+        r = null;
+    }
+}
\ No newline at end of file

리뷰: 스터디 규칙 : 변수명을 줄여쓰지 않는다
@@ -0,0 +1,40 @@
+import java.util.ArrayList;
+
+public class ResultView {
+    public static void resultRacing(int number, ArrayList<Car> cars) {
+        System.out.println("실행 결과");
+        for (int i = 0; i < number; i++) {
+            RacingGame.randomToNumber(cars);
+            resultRacing(cars);
+            System.out.println("");
+        }
+        ArrayList<String> winners = RacingGame.findWinner(cars);
+        finalResultView(winners);
+    }
+
+    public static void resultRacing(ArrayList<Car> cars) {
+        for (int i = 0; i < cars.size(); i++) {
+            System.out.println(cars.get(i).getName() + ":" + racingView(cars.get(i).getPosition()));
+        }
+    }
+
+    public static String racingView(int n) {
+        String car = "";
+        for (int i = 0; i < n; i++) {
+            car += "-";
+        }
+        return car;
+    }
+
+    public static void finalResultView(ArrayList<String> winners) {
+        if (winners.size() == 1) {
+            System.out.println(winners.get(0) + "가 최종 우승했습니다.");
+        }
+        if (winners.size() > 1) {
+            for (int i = 0; i < winners.size() - 1; i++) {
+                System.out.print(winners.get(i) + ",");
+            }
+            System.out.println(winners.get(winners.size() - 1) + "가 최종 우승했습니다.");
+        }
+    }
+}

리뷰: ResultView 는 어플리케이션의 흐름이나 로직을 알 필요 없이 그냥 들어온 input 에 대해서 출력만 해주는 정도의 역할을 하도록 변경해보면 어떨까요?
@@ -5,6 +5,7 @@
 import com.project.Project.domain.interaction.ReviewLike;
 import com.project.Project.domain.member.Member;
 import com.project.Project.domain.member.RecentMapLocation;
+import com.project.Project.domain.review.Review;
 
 import java.util.List;
 import java.util.Optional;
@@ -21,4 +22,9 @@ public interface MemberService {
     public List<ReviewLike> getReviewLikeList(Member member);
 
     Long delete(Member member);
+
+
+
+
+
 }

리뷰: 이 메소드를 ReviewService로 옮기면 좋을 것 같습니다!
가만보니 이전에 작성했던 위의 getReviewLikeList도 잘못 위치해 있는 것 같네요
@@ -7,6 +7,7 @@
 import com.project.Project.domain.interaction.ReviewLike;
 import com.project.Project.domain.member.Member;
 import com.project.Project.domain.member.RecentMapLocation;
+import com.project.Project.domain.review.Review;
 import com.project.Project.repository.interaction.FavoriteRepository;
 import com.project.Project.repository.interaction.ReviewLikeRepository;
 import com.project.Project.repository.member.MemberCustomRepository;
@@ -79,4 +80,6 @@ public Integer getReviewCnt(Member member) {
     public List<ReviewLike> getReviewLikeList(Member member) {
         return reviewLikeRepository.findByReviewLikeStatusAndMember(ReviewLikeStatus.LIKED, member);
     }
+
+
 }

리뷰: 마찬가지로 ReviewServiceImpl쪽으로 옮기면 좋을 것 같습니다!
@@ -2,6 +2,7 @@
 
 import com.project.Project.domain.member.Member;
 import com.project.Project.domain.review.Review;
+import com.querydsl.core.types.dsl.BooleanExpression;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.EntityGraph;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -40,4 +41,6 @@ public interface ReviewRepository extends JpaRepository<Review, Long> {
 
     @Query("select review from Review review where review.author.id = :memberId and review.id = :reviewId")
     Optional<Review> findReviewByAuthorAndReview(Long memberId, Long reviewId);
+
+    List<Review> findReviewsByAuthor(Member member);
 }

리뷰: 이 메소드는 deleted 필드 제외하는 것 반영하시면 될 것 같습니다!
@@ -3,21 +3,17 @@
 <mapper namespace="com.midnear.midnearshopping.mapper.coupon_point.PointMapper">
     <insert id="grantPoints" useGeneratedKeys="true" keyProperty="pointId">
         INSERT INTO point (
-        amount, reason
+        amount, reason, review_id, user_id, grant_date
         ) VALUES (
-        #{amount}, #{reason}
+        #{amount}, #{reason}, #{reviewId}, #{userId}, NOW()
         )
     </insert>
-    <insert id="setReviewPointAmount">
-        INSERT INTO review_point (
-        text_review, photo_review
-        ) VALUES (
-        #{textReview}, #{photoReview}
-        )
-    </insert>
-    <delete id="deletePreviousData">
-        delete from review_point
-    </delete>
+    <select id="getProductInfoByReviewId" resultType="java.lang.String">
+        select concat(op.product_name, ' _ ', op.color)
+        from reviews r
+        join order_products op on r.order_product_id = op.order_product_id
+        where review_id = #{reviewId}
+    </select>
 <!--얘는 파일 따로 뺴기 애매해서 여기에 넣음-->
     <select id="getPointList">
         select

리뷰: 감사합니다..
@@ -0,0 +1,40 @@
+package com.mybox.domain.storage;
+
+import com.mybox.domain.common.BaseTimeEntity;
+import java.time.LocalDateTime;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import lombok.Getter;
+import org.springframework.data.annotation.LastModifiedDate;
+
+@Getter
+@Entity
+public class StorageObjectMetaData extends BaseTimeEntity {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    private String name;
+    private StorageObjectType type;
+    private String extension;
+    private Long size;
+    private String path;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "namespace_id")
+    private Namespace namespace;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "parent_id")
+    private StorageObjectMetaData parentDirectory;
+
+    @LastModifiedDate
+    private LocalDateTime lastModifiedAt;
+
+}

리뷰: `@Enumerated` 붙여주실꺼죠? 😎
@@ -0,0 +1,40 @@
+package com.mybox.domain.storage;
+
+import com.mybox.domain.common.BaseTimeEntity;
+import java.time.LocalDateTime;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import lombok.Getter;
+import org.springframework.data.annotation.LastModifiedDate;
+
+@Getter
+@Entity
+public class StorageObjectMetaData extends BaseTimeEntity {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    private String name;
+    private StorageObjectType type;
+    private String extension;
+    private Long size;
+    private String path;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "namespace_id")
+    private Namespace namespace;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "parent_id")
+    private StorageObjectMetaData parentDirectory;
+
+    @LastModifiedDate
+    private LocalDateTime lastModifiedAt;
+
+}

리뷰: 이걸 놓쳤네요;;ㅎㅎ
@@ -0,0 +1,40 @@
+package com.mybox.domain.storage;
+
+import com.mybox.domain.common.BaseTimeEntity;
+import java.time.LocalDateTime;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import lombok.Getter;
+import org.springframework.data.annotation.LastModifiedDate;
+
+@Getter
+@Entity
+public class StorageObjectMetaData extends BaseTimeEntity {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    private String name;
+    private StorageObjectType type;
+    private String extension;
+    private Long size;
+    private String path;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "namespace_id")
+    private Namespace namespace;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "parent_id")
+    private StorageObjectMetaData parentDirectory;
+
+    @LastModifiedDate
+    private LocalDateTime lastModifiedAt;
+
+}

리뷰: 겨우 하나 찾았습니다🐙
@@ -0,0 +1,40 @@
+package com.mybox.domain.storage;
+
+import com.mybox.domain.common.BaseTimeEntity;
+import java.time.LocalDateTime;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import lombok.Getter;
+import org.springframework.data.annotation.LastModifiedDate;
+
+@Getter
+@Entity
+public class StorageObjectMetaData extends BaseTimeEntity {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    private String name;
+    private StorageObjectType type;
+    private String extension;
+    private Long size;
+    private String path;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "namespace_id")
+    private Namespace namespace;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "parent_id")
+    private StorageObjectMetaData parentDirectory;
+
+    @LastModifiedDate
+    private LocalDateTime lastModifiedAt;
+
+}

리뷰: extension은 어떤 변수 인가요..?! 저도 폴더, 파일 관련 엔티티 설계 중인데 칼럼 설정을 정말 잘하신 것 같아요 고생하셨습니다!! 👍
@@ -0,0 +1,40 @@
+package com.mybox.domain.storage;
+
+import com.mybox.domain.common.BaseTimeEntity;
+import java.time.LocalDateTime;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import lombok.Getter;
+import org.springframework.data.annotation.LastModifiedDate;
+
+@Getter
+@Entity
+public class StorageObjectMetaData extends BaseTimeEntity {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    private String name;
+    private StorageObjectType type;
+    private String extension;
+    private Long size;
+    private String path;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "namespace_id")
+    private Namespace namespace;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "parent_id")
+    private StorageObjectMetaData parentDirectory;
+
+    @LastModifiedDate
+    private LocalDateTime lastModifiedAt;
+
+}

리뷰: 파일 확장자입니다!
@@ -0,0 +1,29 @@
+import { Console } from '@woowacourse/mission-utils';
+import parseInput from './parseInput';
+
+const inputHandler = {
+  async dateHandler(userInput, validate) {
+    try {
+      const input = await Console.readLineAsync(userInput);
+      validate(Number(input));
+      return Number(input);
+    } catch (e) {
+      Console.print(e.message);
+      return this.dateHandler(userInput, validate);
+    }
+  },
+
+  async orderHandler(userInput, validate) {
+    try {
+      const input = await Console.readLineAsync(userInput);
+      const menu = parseInput(input);
+      validate(menu);
+      return Object.fromEntries(menu);
+    } catch (e) {
+      Console.print(e.message);
+      return this.orderHandler(userInput, validate);
+    }
+  },
+};
+
+export default inputHandler;

리뷰: 아예 입력 받고나서 바로 분리하는 방법도 있었네요 이 방법은 생각하지 못했던 것 같습니다 ㅎ..
추가로 trim,split,map을 결합해서 쓰는 것보다 정규표현식을 사용해보는건 어떨까요?
@@ -0,0 +1,58 @@
+import { DATE, DISCOUNT, INFO, MENU, MENU_KIND } from '../Util/constants';
+
+class Discount {
+  calculateDiscount(date, menu) {
+    const discount = {};
+    const addDisCount = (key, value) => {
+      if (value !== 0) discount[key] = value;
+    };
+
+    addDisCount(DISCOUNT.CHRISTMAS, this.isPeriod(date));
+    addDisCount(DISCOUNT.WEEK, this.isWeekday(date, menu));
+    addDisCount(DISCOUNT.WEEKEND, this.isWeekend(date, menu));
+    addDisCount(DISCOUNT.SPECIAL, this.isSpecialDay(date));
+    return discount;
+  }
+
+  isPeriod(date) {
+    let periodDiscount = 0;
+    if (date >= DATE.EVENT_START && date <= DATE.EVENT_END) {
+      periodDiscount +=
+        -DATE.PERIOD_DISCOUNT + (date - 1) * -DATE.PER_DAY_DISCOUNT;
+    }
+    return periodDiscount;
+  }
+
+  isWeekday(date, menu) {
+    let weekDisCount = 0;
+    if (!(date % 7 === 1 || date % 7 === 2)) {
+      let count = 0;
+      Object.keys(menu).forEach(name => {
+        if (MENU[name].kind === MENU_KIND.DESSERT) count += menu[name];
+      });
+      weekDisCount += -INFO.WEEK_DISCOUNT * count;
+    }
+    return weekDisCount;
+  }
+
+  isWeekend(date, menu) {
+    let weekendDisCount = 0;
+    if (date % 7 === 1 || date % 7 === 2) {
+      let count = 0;
+      Object.keys(menu).forEach(name => {
+        if (MENU[name].kind === MENU_KIND.MAIN) count += menu[name];
+      });
+      weekendDisCount += -INFO.WEEK_DISCOUNT * count;
+    }
+    return weekendDisCount;
+  }
+
+  isSpecialDay(date) {
+    let specialDayDiscount = 0;
+    if (DATE.SPECIAL_DATE.includes(date))
+      specialDayDiscount += -DATE.SPECIAL_DISCOUNT;
+    return specialDayDiscount;
+  }
+}
+
+export default Discount;

리뷰: 혹시 new Date() 말고 나머지 값을 사용하신 이유가 있을까요??
@@ -0,0 +1,60 @@
+import { ERROR_MESSAGE, MENU, MENU_KIND } from './constants';
+
+const validateDate = date => {
+  if (!(date >= 1 && date <= 31)) {
+    throw new Error(ERROR_MESSAGE.INVALID_DATE);
+  }
+  if (typeof date !== 'number' || !Number.isInteger(date)) {
+    throw new Error(ERROR_MESSAGE.INVALID_DATE);
+  }
+};
+
+const validateName = menu => {
+  const checkedName = new Set();
+  menu.forEach(([name]) => {
+    if (!Object.keys(MENU).includes(name)) {
+      throw new Error(ERROR_MESSAGE.INVALID_ORDER);
+    }
+    checkedName.add(name);
+  });
+};
+
+const validateDuplicate = menu => {
+  const checkedName = new Set();
+  menu.forEach(([name]) => {
+    if (checkedName.has(name)) {
+      throw new Error(ERROR_MESSAGE.INVALID_ORDER);
+    }
+    checkedName.add(name);
+  });
+};
+
+const validateOnlyDrink = menu => {
+  const types = new Set(menu.map(([name]) => MENU[name].type));
+  if (types.size === 1 && types.has(MENU_KIND.DRINK)) {
+    throw new Error(ERROR_MESSAGE.INVALID_ORDER);
+  }
+};
+
+const validateCount = menu => {
+  if (!menu.every(([, count]) => count >= 1)) {
+    throw new Error(ERROR_MESSAGE.INVALID_ORDER);
+  }
+};
+
+const validateTotalCount = menu => {
+  const total = menu.reduce((acc, [, count]) => acc + count, 0);
+  if (total > 20) {
+    throw new Error(ERROR_MESSAGE.INVALID_ORDER);
+  }
+};
+
+const validateOrder = order => {
+  validateName(order);
+  validateDuplicate(order);
+  validateOnlyDrink(order);
+  validateCount(order);
+  validateTotalCount(order);
+};
+
+export { validateDate, validateOrder };

리뷰: 해당 부분도 정규표현식을 쓰면 if를 하나만 써도 될 것 같습니다 !
@@ -0,0 +1,29 @@
+import { Console } from '@woowacourse/mission-utils';
+import parseInput from './parseInput';
+
+const inputHandler = {
+  async dateHandler(userInput, validate) {
+    try {
+      const input = await Console.readLineAsync(userInput);
+      validate(Number(input));
+      return Number(input);
+    } catch (e) {
+      Console.print(e.message);
+      return this.dateHandler(userInput, validate);
+    }
+  },
+
+  async orderHandler(userInput, validate) {
+    try {
+      const input = await Console.readLineAsync(userInput);
+      const menu = parseInput(input);
+      validate(menu);
+      return Object.fromEntries(menu);
+    } catch (e) {
+      Console.print(e.message);
+      return this.orderHandler(userInput, validate);
+    }
+  },
+};
+
+export default inputHandler;

리뷰: 정규 표현식을 활용했으면 굳이 파싱하는 작업이 필요하지 않았을 수도 있겠네요 좋은 피드백 감사합니다 ㅎㅎ🤣
@@ -0,0 +1,58 @@
+import { DATE, DISCOUNT, INFO, MENU, MENU_KIND } from '../Util/constants';
+
+class Discount {
+  calculateDiscount(date, menu) {
+    const discount = {};
+    const addDisCount = (key, value) => {
+      if (value !== 0) discount[key] = value;
+    };
+
+    addDisCount(DISCOUNT.CHRISTMAS, this.isPeriod(date));
+    addDisCount(DISCOUNT.WEEK, this.isWeekday(date, menu));
+    addDisCount(DISCOUNT.WEEKEND, this.isWeekend(date, menu));
+    addDisCount(DISCOUNT.SPECIAL, this.isSpecialDay(date));
+    return discount;
+  }
+
+  isPeriod(date) {
+    let periodDiscount = 0;
+    if (date >= DATE.EVENT_START && date <= DATE.EVENT_END) {
+      periodDiscount +=
+        -DATE.PERIOD_DISCOUNT + (date - 1) * -DATE.PER_DAY_DISCOUNT;
+    }
+    return periodDiscount;
+  }
+
+  isWeekday(date, menu) {
+    let weekDisCount = 0;
+    if (!(date % 7 === 1 || date % 7 === 2)) {
+      let count = 0;
+      Object.keys(menu).forEach(name => {
+        if (MENU[name].kind === MENU_KIND.DESSERT) count += menu[name];
+      });
+      weekDisCount += -INFO.WEEK_DISCOUNT * count;
+    }
+    return weekDisCount;
+  }
+
+  isWeekend(date, menu) {
+    let weekendDisCount = 0;
+    if (date % 7 === 1 || date % 7 === 2) {
+      let count = 0;
+      Object.keys(menu).forEach(name => {
+        if (MENU[name].kind === MENU_KIND.MAIN) count += menu[name];
+      });
+      weekendDisCount += -INFO.WEEK_DISCOUNT * count;
+    }
+    return weekendDisCount;
+  }
+
+  isSpecialDay(date) {
+    let specialDayDiscount = 0;
+    if (DATE.SPECIAL_DATE.includes(date))
+      specialDayDiscount += -DATE.SPECIAL_DISCOUNT;
+    return specialDayDiscount;
+  }
+}
+
+export default Discount;

리뷰: 미션에서 2023년 2월로 정확한 기간을 명시해주었기에 관련된 건 최대한 Date 객체 생성이 아닌 구현으로 해결하고 싶다는 점에서 사용을 하지 않으려고 했습니다 ! 또 그러다보니 충분히 다른 표현식으로 일자를 판별할 수 있다고 생각하여 그렇게 구현했던 거 같네요 🤔