ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,19 @@
+import IDiscountStrategy from './IDiscountStrategy';
+import { DiscountStrategyConstants } from './constants/DiscountStrategyConstants';
+
+export default class WeekdayDiscountStrategy extends IDiscountStrategy {
+  applyDiscount(order, date) {
+    const dayOfWeek = date.getDay();
+    const isWeekday = dayOfWeek >= 0 && dayOfWeek <= 4;
+
+    if (isWeekday) {
+      const DESSERT_DISCOUNT = 2023;
+      const discountAmount = order
+        .getItems()
+        .filter((item) => item.category === 'DESSERTS')
+        .reduce((total, item) => total + item.quantity * DESSERT_DISCOUNT, 0);
+      return { name: DiscountStrategyConstants.WEEKDAY_DISCOUNT, amount: discountAmount };
+    }
+    return { name: DiscountStrategyConstants.WEEKDAY_DISCOUNT, amount: 0 };
+  }
+}

리뷰: `0`, `4`와 같은 숫자를 `SUNDAY`, `THURSDAY`처럼 상수화해서 사용하면 코드 가독성을 더 챙길 수 있을 것 같아요!
@@ -0,0 +1,36 @@
+import { ValidatorConstants } from './constants/ValidatorConstants';
+
+export const InputValidator = {
+  Day: {
+    validateDay(input) {
+      const dayPattern = /^\d+$/;
+      if (!dayPattern.test(input)) {
+        throw new Error(ValidatorConstants.INVALID_DATE_ERROR);
+      }
+      const day = parseInt(input, 10);
+      if (day < 1 || day > 31) {
+        throw new Error(ValidatorConstants.INVALID_DATE_ERROR);
+      }
+
+      return day;
+    },
+  },
+
+  Menu: {
+    validateMenu(input) {
+      const menuSelections = input.split(',');
+      const selectionPattern = /^[가-힣]+-\d+$/;
+      const validSelections = menuSelections.map((selection) => {
+        const trimmedSelection = selection.trim();
+        if (!selectionPattern.test(trimmedSelection)) {
+          throw new Error(ValidatorConstants.INVALID_ORDER_ERROR);
+        }
+        const [name, quantity] = trimmedSelection.split('-');
+
+        return { name, quantity: parseInt(quantity, 10) };
+      });
+
+      return validSelections;
+    },
+  },
+};

리뷰: 각각의 validation(정규표현식 패턴 & 범위)을 두 개의 함수로 분리해 선언하고 호출해서 사용하는 건 어떨까요? 의도해서 한꺼번에 작성하신 것 같은데, 만약 맞다면 이유가 궁금해요!
@@ -0,0 +1,36 @@
+import { ValidatorConstants } from './constants/ValidatorConstants';
+
+export const InputValidator = {
+  Day: {
+    validateDay(input) {
+      const dayPattern = /^\d+$/;
+      if (!dayPattern.test(input)) {
+        throw new Error(ValidatorConstants.INVALID_DATE_ERROR);
+      }
+      const day = parseInt(input, 10);
+      if (day < 1 || day > 31) {
+        throw new Error(ValidatorConstants.INVALID_DATE_ERROR);
+      }
+
+      return day;
+    },
+  },
+
+  Menu: {
+    validateMenu(input) {
+      const menuSelections = input.split(',');
+      const selectionPattern = /^[가-힣]+-\d+$/;
+      const validSelections = menuSelections.map((selection) => {
+        const trimmedSelection = selection.trim();
+        if (!selectionPattern.test(trimmedSelection)) {
+          throw new Error(ValidatorConstants.INVALID_ORDER_ERROR);
+        }
+        const [name, quantity] = trimmedSelection.split('-');
+
+        return { name, quantity: parseInt(quantity, 10) };
+      });
+
+      return validSelections;
+    },
+  },
+};

리뷰: 이 로직이라면 이런 입력을 넣어도 정상적으로 작동할 것 같아요. 혹시 다른 부분에서 검사하고 있는데 제가 놓친 것일까요?

