ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,43 @@
+export const APPETIZER = Object.freeze({
+  '양송이수프' : 6000,
+  '타파스' : 5500,
+  '시저샐러드' : 8000,
+  'type' : 'appetizer',
+});
+
+export const MAIN = Object.freeze({
+  '티본스테이크' : 55000,
+  '바비큐립' : 54000,
+  '해산물파스타' : 35000,
+  '크리스마스파스타' : 25000,
+  'type' : 'main',
+});
+
+export const DESERT = Object.freeze({
+  '초코케이크' : 15000,
+  '아이스크림' : 5000,
+  'type' : 'desert',
+});
+
+export const DRINK = Object.freeze({
+  '제로콜라' : 3000,
+  '레드와인' : 60000,
+  '샴페인' : 25000,
+  'type' : 'drink',
+});
+
+export const MENU = [APPETIZER, MAIN, DESERT, DRINK];
+
+export const NAME = Object.freeze({
+  type : 'type',
+  appetizer : 'appetizer',
+  main : 'main',
+  desert : 'desert',
+  drink : 'drink',
+});
+
+export const KNIFE = Object.freeze({
+  namePosition : 0,
+  quantityPosition : 1,
+  bladePosition : '-'
+});

리뷰: 타입부분은 해당 객체에 마지막에 넣기보단, 따로 빼서 확인하는게 좋을 것 같습니다! 
객체가 중간에 속성이 다를 경우, 유지보수도 힘들뿐만 아니라 매번 `APPETIZER`의 마지막 속성은 type이라는걸 기억해두고 코드를 짜야해서, type은 해당 객체에서 따로 빼는게 좋아보입니다!
```js
export const APPETIZER = Object.freeze({
  '양송이수프': 6000,
  '타파스': 5500,
  '시저샐러드': 8000,
});
```
@@ -0,0 +1,43 @@
+export const APPETIZER = Object.freeze({
+  '양송이수프' : 6000,
+  '타파스' : 5500,
+  '시저샐러드' : 8000,
+  'type' : 'appetizer',
+});
+
+export const MAIN = Object.freeze({
+  '티본스테이크' : 55000,
+  '바비큐립' : 54000,
+  '해산물파스타' : 35000,
+  '크리스마스파스타' : 25000,
+  'type' : 'main',
+});
+
+export const DESERT = Object.freeze({
+  '초코케이크' : 15000,
+  '아이스크림' : 5000,
+  'type' : 'desert',
+});
+
+export const DRINK = Object.freeze({
+  '제로콜라' : 3000,
+  '레드와인' : 60000,
+  '샴페인' : 25000,
+  'type' : 'drink',
+});
+
+export const MENU = [APPETIZER, MAIN, DESERT, DRINK];
+
+export const NAME = Object.freeze({
+  type : 'type',
+  appetizer : 'appetizer',
+  main : 'main',
+  desert : 'desert',
+  drink : 'drink',
+});
+
+export const KNIFE = Object.freeze({
+  namePosition : 0,
+  quantityPosition : 1,
+  bladePosition : '-'
+});

리뷰: 이 부분은 `-` 로 쪼갰을때 나오는 배열의 index를 가져오기 위한 상수 맞을까요? 그렇다면 구조분해할당 쓰면 더 깔끔할 것 같아요! 그렇게 된다면 `KNIFE `상수명보다는 `delimiter`나 `seperator`로 바꾸는것도 좋을 것 같아요!
@@ -0,0 +1,14 @@
+export const ERROR_DATE = Object.freeze({
+  basic : '[ERROR] 유효하지 않은 날짜입니다. 다시 입력해 주세요.',
+  minDate : 1,
+  maxDate : 31,
+});
+
+export const ERROR_MENU = Object.freeze({
+  basic : '[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요.',
+  onlyDrink : '[ERROR] 음료만 주문 시, 주문할 수 없습니다.',
+  maxOrder : '[ERROR] 메뉴는 한 번에 최대 20개까지만 주문할 수 있습니다.',
+  orderAmountExample : '(e.g. 시저샐러드-1, 티본스테이크-1, 크리스마스파스타-1, 제로콜라-3, 아이스크림-1의 총개수는 7개)',
+  minOrderNumber : 1,
+  maxOrderNumber : 20,
+});