```
바비큐립-1,,,,,,,타파스-2
바비큐립-1,,,타파스-2,,
```
@@ -0,0 +1,87 @@
+const express = require('express')
+const http = require('http');
+const path = require('path');
+
+const bodyParser = require('body-parser');
+const static = require('serve-static');
+const multer = require("multer")
+
+const app = express();
+
+app.set('port', process.env.PORT || 3000);
+
+app.use(bodyParser.urlencoded({ extended: false }))
+app.use(bodyParser.json())
+
+app.use('/public', static(path.join(__dirname, 'public')));
+app.use('/uploads', static(path.join(__dirname, 'uploads')))
+
+const upload = multer({
+    storage: multer.diskStorage({
+        destination: function (req, file, cb) {
+            cb(null, './uploads/');
+        },
+        filename: function (req, file, cb) {
+            cb(null, file.originalname);
+        }
+    }),
+}).single('userfile');
+
+app.post("/save", function (req, res) {
+    try {
+        upload(req, res, function (err) {
+            var name = req.body.name;
+            var date = req.body.date;
+            var content = req.body.content;
+            var filename = req.file.filename;
+            console.log(filename);
+            res.writeHead(200, { 'Content-Type': 'text/html;charset=utf8' });
+            res.write(`
+            <head>
+            <meta charset="UTF-8">
+            <link rel="stylesheet" href="/public/stylesheet/momo.css">
+            <title>Document</title>
+            </head>
+            <form method="GET" action="/" id="re-form">
+            <table class="header-table">
+                <thead>
+                    <th class="table-head">나의 메모</th>
+                </thead>
+                <tbody class="table-body">
+                    <tr>
+                        <td>${name},${date},${content}메모가 저장되었습니다.</td>
+                    </tr>
+                    <tr>
+                        <td colspan="2" class="upload-display">
+                            <div class="upload-thumb-wrap"><img class="upload-thumb" src="/uploads/${filename}"></div>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+            <table class="footer-table">
+                <tbody>
+                    <tr><td id="re-layor"><button id="redirect" form = "re-form" type="submit" >다시작성</button></td></tr>
+                </tbody>
+            </table>
+            </form>
+            `);
+            res.end();
+        });
+
+    } catch (err) {
+        console.dir(err.stack);
+
+        res.writeHead(400, { 'Content-Type': 'text/html;charset=utf8' });
+        res.write('<div><p>메모 저장 시 에러 발생</p></div>');
+        res.end();
+    }
+
+});
+
+app.get('/', function (req, res) {
+    res.sendFile(__dirname + "/view/memo/memo.html");
+});
+
+http.createServer(app).listen(app.get('port'), function () {
+    console.log("서버시작");
+});
\ No newline at end of file

리뷰: String이 아닌 html이나 ejs 파일로 보내는 것이 좋습니다. (Feat. 쿠마쨩)
save.ejs로 분리해 주세요.
@@ -0,0 +1,87 @@
+const express = require('express')
+const http = require('http');
+const path = require('path');
+
+const bodyParser = require('body-parser');
+const static = require('serve-static');
+const multer = require("multer")
+
+const app = express();
+
+app.set('port', process.env.PORT || 3000);
+
+app.use(bodyParser.urlencoded({ extended: false }))
+app.use(bodyParser.json())
+
+app.use('/public', static(path.join(__dirname, 'public')));
+app.use('/uploads', static(path.join(__dirname, 'uploads')))
+
+const upload = multer({
+    storage: multer.diskStorage({
+        destination: function (req, file, cb) {
+            cb(null, './uploads/');
+        },
+        filename: function (req, file, cb) {
+            cb(null, file.originalname);
+        }
+    }),
+}).single('userfile');
+
+app.post("/save", function (req, res) {
+    try {
+        upload(req, res, function (err) {
+            var name = req.body.name;
+            var date = req.body.date;
+            var content = req.body.content;
+            var filename = req.file.filename;
+            console.log(filename);
+            res.writeHead(200, { 'Content-Type': 'text/html;charset=utf8' });
+            res.write(`
+            <head>
+            <meta charset="UTF-8">
+            <link rel="stylesheet" href="/public/stylesheet/momo.css">
+            <title>Document</title>
+            </head>
+            <form method="GET" action="/" id="re-form">
+            <table class="header-table">
+                <thead>
+                    <th class="table-head">나의 메모</th>
+                </thead>
+                <tbody class="table-body">
+                    <tr>
+                        <td>${name},${date},${content}메모가 저장되었습니다.</td>
+                    </tr>
+                    <tr>
+                        <td colspan="2" class="upload-display">
+                            <div class="upload-thumb-wrap"><img class="upload-thumb" src="/uploads/${filename}"></div>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+            <table class="footer-table">
+                <tbody>
+                    <tr><td id="re-layor"><button id="redirect" form = "re-form" type="submit" >다시작성</button></td></tr>
+                </tbody>
+            </table>
+            </form>
+            `);
+            res.end();
+        });
+
+    } catch (err) {
+        console.dir(err.stack);
+
+        res.writeHead(400, { 'Content-Type': 'text/html;charset=utf8' });
+        res.write('<div><p>메모 저장 시 에러 발생</p></div>');
+        res.end();
+    }
+
+});
+
+app.get('/', function (req, res) {
+    res.sendFile(__dirname + "/view/memo/memo.html");
+});
+
+http.createServer(app).listen(app.get('port'), function () {
+    console.log("서버시작");
+});
\ No newline at end of file

리뷰: 빈 줄과 들여쓰기 정리해 주세요.
@@ -1 +1,127 @@
 # java-chess 게임
+
+## 구현해야할 목록
+
+### 입력
+
+- [x] 명령어 입력
+    - [x] 예외: `null` 입력
+
+### 출력
+
+- [x] 시작 안내 문구 출력
+- [x] 체스판 스냅샷 출력
+- [x] 차례 출력
+- [x] 점수 출력
+- [x] 승자 출력
+
+### 서비스
+
+#### `ChessService`
+
+- [x] `Command`에 따라 기능 수행
+- [x] 게임 현재 상황 DTO
+
+### 도메인
+
+#### `Operation`
+
+- [x] 명령어 검증
+    - [x] start: 게임 실행
+    - [x] status: 팀별 점수
+    - [x] move: 기물 이동
+    - [x] end: 강제 종료
+
+#### `Board`
+
+- [x] 기물 이동
+    - [x] 예외
+        - [x] 움직일 기물이 자신 팀 소유가 아닌 경우
+        - [x] `source`와 `target`이 같은 위치인 경우
+        - [x] 본인의 기물을 공격하는 경우
+        - [x] 이동 경로가 다른 기물에 가로막힌 경우
+        - [x] `King`: `target`이 적이 공격 가능한 위치인 경우
+        - [x] `Pawn`: `target`에 적이 없는데 대각선으로 이동하는 경우
+    - [x] 자신의 기물 이동
+    - [x] 공격인 경우 적 기물 제거
+    - [x] 차례 변경
+- [x] 현재 차례 관리
+- [x] 위치 정보
+    - [x] 특정 위치가 비었는지 확인
+    - [x] 특정 위치에 있는 기물 확인
+- [x] 각 팀 점수 계산
+- [x] 승자 확인
+    - [x] 예외: 두 `King`이 모두 살아 있는 경우
+
+#### `Team`
+
+- [x] 기물 이동
+- [x] 기물 이동 경로 검색
+- [x] 현위치에서 공격 가능한 모든 경로 검색
+- [x] 적에게 공격받은 경우 기물 제거
+- [x] 기물 검색
+- [x] 점수 계산
+
+#### `Piece`
+
+- [x] 이동 경로 검색
+- [x] 현위치에서 공격 가능한 모든 경로 검색
+- [x] 색상 확인
+- [x] 타입 확인
+    - [x] `Pawn`
+    - [x] `King`
+
+#### `MovePattern`
+
+- [x] 각 기물 타입에 맞는 패턴 검색
+    - [x] `Pawn`은 색상에 맞는 패턴 검색
+- [x] 본인 패턴 중 `gap`에 맞는 `MoveUnit` 검색
+- [x] 본인 패턴으로 공격 가능한 모든 경로 검색
+
+#### `MoveLimit`
+
+- [x] 한 칸만 이동 가능한지 확인
+
+#### `MoveUnits`
+
+- [x] 본인 리스트에서 매칭되는 `MoveUnit` 검색
+    - [x] 예외: 매칭되는 `MoveUnit`이 없는 경우
+- [x] 이동 단위 별로 이동 가능한 모든 경로 검색
+
+#### `MoveUnit`
+
+- [x] `MoveUnit`의 좌표가 `gap`에 매칭되는지 확인
+
+#### `Position`
+
+- [x] 64개 위치 캐싱 및 검색
+- [x] `Gap` 계산
+- [x] 이동 단위로 타겟까지 이동할 때 지나가는 모든 위치 검색
+- [x] 이동 단위로 이동 가능한 체스판의 모든 위치 검색
+- [x] 이동 단위로 한 번 더 이동 가능한지 확인
+- [x] 이동 단위로 이동
+
+## 이동 규칙
+
+- [x] 폰 (1 or 0.5)
+    - [x] 적 방향 직선 1칸 이동
+    - [x] 처음 이동 시에는 2칸 이동 가능
+    - [x] 공격 시에는 적 방향 좌, 우 대각선 1칸 이동
+
+- [x] 룩 (5)
+    - [x] 모든 직선 방향으로 원하는 만큼 이동
+
+- [x] 나이트 (2.5)
+    - [x] 모든 직선 방향 1칸 + 이동한 직선 방향의 좌, 우 대각선 1칸으로 이동
+    - [x] 진행 방향이 가로막혀도 적, 아군 상관없이 뛰어넘을 수 있음
+
+- [x] 비숍 (3)
+    - [x] 모든 대각선 방향으로 원하는 만큼 이동
+
+- [x] 퀸 (9)
+    - [x] 모든 방향으로 원하는 만큼 이동
+
+- [x] 킹
+    - [x] 모든 방향 1칸 이동
+    - [x] 상대의 공격 범위로는 이동 불가능
+