리뷰: `ERROR_MENU`에는 에러와 관련된것만 있으면 좋을 것 같은데, 11,12,13 line은 조금 애매한 것 같습니다!
`ERROR_MENU`-> `MENU`로 바꾸고, 그 안에 `ERROR`로 한번 더 감싸는건 어떨지 추천하고 갑니당!
@@ -0,0 +1,41 @@
+import { BENEFIT_MESSEAGE } from "./BenefitStorage.js";
+import { EVENT_NAME } from "./BenefitStorage.js";
+
+export const priceFilter = (priceNumber) => new Intl.NumberFormat('ko-KR').format(priceNumber);
+
+export const merageFoodInfo = (foodName, foodAmount) => `${foodName} ${foodAmount}개`;
+
+export const PRICE_REFINER = Object.freeze({
+  positive : (priceNumber) => `${priceFilter(priceNumber)}원`,
+  negative : (priceNumber) => {
+    if (priceNumber === 0) return `${priceNumber}원`;
+
+    return `-${priceFilter(priceNumber)}원`;
+  },
+});
+
+export const isNotApplicableBenefits = (benefitList) => {
+  const benefitsResultArray = [];
+  for (let benefitResult of benefitList.values()) {
+    if (benefitResult !== 0) benefitsResultArray.push(benefitResult);
+  }
+  if (benefitsResultArray.length === 1) return true;
+
+  if (!benefitList.get(EVENT_NAME.condition)) return true;
+
+  return false;
+};
+
+export const BENEFITS_REFINER = Object.freeze({
+  benfitList : (benefitList) => {
+    if (isNotApplicableBenefits(benefitList)) return [BENEFIT_MESSEAGE.non];
+    
+    const refinedBenefits = [];
+    benefitList.forEach((value, key) => {
+      if (value !==0 && typeof(value) !== 'boolean') {
+        refinedBenefits.push(`${BENEFIT_MESSEAGE[key]}${PRICE_REFINER.negative(value)}`);   
+      }
+    });
+    return refinedBenefits;
+  },
+});

리뷰: 해당 객체의 경우 positive, negative속성을 나누지말고 처음부터 3가지 조건문으로 바로 검사하면 어떨까요?
@@ -0,0 +1,41 @@
+import { BENEFIT_MESSEAGE } from "./BenefitStorage.js";
+import { EVENT_NAME } from "./BenefitStorage.js";
+
+export const priceFilter = (priceNumber) => new Intl.NumberFormat('ko-KR').format(priceNumber);
+
+export const merageFoodInfo = (foodName, foodAmount) => `${foodName} ${foodAmount}개`;
+
+export const PRICE_REFINER = Object.freeze({
+  positive : (priceNumber) => `${priceFilter(priceNumber)}원`,
+  negative : (priceNumber) => {
+    if (priceNumber === 0) return `${priceNumber}원`;
+
+    return `-${priceFilter(priceNumber)}원`;
+  },
+});
+
+export const isNotApplicableBenefits = (benefitList) => {
+  const benefitsResultArray = [];
+  for (let benefitResult of benefitList.values()) {
+    if (benefitResult !== 0) benefitsResultArray.push(benefitResult);
+  }
+  if (benefitsResultArray.length === 1) return true;
+
+  if (!benefitList.get(EVENT_NAME.condition)) return true;
+
+  return false;
+};
+
+export const BENEFITS_REFINER = Object.freeze({
+  benfitList : (benefitList) => {
+    if (isNotApplicableBenefits(benefitList)) return [BENEFIT_MESSEAGE.non];
+    
+    const refinedBenefits = [];
+    benefitList.forEach((value, key) => {
+      if (value !==0 && typeof(value) !== 'boolean') {
+        refinedBenefits.push(`${BENEFIT_MESSEAGE[key]}${PRICE_REFINER.negative(value)}`);   
+      }
+    });
+    return refinedBenefits;
+  },
+});

리뷰: 혹시 얘네도 상수라고 볼 수 있는데 카멜케이스로 작성하신 이유가 있을까요?
@@ -0,0 +1,41 @@
+import { BENEFIT_MESSEAGE } from "./BenefitStorage.js";
+import { EVENT_NAME } from "./BenefitStorage.js";
+
+export const priceFilter = (priceNumber) => new Intl.NumberFormat('ko-KR').format(priceNumber);
+
+export const merageFoodInfo = (foodName, foodAmount) => `${foodName} ${foodAmount}개`;
+
+export const PRICE_REFINER = Object.freeze({
+  positive : (priceNumber) => `${priceFilter(priceNumber)}원`,
+  negative : (priceNumber) => {
+    if (priceNumber === 0) return `${priceNumber}원`;
+
+    return `-${priceFilter(priceNumber)}원`;
+  },
+});
+
+export const isNotApplicableBenefits = (benefitList) => {
+  const benefitsResultArray = [];
+  for (let benefitResult of benefitList.values()) {
+    if (benefitResult !== 0) benefitsResultArray.push(benefitResult);
+  }
+  if (benefitsResultArray.length === 1) return true;
+
+  if (!benefitList.get(EVENT_NAME.condition)) return true;
+
+  return false;
+};
+
+export const BENEFITS_REFINER = Object.freeze({
+  benfitList : (benefitList) => {
+    if (isNotApplicableBenefits(benefitList)) return [BENEFIT_MESSEAGE.non];
+    
+    const refinedBenefits = [];
+    benefitList.forEach((value, key) => {
+      if (value !==0 && typeof(value) !== 'boolean') {
+        refinedBenefits.push(`${BENEFIT_MESSEAGE[key]}${PRICE_REFINER.negative(value)}`);   
+      }
+    });
+    return refinedBenefits;
+  },
+});