리뷰: 각 기물 뒤에 나온 숫자가 점수인 것으로 보이는데,
점수 계산에 대한 것도 기능 목록으로 빼면 어떨까요?
해당 코드만 보고 이해하는 사람에게는 어떤 숫자를 의미하는지 알기가 어려울 것 같아요.
@@ -1 +1,127 @@
 # java-chess 게임
+
+## 구현해야할 목록
+
+### 입력
+
+- [x] 명령어 입력
+    - [x] 예외: `null` 입력
+
+### 출력
+
+- [x] 시작 안내 문구 출력
+- [x] 체스판 스냅샷 출력
+- [x] 차례 출력
+- [x] 점수 출력
+- [x] 승자 출력
+
+### 서비스
+
+#### `ChessService`
+
+- [x] `Command`에 따라 기능 수행
+- [x] 게임 현재 상황 DTO
+
+### 도메인
+
+#### `Operation`
+
+- [x] 명령어 검증
+    - [x] start: 게임 실행
+    - [x] status: 팀별 점수
+    - [x] move: 기물 이동
+    - [x] end: 강제 종료
+
+#### `Board`
+
+- [x] 기물 이동
+    - [x] 예외
+        - [x] 움직일 기물이 자신 팀 소유가 아닌 경우
+        - [x] `source`와 `target`이 같은 위치인 경우
+        - [x] 본인의 기물을 공격하는 경우
+        - [x] 이동 경로가 다른 기물에 가로막힌 경우
+        - [x] `King`: `target`이 적이 공격 가능한 위치인 경우
+        - [x] `Pawn`: `target`에 적이 없는데 대각선으로 이동하는 경우
+    - [x] 자신의 기물 이동
+    - [x] 공격인 경우 적 기물 제거
+    - [x] 차례 변경
+- [x] 현재 차례 관리
+- [x] 위치 정보
+    - [x] 특정 위치가 비었는지 확인
+    - [x] 특정 위치에 있는 기물 확인
+- [x] 각 팀 점수 계산
+- [x] 승자 확인
+    - [x] 예외: 두 `King`이 모두 살아 있는 경우
+
+#### `Team`
+
+- [x] 기물 이동
+- [x] 기물 이동 경로 검색
+- [x] 현위치에서 공격 가능한 모든 경로 검색
+- [x] 적에게 공격받은 경우 기물 제거
+- [x] 기물 검색
+- [x] 점수 계산
+
+#### `Piece`
+
+- [x] 이동 경로 검색
+- [x] 현위치에서 공격 가능한 모든 경로 검색
+- [x] 색상 확인
+- [x] 타입 확인
+    - [x] `Pawn`
+    - [x] `King`
+
+#### `MovePattern`
+
+- [x] 각 기물 타입에 맞는 패턴 검색
+    - [x] `Pawn`은 색상에 맞는 패턴 검색
+- [x] 본인 패턴 중 `gap`에 맞는 `MoveUnit` 검색
+- [x] 본인 패턴으로 공격 가능한 모든 경로 검색
+
+#### `MoveLimit`
+
+- [x] 한 칸만 이동 가능한지 확인
+
+#### `MoveUnits`
+
+- [x] 본인 리스트에서 매칭되는 `MoveUnit` 검색
+    - [x] 예외: 매칭되는 `MoveUnit`이 없는 경우
+- [x] 이동 단위 별로 이동 가능한 모든 경로 검색
+
+#### `MoveUnit`
+
+- [x] `MoveUnit`의 좌표가 `gap`에 매칭되는지 확인
+
+#### `Position`
+
+- [x] 64개 위치 캐싱 및 검색
+- [x] `Gap` 계산
+- [x] 이동 단위로 타겟까지 이동할 때 지나가는 모든 위치 검색
+- [x] 이동 단위로 이동 가능한 체스판의 모든 위치 검색
+- [x] 이동 단위로 한 번 더 이동 가능한지 확인
+- [x] 이동 단위로 이동
+
+## 이동 규칙
+
+- [x] 폰 (1 or 0.5)
+    - [x] 적 방향 직선 1칸 이동
+    - [x] 처음 이동 시에는 2칸 이동 가능
+    - [x] 공격 시에는 적 방향 좌, 우 대각선 1칸 이동
+
+- [x] 룩 (5)
+    - [x] 모든 직선 방향으로 원하는 만큼 이동
+
+- [x] 나이트 (2.5)
+    - [x] 모든 직선 방향 1칸 + 이동한 직선 방향의 좌, 우 대각선 1칸으로 이동
+    - [x] 진행 방향이 가로막혀도 적, 아군 상관없이 뛰어넘을 수 있음
+
+- [x] 비숍 (3)
+    - [x] 모든 대각선 방향으로 원하는 만큼 이동
+
+- [x] 퀸 (9)
+    - [x] 모든 방향으로 원하는 만큼 이동
+
+- [x] 킹
+    - [x] 모든 방향 1칸 이동
+    - [x] 상대의 공격 범위로는 이동 불가능
+