리뷰: 여기 !==뒤에 띄어쓰기 1번 해야할 것 같아요!
@@ -0,0 +1,81 @@
+import Supervisor from "../domain/Supervisor.js";
+import InputView from "../InputView.js";
+import OutputView from "../OutputView.js";
+
+class EventPlanner {
+  #supervisor;
+
+  constructor() {
+    this.#supervisor = new Supervisor();
+  }
+  
+  async start() {
+    OutputView.printIntroduce();
+    
+    await this.getDate();
+    await this.getMenu();
+
+    this.plannerResult(); 
+  }
+
+  async getDate() {
+    try {
+      this.#supervisor.dateUpload(await InputView.readDate());
+
+    } catch (error) {
+      OutputView.printErrorMesseage(error);
+      await this.getDate();
+    }  
+  }
+
+  async getMenu() {
+    try {
+      this.#supervisor.menuUpload(await InputView.readMenu());
+      
+    } catch (error) {
+      OutputView.printErrorMesseage(error);
+      await this.getMenu();
+    }
+  }
+
+  plannerResult() {
+    OutputView.printProlog(this.#supervisor.event().date());
+    this.orderMenu();
+    this.totalOrderAmount();
+    this.freebieMenu();
+    this.benefitList();
+    this.totalBenefitAmount();
+    this.finalPaymentAmount();
+    this.badge();
+  }
+  
+  orderMenu() {
+    OutputView.printOrderMenuResult(this.#supervisor.cashier().foodsListWithQuantity());
+  }
+
+  totalOrderAmount() {
+    OutputView.printTotalOrderAmountResult(this.#supervisor.cashier().totalFoodsPrice());
+  }
+
+  freebieMenu() {
+    OutputView.printFreebieMenuResult(this.#supervisor.cashier().freebieMenu());
+  }
+
+  benefitList() {
+    OutputView.printBenefitListResult(this.#supervisor.benefitList());
+  }
+
+  totalBenefitAmount() {
+    OutputView.printTotalBenefitAmountResult(this.#supervisor.totalBenefitAmount());
+  }
+
+  finalPaymentAmount() {
+    OutputView.printFinalPaymentAmountResult(this.#supervisor.finalPaymentAmount());
+  }
+
+  badge() {
+    OutputView.printBadgeResult(this.#supervisor.giveBadge());
+  }
+}
+
+export default EventPlanner;

리뷰: 해당 부분은 따로 함수로 안빼고 `OutputView.print~`로 바로 넣어도 괜찮지 않을까 합니다!
각각의 함수에서 따로 추가적인 기능이 있는게 아니라서, OutputView로 바로 들어가도 좋을 것 같아요!
@@ -0,0 +1,70 @@
+import Food from "./Food.js";
+import { ERROR_MENU } from "../constants/ErrorMesseage.js";
+import { merageFoodInfo } from "../constants/ViewRefiner.js";
+import { DISCOUNT, BENEFIT_MESSEAGE } from "../constants/BenefitStorage.js";
+import { NAME } from "../constants/FoodStorage.js";
+
+class Cashier {
+  #foods = [];
+
+  constructor(orderHistory) {
+    this.#enrollFoods(orderHistory);
+    this.#orderDuplicationValidator();
+    this.#onlyDrinkValidator();
+    this.#orderMaxValidator();
+  }
+
+  #enrollFoods(orderHistory) {
+    orderHistory
+      .split(',')
+      .forEach((food) => this.#foods.push(new Food(food)));
+  }
+
+  #orderDuplicationValidator() {
+    const foodNameList = this.#foods.map((food) => food.name());
+    if (foodNameList.length !== new Set(foodNameList).size) {
+      throw new Error(ERROR_MENU.basic);
+    }
+  }
+
+  #onlyDrinkValidator() {
+    const drinkTypeFoodsList = this.#foods.filter((food) => food.type() === NAME.drink);
+
+    if (drinkTypeFoodsList.length === this.#foods.length) {
+      throw new Error(ERROR_MENU.onlyDrink);
+    }
+  }
+
+  #orderMaxValidator() {
+    if (this.#totalFoodsQuantity() > ERROR_MENU.maxOrderNumber) {
+      throw new Error(`${ERROR_MENU.maxOrder}\n${ERROR_MENU.orderAmountExample}`);
+    }
+  }
+
+  #totalFoodsQuantity() {
+    return this.#foods.reduce((acc,cur) => acc + cur.quantity(), 0);
+  }
+
+  foodsListWithQuantity() {
+    return this.#foods.map((foodInfo) => merageFoodInfo(foodInfo.name(), foodInfo.quantity()));
+  }
+
+  totalFoodsPrice() {
+    return this.#foods.reduce((acc, cur) => acc + cur.totalPrice(), 0); 
+  }
+
+  totalTypeQuantity(foodType) {
+    return this.#foods
+      .filter((food) => food.type() === foodType)
+      .reduce((acc, cur) => acc + cur.quantity(), 0);
+  }
+
+  freebieMenu() {
+    if (this.totalFoodsPrice() >= DISCOUNT.freebieStandard) {
+      return DISCOUNT.freebieItem;
+    }
+    return BENEFIT_MESSEAGE.non;
+  }
+}
+
+export default Cashier;

리뷰: import 순서도 맞춰주면 좋을 것 같아요! 예를 들어 constants부분도 알파벳 순으로 import해준다거나,,!
@@ -0,0 +1,70 @@
+import Food from "./Food.js";
+import { ERROR_MENU } from "../constants/ErrorMesseage.js";
+import { merageFoodInfo } from "../constants/ViewRefiner.js";
+import { DISCOUNT, BENEFIT_MESSEAGE } from "../constants/BenefitStorage.js";
+import { NAME } from "../constants/FoodStorage.js";
+
+class Cashier {
+  #foods = [];
+
+  constructor(orderHistory) {
+    this.#enrollFoods(orderHistory);
+    this.#orderDuplicationValidator();
+    this.#onlyDrinkValidator();
+    this.#orderMaxValidator();
+  }
+
+  #enrollFoods(orderHistory) {
+    orderHistory
+      .split(',')
+      .forEach((food) => this.#foods.push(new Food(food)));
+  }
+
+  #orderDuplicationValidator() {
+    const foodNameList = this.#foods.map((food) => food.name());
+    if (foodNameList.length !== new Set(foodNameList).size) {
+      throw new Error(ERROR_MENU.basic);
+    }
+  }
+
+  #onlyDrinkValidator() {
+    const drinkTypeFoodsList = this.#foods.filter((food) => food.type() === NAME.drink);
+
+    if (drinkTypeFoodsList.length === this.#foods.length) {
+      throw new Error(ERROR_MENU.onlyDrink);
+    }
+  }
+
+  #orderMaxValidator() {
+    if (this.#totalFoodsQuantity() > ERROR_MENU.maxOrderNumber) {
+      throw new Error(`${ERROR_MENU.maxOrder}\n${ERROR_MENU.orderAmountExample}`);
+    }
+  }
+
+  #totalFoodsQuantity() {
+    return this.#foods.reduce((acc,cur) => acc + cur.quantity(), 0);
+  }
+
+  foodsListWithQuantity() {
+    return this.#foods.map((foodInfo) => merageFoodInfo(foodInfo.name(), foodInfo.quantity()));
+  }
+
+  totalFoodsPrice() {
+    return this.#foods.reduce((acc, cur) => acc + cur.totalPrice(), 0); 
+  }
+
+  totalTypeQuantity(foodType) {
+    return this.#foods
+      .filter((food) => food.type() === foodType)
+      .reduce((acc, cur) => acc + cur.quantity(), 0);
+  }
+
+  freebieMenu() {
+    if (this.totalFoodsPrice() >= DISCOUNT.freebieStandard) {
+      return DISCOUNT.freebieItem;
+    }
+    return BENEFIT_MESSEAGE.non;
+  }
+}
+
+export default Cashier;

리뷰: 해당 부분도 split부분이니까 따로 상수로 만들어줘도 좋을 것 같습니다!
@@ -0,0 +1,62 @@
+package baseball;
+
+
+import java.util.List;
+
+public class GameUtil {
+
+    public void runGame() {
+
+        if (runOnlyOnceGame()) {
+            showMenu();
+        }
+    }
+
+    public boolean runOnlyOnceGame() {
+
+        Computer computer = new Computer();
+        List<Integer> computers = computer.makeNumbers();
+
+        return gameResult(computers);
+    }
+
+    private boolean gameResult(List<Integer> computers) {
+        boolean threeStrike = true;
+        while (threeStrike) {
+
+            Player player = new Player();
+            List<Integer> playerNumbers = player.makeNumbers();
+            Referee referee = new Referee();
+
+            String result = referee.informStrikeBall(computers, playerNumbers);
+            System.out.println(result);
+            threeStrike = isGame(threeStrike, result);
+        }
+
+        return true;
+    }
+
+    private boolean isGame(boolean game, String result) {
+        if (result.equals("3스트라이크")) {
+            System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
+            game = false;
+        }
+        return game;
+    }
+
+    private void showMenu() {
+        ScannerUtil scannerUtil = new ScannerUtil();
+        System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
+
+        int choice = scannerUtil.insertInt();
+        if (choice == 1) {
+            runGame();
+        }
+
+        while (choice != 1 && choice != 2) {
+            System.out.println("잘못 입력하셨습니다. 다시입력해주세요.");
+            choice = scannerUtil.insertInt();
+        }
+        System.out.println("수고하셨습니다.");
+    }
+}

리뷰: Util 이라는 이름의 클래스는 적합하지 않은 것 같아요 :)

`유틸 클래스`는 보통 실용성이나 유용성에 중점을 둔 정적 메서드들을 모아두고 여러 곳에서 호출하는 형식으로 사용하며 여러 곳에서 호출하기 때문에 유틸 클래스는 공통적인 로직을 다루도록 만들어야하며 합니다.

개인적으로는 실제로는 이러한 유틸 클래스의 메서드를 변경했을 때 영향이 너무 크기 때문에 최대한 사용을 지양하는 것을 선호합니다 :)
@@ -0,0 +1,62 @@
+package baseball;
+
+
+import java.util.List;
+
+public class GameUtil {
+
+    public void runGame() {
+
+        if (runOnlyOnceGame()) {
+            showMenu();
+        }
+    }
+
+    public boolean runOnlyOnceGame() {
+
+        Computer computer = new Computer();
+        List<Integer> computers = computer.makeNumbers();
+
+        return gameResult(computers);
+    }
+
+    private boolean gameResult(List<Integer> computers) {
+        boolean threeStrike = true;
+        while (threeStrike) {
+
+            Player player = new Player();
+            List<Integer> playerNumbers = player.makeNumbers();
+            Referee referee = new Referee();
+
+            String result = referee.informStrikeBall(computers, playerNumbers);
+            System.out.println(result);
+            threeStrike = isGame(threeStrike, result);
+        }
+
+        return true;
+    }
+
+    private boolean isGame(boolean game, String result) {
+        if (result.equals("3스트라이크")) {
+            System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
+            game = false;
+        }
+        return game;
+    }
+
+    private void showMenu() {
+        ScannerUtil scannerUtil = new ScannerUtil();
+        System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
+
+        int choice = scannerUtil.insertInt();
+        if (choice == 1) {
+            runGame();
+        }
+
+        while (choice != 1 && choice != 2) {
+            System.out.println("잘못 입력하셨습니다. 다시입력해주세요.");
+            choice = scannerUtil.insertInt();
+        }
+        System.out.println("수고하셨습니다.");
+    }
+}