리뷰: 퀸의 이동방향은 상하좌우대각선 모두 원하는만큼 이동인 것으로 알고 있는데,
상하좌우는 1칸씩밖에 이동하지 못하는건가요?
퀸의 이동 규칙을 한 번 다시 봐주시겠어요?
@@ -1 +1,127 @@
 # java-chess 게임
+
+## 구현해야할 목록
+
+### 입력
+
+- [x] 명령어 입력
+    - [x] 예외: `null` 입력
+
+### 출력
+
+- [x] 시작 안내 문구 출력
+- [x] 체스판 스냅샷 출력
+- [x] 차례 출력
+- [x] 점수 출력
+- [x] 승자 출력
+
+### 서비스
+
+#### `ChessService`
+
+- [x] `Command`에 따라 기능 수행
+- [x] 게임 현재 상황 DTO
+
+### 도메인
+
+#### `Operation`
+
+- [x] 명령어 검증
+    - [x] start: 게임 실행
+    - [x] status: 팀별 점수
+    - [x] move: 기물 이동
+    - [x] end: 강제 종료
+
+#### `Board`
+
+- [x] 기물 이동
+    - [x] 예외
+        - [x] 움직일 기물이 자신 팀 소유가 아닌 경우
+        - [x] `source`와 `target`이 같은 위치인 경우
+        - [x] 본인의 기물을 공격하는 경우
+        - [x] 이동 경로가 다른 기물에 가로막힌 경우
+        - [x] `King`: `target`이 적이 공격 가능한 위치인 경우
+        - [x] `Pawn`: `target`에 적이 없는데 대각선으로 이동하는 경우
+    - [x] 자신의 기물 이동
+    - [x] 공격인 경우 적 기물 제거
+    - [x] 차례 변경
+- [x] 현재 차례 관리
+- [x] 위치 정보
+    - [x] 특정 위치가 비었는지 확인
+    - [x] 특정 위치에 있는 기물 확인
+- [x] 각 팀 점수 계산
+- [x] 승자 확인
+    - [x] 예외: 두 `King`이 모두 살아 있는 경우
+
+#### `Team`
+
+- [x] 기물 이동
+- [x] 기물 이동 경로 검색
+- [x] 현위치에서 공격 가능한 모든 경로 검색
+- [x] 적에게 공격받은 경우 기물 제거
+- [x] 기물 검색
+- [x] 점수 계산
+
+#### `Piece`
+
+- [x] 이동 경로 검색
+- [x] 현위치에서 공격 가능한 모든 경로 검색
+- [x] 색상 확인
+- [x] 타입 확인
+    - [x] `Pawn`
+    - [x] `King`
+
+#### `MovePattern`
+
+- [x] 각 기물 타입에 맞는 패턴 검색
+    - [x] `Pawn`은 색상에 맞는 패턴 검색
+- [x] 본인 패턴 중 `gap`에 맞는 `MoveUnit` 검색
+- [x] 본인 패턴으로 공격 가능한 모든 경로 검색
+
+#### `MoveLimit`
+
+- [x] 한 칸만 이동 가능한지 확인
+
+#### `MoveUnits`
+
+- [x] 본인 리스트에서 매칭되는 `MoveUnit` 검색
+    - [x] 예외: 매칭되는 `MoveUnit`이 없는 경우
+- [x] 이동 단위 별로 이동 가능한 모든 경로 검색
+
+#### `MoveUnit`
+
+- [x] `MoveUnit`의 좌표가 `gap`에 매칭되는지 확인
+
+#### `Position`
+
+- [x] 64개 위치 캐싱 및 검색
+- [x] `Gap` 계산
+- [x] 이동 단위로 타겟까지 이동할 때 지나가는 모든 위치 검색
+- [x] 이동 단위로 이동 가능한 체스판의 모든 위치 검색
+- [x] 이동 단위로 한 번 더 이동 가능한지 확인
+- [x] 이동 단위로 이동
+
+## 이동 규칙
+
+- [x] 폰 (1 or 0.5)
+    - [x] 적 방향 직선 1칸 이동
+    - [x] 처음 이동 시에는 2칸 이동 가능
+    - [x] 공격 시에는 적 방향 좌, 우 대각선 1칸 이동
+
+- [x] 룩 (5)
+    - [x] 모든 직선 방향으로 원하는 만큼 이동
+
+- [x] 나이트 (2.5)
+    - [x] 모든 직선 방향 1칸 + 이동한 직선 방향의 좌, 우 대각선 1칸으로 이동
+    - [x] 진행 방향이 가로막혀도 적, 아군 상관없이 뛰어넘을 수 있음
+
+- [x] 비숍 (3)
+    - [x] 모든 대각선 방향으로 원하는 만큼 이동
+
+- [x] 퀸 (9)
+    - [x] 모든 방향으로 원하는 만큼 이동
+
+- [x] 킹
+    - [x] 모든 방향 1칸 이동
+    - [x] 상대의 공격 범위로는 이동 불가능
+