리뷰: 파일 마지막에 엔터(개행문자)를 넣어주세요 :)

이유는 리뷰를 진행할 때 깃허브에서 경고메시지를 지우고 혹시 모르는 파일 읽기 오류에 대비하기 위함입니다.

좀 더 알고싶으시면 참고 링크를 보셔도 재밌을 것 같네요 :)

Intellij 를 사용하실 경우엔Preferences -> Editor -> General -> Ensure line feed at file end on save 를 체크해주시면파일 저장 시 마지막에 개행문자를 자동으로 넣어줍니다!

https://minz.dev/19https://stackoverflow.com/questions/729692/why-should-text-files-end-with-a-newline
@@ -0,0 +1,62 @@
+package baseball;
+
+
+import java.util.List;
+
+public class GameUtil {
+
+    public void runGame() {
+
+        if (runOnlyOnceGame()) {
+            showMenu();
+        }
+    }
+
+    public boolean runOnlyOnceGame() {
+
+        Computer computer = new Computer();
+        List<Integer> computers = computer.makeNumbers();
+
+        return gameResult(computers);
+    }
+
+    private boolean gameResult(List<Integer> computers) {
+        boolean threeStrike = true;
+        while (threeStrike) {
+
+            Player player = new Player();
+            List<Integer> playerNumbers = player.makeNumbers();
+            Referee referee = new Referee();
+
+            String result = referee.informStrikeBall(computers, playerNumbers);
+            System.out.println(result);
+            threeStrike = isGame(threeStrike, result);
+        }
+
+        return true;
+    }
+
+    private boolean isGame(boolean game, String result) {
+        if (result.equals("3스트라이크")) {
+            System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
+            game = false;
+        }
+        return game;
+    }
+
+    private void showMenu() {
+        ScannerUtil scannerUtil = new ScannerUtil();
+        System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
+
+        int choice = scannerUtil.insertInt();
+        if (choice == 1) {
+            runGame();
+        }
+
+        while (choice != 1 && choice != 2) {
+            System.out.println("잘못 입력하셨습니다. 다시입력해주세요.");
+            choice = scannerUtil.insertInt();
+        }
+        System.out.println("수고하셨습니다.");
+    }
+}

리뷰: - 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
- UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.

프로그래밍 요구사항 중에 위와 같은 요구사항이 있었는데요. 이 부분을 어떻게 구현할지 생각해보시면 좋을 것 같습니다.
@@ -0,0 +1,61 @@
+package baseball;
+
+import java.util.List;
+
+public class Referee {
+
+    public int countBall(List<Integer> list1, List<Integer> list2) {
+
+        int count = 0;
+        int strike = countStrike(list1, list2);
+
+        for (Integer number : list1) {
+            count = getCount(list2, count, number);
+        }
+        return count - strike;
+    }
+
+    public int countStrike(List<Integer> list1, List<Integer> list2) {
+
+        int count = 0;
+        for (int index = 0; index < 3; index++) {
+            count = getCountStrike(list1, list2, count, index);
+        }
+        return count;
+    }
+
+    public String informStrikeBall(List<Integer> list1, List<Integer> list2) {
+
+        int ball = countBall(list1, list2);
+        int strike = countStrike(list1, list2);
+
+        if (strike == 3) {
+            return strike + "스트라이크";
+        }
+
+        if (strike == 0 && ball != 0) {
+            return ball + "볼";
+        }
+
+        if (strike != 0 && ball != 0) {
+            return ball + "볼 " + strike + "스트라이크";
+        }
+
+        return "낫싱";
+    }
+
+    private int getCountStrike(List<Integer> list1, List<Integer> list2, int count, int index) {
+        if (list1.get(index) == list2.get(index)) {
+            count++;
+        }
+        return count;
+    }
+
+    private int getCount(List<Integer> list2, int count, Integer number) {
+        if (list2.contains(number)) {
+            count++;
+        }
+        return count;
+    }
+
+}