리뷰: 넵! Player 기능목록에 점수 계산도 추가했습니다
@@ -1 +1,127 @@
 # java-chess 게임
+
+## 구현해야할 목록
+
+### 입력
+
+- [x] 명령어 입력
+    - [x] 예외: `null` 입력
+
+### 출력
+
+- [x] 시작 안내 문구 출력
+- [x] 체스판 스냅샷 출력
+- [x] 차례 출력
+- [x] 점수 출력
+- [x] 승자 출력
+
+### 서비스
+
+#### `ChessService`
+
+- [x] `Command`에 따라 기능 수행
+- [x] 게임 현재 상황 DTO
+
+### 도메인
+
+#### `Operation`
+
+- [x] 명령어 검증
+    - [x] start: 게임 실행
+    - [x] status: 팀별 점수
+    - [x] move: 기물 이동
+    - [x] end: 강제 종료
+
+#### `Board`
+
+- [x] 기물 이동
+    - [x] 예외
+        - [x] 움직일 기물이 자신 팀 소유가 아닌 경우
+        - [x] `source`와 `target`이 같은 위치인 경우
+        - [x] 본인의 기물을 공격하는 경우
+        - [x] 이동 경로가 다른 기물에 가로막힌 경우
+        - [x] `King`: `target`이 적이 공격 가능한 위치인 경우
+        - [x] `Pawn`: `target`에 적이 없는데 대각선으로 이동하는 경우
+    - [x] 자신의 기물 이동
+    - [x] 공격인 경우 적 기물 제거
+    - [x] 차례 변경
+- [x] 현재 차례 관리
+- [x] 위치 정보
+    - [x] 특정 위치가 비었는지 확인
+    - [x] 특정 위치에 있는 기물 확인
+- [x] 각 팀 점수 계산
+- [x] 승자 확인
+    - [x] 예외: 두 `King`이 모두 살아 있는 경우
+
+#### `Team`
+
+- [x] 기물 이동
+- [x] 기물 이동 경로 검색
+- [x] 현위치에서 공격 가능한 모든 경로 검색
+- [x] 적에게 공격받은 경우 기물 제거
+- [x] 기물 검색
+- [x] 점수 계산
+
+#### `Piece`
+
+- [x] 이동 경로 검색
+- [x] 현위치에서 공격 가능한 모든 경로 검색
+- [x] 색상 확인
+- [x] 타입 확인
+    - [x] `Pawn`
+    - [x] `King`
+
+#### `MovePattern`
+
+- [x] 각 기물 타입에 맞는 패턴 검색
+    - [x] `Pawn`은 색상에 맞는 패턴 검색
+- [x] 본인 패턴 중 `gap`에 맞는 `MoveUnit` 검색
+- [x] 본인 패턴으로 공격 가능한 모든 경로 검색
+
+#### `MoveLimit`
+
+- [x] 한 칸만 이동 가능한지 확인
+
+#### `MoveUnits`
+
+- [x] 본인 리스트에서 매칭되는 `MoveUnit` 검색
+    - [x] 예외: 매칭되는 `MoveUnit`이 없는 경우
+- [x] 이동 단위 별로 이동 가능한 모든 경로 검색
+
+#### `MoveUnit`
+
+- [x] `MoveUnit`의 좌표가 `gap`에 매칭되는지 확인
+
+#### `Position`
+
+- [x] 64개 위치 캐싱 및 검색
+- [x] `Gap` 계산
+- [x] 이동 단위로 타겟까지 이동할 때 지나가는 모든 위치 검색
+- [x] 이동 단위로 이동 가능한 체스판의 모든 위치 검색
+- [x] 이동 단위로 한 번 더 이동 가능한지 확인
+- [x] 이동 단위로 이동
+
+## 이동 규칙
+
+- [x] 폰 (1 or 0.5)
+    - [x] 적 방향 직선 1칸 이동
+    - [x] 처음 이동 시에는 2칸 이동 가능
+    - [x] 공격 시에는 적 방향 좌, 우 대각선 1칸 이동
+
+- [x] 룩 (5)
+    - [x] 모든 직선 방향으로 원하는 만큼 이동
+
+- [x] 나이트 (2.5)
+    - [x] 모든 직선 방향 1칸 + 이동한 직선 방향의 좌, 우 대각선 1칸으로 이동
+    - [x] 진행 방향이 가로막혀도 적, 아군 상관없이 뛰어넘을 수 있음
+
+- [x] 비숍 (3)
+    - [x] 모든 대각선 방향으로 원하는 만큼 이동
+
+- [x] 퀸 (9)
+    - [x] 모든 방향으로 원하는 만큼 이동
+
+- [x] 킹
+    - [x] 모든 방향 1칸 이동
+    - [x] 상대의 공격 범위로는 이동 불가능
+