리뷰: Referee 클래스의 인스턴스는 어떤 상태(내부 필드)도 가지지 않기 때문에 이 클래스의 모든 객체들은 동일한 객체이겠네요 !

너무 많은 상태를 가지는 것은 좋은 설계가 아니지만, 아무것도 가지지 않는 방식 또한 바람직한 설계는 아닙니다.

적절한 상태를 가진 객체를 설계해보면 좋을 것 같아요.

다른 클래스들에도 함께 적용되는 피드백일 것 같습니다 :)
@@ -0,0 +1,61 @@
+package baseball;
+
+import java.util.List;
+
+public class Referee {
+
+    public int countBall(List<Integer> list1, List<Integer> list2) {
+
+        int count = 0;
+        int strike = countStrike(list1, list2);
+
+        for (Integer number : list1) {
+            count = getCount(list2, count, number);
+        }
+        return count - strike;
+    }
+
+    public int countStrike(List<Integer> list1, List<Integer> list2) {
+
+        int count = 0;
+        for (int index = 0; index < 3; index++) {
+            count = getCountStrike(list1, list2, count, index);
+        }
+        return count;
+    }
+
+    public String informStrikeBall(List<Integer> list1, List<Integer> list2) {
+
+        int ball = countBall(list1, list2);
+        int strike = countStrike(list1, list2);
+
+        if (strike == 3) {
+            return strike + "스트라이크";
+        }
+
+        if (strike == 0 && ball != 0) {
+            return ball + "볼";
+        }
+
+        if (strike != 0 && ball != 0) {
+            return ball + "볼 " + strike + "스트라이크";
+        }
+
+        return "낫싱";
+    }
+
+    private int getCountStrike(List<Integer> list1, List<Integer> list2, int count, int index) {
+        if (list1.get(index) == list2.get(index)) {
+            count++;
+        }
+        return count;
+    }
+
+    private int getCount(List<Integer> list2, int count, Integer number) {
+        if (list2.contains(number)) {
+            count++;
+        }
+        return count;
+    }
+
+}

리뷰: 임의의 숫자를 사용하는 매직넘버는소스 코드를 읽기 어렵게 만드는데요 !

이 부분을 어떻게 개선할 수 있을까요? 관련 링크 남겨놓겠습니다 :)

https://www.slipp.net/questions/356
@@ -0,0 +1,60 @@
+package baseball;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RefereeTest {
+
+    @Test
+    @DisplayName("두 개의 리스트에서 몇 개의 숫자가 같은지 확인")
+    void countBall() throws Exception {
+
+        //given
+        Referee referee = new Referee();
+        List<Integer> list1 = Arrays.asList(1, 2, 3);
+        List<Integer> list2 = Arrays.asList(3, 1, 2);
+
+        //when
+        int ball = referee.countBall(list1, list2);
+
+        //then
+        assertThat(ball).isEqualTo(3);
+    }
+
+    @Test
+    @DisplayName("두 개의 리스트에서 같은 자리에 같은 숫자가 몇 개 있는지 확인")
+    void countStrike() throws Exception {
+
+        //given
+        Referee referee = new Referee();
+        List<Integer> list1 = Arrays.asList(1, 2, 3);
+        List<Integer> list2 = Arrays.asList(1, 2, 3);
+
+        //when
+        int strike = referee.countStrike(list1, list2);
+
+        //then
+        assertThat(strike).isEqualTo(3);
+    }
+
+    @Test
+    @DisplayName("볼, 스트라이크 갯수 알려주기")
+    void ballStrikeCount() throws Exception {
+
+        //given
+        Referee referee = new Referee();
+        List<Integer> list1 = Arrays.asList(1, 2, 3);
+        List<Integer> list2 = Arrays.asList(1, 2, 3);
+
+        //when
+        String inform = referee.informStrikeBall(list1, list2);
+
+        //then
+        assertThat(inform).isEqualTo("3스트라이크");
+    }
+}

리뷰: 해당 테스트 메서드에서 예외를 선언을 하는 특별한 이유가 없다면 지워주세요 :)

테스트 메서드에 예외 선언을 함으로 써`해당 테스트가 실패할 수도 있다`라는 느낌을 주는 것 같습니다.