리뷰: 넵 퀸 이동 규칙을 완전히 착각해버렸어요ㅠㅠ 수정했습니다!
@@ -0,0 +1,32 @@
+import { ERROR_MSG } from '../../constants/PlannerMsg.js';
+
+class DateValidate {
+  #regax;
+
+  #date;
+
+  constructor(regax, date) {
+    this.#regax = regax;
+    this.#date = date;
+  }
+
+  regaxCheck() {
+    if (this.#regax.test(this.#date)) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+
+  safeCheck() {
+    if (!Number.isSafeInteger(Number(this.#date))) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+
+  rangeCheck() {
+    if (Number(this.#date) <= 0 || Number(this.#date) > 31) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+}
+
+export default DateValidate;

리뷰: 이건 진짜 사소한 거긴한데, 변수 중에 #regax 가 있는데 정규표현식을 나타내는 거라고 생각하는데, 혹시 맞다면 regular expression => regex 가 좋지 않을까! 생각해봤습니다! 아마 오타이신 거 같기두하구..!?
@@ -0,0 +1,32 @@
+import { ERROR_MSG } from '../../constants/PlannerMsg.js';
+
+class DateValidate {
+  #regax;
+
+  #date;
+
+  constructor(regax, date) {
+    this.#regax = regax;
+    this.#date = date;
+  }
+
+  regaxCheck() {
+    if (this.#regax.test(this.#date)) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+
+  safeCheck() {
+    if (!Number.isSafeInteger(Number(this.#date))) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+
+  rangeCheck() {
+    if (Number(this.#date) <= 0 || Number(this.#date) > 31) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+}
+
+export default DateValidate;

리뷰: Number.isInteger 만 알았지, Number.isSafeInteger 라는 메서드가 있는 줄은 정말 몰랐는데, 덕분에 이렇게 또 하나 알아가요!
@@ -0,0 +1,32 @@
+import { ERROR_MSG } from '../../constants/PlannerMsg.js';
+
+class DateValidate {
+  #regax;
+
+  #date;
+
+  constructor(regax, date) {
+    this.#regax = regax;
+    this.#date = date;
+  }
+
+  regaxCheck() {
+    if (this.#regax.test(this.#date)) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+
+  safeCheck() {
+    if (!Number.isSafeInteger(Number(this.#date))) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+
+  rangeCheck() {
+    if (Number(this.#date) <= 0 || Number(this.#date) > 31) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+}
+
+export default DateValidate;

리뷰: rangeCheck메서드에서 날짜를 나타내는 숫자 0, 31도 상수처리해서 가져오면 나중에 변경할 때 더 편리하지 않을까 싶었습니다!
@@ -0,0 +1,32 @@
+import { ERROR_MSG } from '../../constants/PlannerMsg.js';
+
+class DateValidate {
+  #regax;
+
+  #date;
+
+  constructor(regax, date) {
+    this.#regax = regax;
+    this.#date = date;
+  }
+
+  regaxCheck() {
+    if (this.#regax.test(this.#date)) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+
+  safeCheck() {
+    if (!Number.isSafeInteger(Number(this.#date))) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+
+  rangeCheck() {
+    if (Number(this.#date) <= 0 || Number(this.#date) > 31) {
+      throw new Error(ERROR_MSG.dateError);
+    }
+  }
+}
+
+export default DateValidate;

리뷰: 앗 MVC패턴 안에서만 상수화를 생각했지 이부분을 깜빡했네요..! 좋은 의견 감사합니다!
@@ -0,0 +1,28 @@
+import DateValidate from './validator/DateValidate.js';
+import MenuValidate from './validator/MenuValidate.js';
+
+class InputValidator {
+  #REGAX;
+
+  constructor() {
+    this.#REGAX = /\s|[!@#$%^&*(),?":{}|<>]|[a-zA-Z]/;
+  }
+
+  async dateValidate(date) {
+    const dateValidator = new DateValidate(this.#REGAX, date);
+    dateValidator.regaxCheck();
+    dateValidator.safeCheck();
+    dateValidator.rangeCheck();
+  }
+
+  async menuValidate(menu) {
+    const menuValidator = new MenuValidate(menu);
+    menuValidator.menuCheck();
+    menuValidator.menuAmountCheck(this.#REGAX);
+    menuValidator.formCheck();
+    menuValidator.duplicateCheck();
+    menuValidator.drinkCheck();
+  }
+}
+
+export default InputValidator;

리뷰: 정규식으로 유효성 검사 로직을 간결하게 표현했으면 좋았을 거란 리뷰를 받은 입장으로서.. 정규식 사용을 깔끔하신 점 배우고 갑니다 🙌🏻
@@ -0,0 +1,34 @@
+export const EVENT_CONST = {
+  christmas: 0,
+  weekDay: 0,
+  weekendDay: 0,
+  specialDay: 0,
+  benefitEvent: 0,
+};
+
+export const DAY_OF_WEEK = {
+  sun: 0,
+  mon: 1,
+  tue: 2,
+  wed: 3,
+  thu: 4,
+  fri: 5,
+  sat: 6,
+  weekDay: [0, 1, 2, 3, 4],
+  weekendDay: [5, 6],
+  specialDay: [0, 25],
+};
+
+export const UTILS_CONST = {
+  userDay: (userDate) => `2023-12-${userDate}`,
+  christmasBenefit: (userDate) => 1000 + (userDate - 1) * 100,
+  minGetBenefit: 10000,
+  christmasEventEnd: 25,
+  noBenefit: 0,
+  discount: 2023,
+  weekDayEvent: 'dessert',
+  weekendEvent: 'main',
+  specialDiscount: 1000,
+  minGetGift: 120000,
+  giftCost: 25000,
+};

리뷰: 이미 상수 선언으로 const 라는 단어는 내포할 수 있다고 생각해요! UTILS,  EVENT 로 선언하고 내부 상수들의 명칭을 더 구체적으로 작성하시는 방법도 좋았을거라구 생각합니다 ㅎㅎ