ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,46 @@
+import { ERROR_DATE, ERROR_MENU } from "../constants/ErrorMesseage.js";
+import { MENU, KNIFE } from "../constants/FoodStorage.js";
+
+export const dateValidator = (date) => {
+  if (
+    date.includes(' ') ||
+    date.includes('.') ||
+    Number.isNaN(Number(date)) ||
+    !Number.isInteger(Number(date)) ||
+    Number(date) < ERROR_DATE.minDate ||
+    Number(date) > ERROR_DATE.maxDate
+  ) {
+    throw new Error(ERROR_DATE.basic);
+  }
+};
+
+export const nonFoodInMenu = (foodName) => {
+  const foodType = MENU
+    .filter((type) => Object.hasOwn(type, foodName));
+
+  if (foodType.length === 0) {
+    return true;
+  }
+  return false;
+};
+
+export const nonFoodQuantity = (foodQuantity) => {
+  if (foodQuantity < ERROR_MENU.minOrderNumber) {
+    return true;
+  }
+  return false;
+};
+
+export const foodValidator = (foodInfo) => {
+  if (
+    foodInfo.length !== 2 ||
+    foodInfo[KNIFE.quantityPosition].includes('.') ||
+    foodInfo[KNIFE.quantityPosition].includes(' ') ||
+    Number.isNaN(Number(foodInfo[KNIFE.quantityPosition])) ||
+    !Number.isInteger(Number(foodInfo[KNIFE.quantityPosition])) ||
+    nonFoodInMenu(foodInfo[KNIFE.namePosition]) ||
+    nonFoodQuantity(Number(foodInfo[KNIFE.quantityPosition]))
+  ) {
+    throw new Error(ERROR_MENU.basic);
+  }
+};

리뷰: `if` 문 내부에서 검증하는 것들이 너무 많아서 오히려 가독성이 떨어져 보일 수도 있을 것 같아요,,!

이 부분을 정규표현식을 활용한다면 가독성 향상에 도움이 될 수 있을 것 같아요!
@@ -0,0 +1,110 @@
+import {
+  priceFilter,
+  PRICE_REFINER,
+  merageFoodInfo,
+  BENEFITS_REFINER,
+  isNotApplicableBenefits
+} from "../src/constants/ViewRefiner.js";
+
+test('숫자를 천단위로 잘라서 문자로 변환되는지 테스트', () => {
+  const NUMBER = 1234567890;
+  const PRICE_STRING = '1,234,567,890';
+  
+  expect(priceFilter(NUMBER)).toEqual(PRICE_STRING);
+});
+
+test('숫자가 0일경우 문자로 0원을 반환한다', () => {
+  const PRICE = 0;
+  const RESULT = '0원';
+
+  expect(PRICE_REFINER.negative(PRICE)).toEqual(RESULT);
+});
+
+test('숫자가 0이 아니라면 천단위로 잘라 마이너스와 원을 붙여 문자로 반환한다', () => {
+  const PRICE = 1500000;
+  const RESULT = '-1,500,000원';
+
+  expect(PRICE_REFINER.negative(PRICE)).toEqual(RESULT);
+});
+
+test('음식 이름과 수량을 잘 짝지어 주는지 테스트', () => {
+  const FOOD_NAME = '시골된장찌개';
+  const FOOD_AMOUNT = '7';
+  const FOOD_NAME_WITH_AMOUNT = '시골된장찌개 7개';
+
+  expect(merageFoodInfo(FOOD_NAME, FOOD_AMOUNT)).toEqual(FOOD_NAME_WITH_AMOUNT);
+});
+
+test('혜택 내역이 하나도 없을때(키 condition의 value가 false) 없음이라는 문자만 담긴 배열을 반환한다', () => {
+  const map = new Map();
+  map
+    .set('christmas', 1000)
+    .set('weekday', 2023 * 1)
+    .set('weekend', 0)
+    .set('special', 0)
+    .set('freebie', 0)
+    .set('condition', false);
+
+  const BENEFITS_LIST = ['없음'];
+
+  expect(BENEFITS_REFINER.benfitList(map)).toEqual(BENEFITS_LIST);
+});
+
+test('키 condition의 value가 true라면 map에 담긴 정보를 최종 출력형식에 맞춰 문자 배열로 반환한다', () => {
+  const map = new Map();
+  map
+    .set('christmas', 1000 + (24 -1) * 100)
+    .set('weekday', 2023 * 10)
+    .set('weekend', 0)
+    .set('special', 1000)
+    .set('freebie', 25000)
+    .set('condition', true);
+
+  const BENEFITS_ARRAY = [
+    '크리스마스 디데이 할인: -3,300원',
+    '평일 할인: -20,230원',
+    '특별 할인: -1,000원',
+    '증정 이벤트: -25,000원'
+  ];
+
+  expect(BENEFITS_REFINER.benfitList(map)).toEqual(BENEFITS_ARRAY);
+});
+
+test('모든 혜택 할인금액이 0원이면 true를 반환한다', () => {
+  const map = new Map();
+  map
+    .set('christmas', 0)
+    .set('weekday', 0)
+    .set('weekend', 0)
+    .set('special', 0)
+    .set('freebie', 0)
+    .set('condition', true);
+
+  expect(isNotApplicableBenefits(map)).toEqual(true);
+});
+
+test('map 속의 conditon 의 value 가 false라면 true를 반환한다', () => {
+  const map = new Map();
+  map
+    .set('christmas', 2000)
+    .set('weekday', 2023)
+    .set('weekend', 0)
+    .set('special', 1000)
+    .set('freebie', 25000)
+    .set('condition', false);
+  
+  expect(isNotApplicableBenefits(map)).toEqual(true);
+});
+
+test('혜택 금액이 모두 0원이 아니면서 conditon의 value가 true라면 false를 반환한다', () => {
+  const map = new Map();
+  map
+    .set('christmas', 0)
+    .set('weekday', 0)
+    .set('weekend', 0)
+    .set('special', 0)
+    .set('freebie', 25000)
+    .set('condition', true);
+  
+  expect(isNotApplicableBenefits(map)).toEqual(false);
+});

리뷰: 혜택 내역을 map에서 관리 하다보니 출력 형태로 변환하는 로직이 다소 복잡해졌습니다. 해당 로직은 그 역할을 해주는데 생각보다 복잡하고 실수를 많이 한 부분이라 테스트를 진행했습니다!
@@ -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;

리뷰: 리팩토링때 적용해보도록 하겠습니다! 👍
@@ -0,0 +1,84 @@
+import { dateValidator } from "../util/Validator.js";
+import {
+  DISCOUNT,
+  BADGE, 
+  BENEFIT_MESSEAGE
+} from "../constants/BenefitStorage.js";
+
+class Event {
+  #date;
+
+  constructor(date) {
+    dateValidator(date);    
+    this.#date = Number(date);
+  }
+
+  #week() {
+    const WEEK = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
+    
+    return WEEK[new Date(2023, 11, this.#date).getDay()];
+  }
+
+  date() {
+    return this.#date;
+  }
+
+  christmasDDayDiscount() {
+    if (this.#date <= DISCOUNT.christmasDate) {
+      return DISCOUNT.christmasBasic + (this.#date - 1) * DISCOUNT.christmasAccumulation;
+    }
+    return DISCOUNT.zero;
+  }
+
+  weekdayDiscount(desertQuantity) {
+    if (this.#week() !== 'FR' && this.#week() !== 'SA') {
+      return desertQuantity * DISCOUNT.weekday;
+    }
+    return DISCOUNT.zero;
+  }
+
+  weekendDiscount(mainQuantity) {
+    if (this.#week() === 'FR' || this.#week() === 'SA') {
+      return mainQuantity * DISCOUNT.weekend;
+    }
+    return DISCOUNT.zero;
+  }
+
+  specialDiscount() {
+    if (this.#week() === 'SU' || this.#date === DISCOUNT.christmasDate) {
+      return DISCOUNT.special;
+    }
+    return DISCOUNT.zero;
+  }
+
+  freebieDiscount(totalFoodsPriceBeforeDiscount) {
+    if (totalFoodsPriceBeforeDiscount >= DISCOUNT.freebieStandard) {
+      return DISCOUNT.freebiePrice;
+    }
+    return DISCOUNT.zero;
+  }
+
+  condition(totalFoodsPriceBeforeDiscount) {
+    if (totalFoodsPriceBeforeDiscount >= DISCOUNT.eventStandardAmount) {
+      return true;
+    }
+    return false;
+  }
+  
+  getBadge(totalBenefitAmount) { 
+    if (totalBenefitAmount < BADGE.star) {
+      return BENEFIT_MESSEAGE.non;
+    }
+    if (totalBenefitAmount >= BADGE.santa) {
+      return BADGE.santaName;
+    }
+    if (totalBenefitAmount >= BADGE.tree) {
+      return BADGE.treeName;
+    }
+    if (totalBenefitAmount >= BADGE.star) {
+      return BADGE.starName;
+    }
+  }
+}
+
+export default Event;

리뷰: 상수 처리는 하였지만 지금 다시 봐도 클래스 내에서 선언한 부분은 말씀대로 많이 아쉬운 것 같습니다ㅠ 요일의 이름을 풀네임을 할지도 고민이었는데 두 글자로도 충분할 것 같아 약어를 사용하였습니다.
@@ -0,0 +1,49 @@
+import { foodValidator } from "../util/Validator.js";
+import { 
+  MENU,
+  NAME,
+  KNIFE
+} from "../constants/FoodStorage.js";
+
+class Food {
+  #name;
+
+  #quantity;
+
+  constructor(food) {
+    foodValidator(this.#enrollFood(food));
+  }
+   
+  #enrollFood(food) {
+    const foodInfoArray = food.split(KNIFE.bladePosition); 
+    this.#name = foodInfoArray[KNIFE.namePosition];
+    this.#quantity = Number(foodInfoArray[KNIFE.quantityPosition]);
+
+    return foodInfoArray;
+  }
+
+  #category() {
+    const [foodTypeInfo] = MENU
+      .filter((foodType) => Object.hasOwn(foodType, this.#name));
+  
+    return foodTypeInfo;
+  }
+
+  type() {
+    return this.#category()[NAME.type];
+  }
+
+  name() {
+    return this.#name;
+  }
+  
+  quantity() {
+    return this.#quantity;
+  }
+
+  totalPrice() {
+    return this.#category()[this.#name] * this.quantity();
+  }
+}
+
+export default Food;

리뷰: get을 정확히 언제 붙여야 할지 고민이 됩니다. type 메서드의 경우 type을 가져오는 것이니 get을 붙여야 할지,
단순히 필드 값을 가져오는게 아니라  엄연히 로직이 구현 되어 있으니 food.type() 우로도 의미 전달히 충분한지 아직 햇갈리는 부분인 것 같습니다.ㅠㅠ
@@ -0,0 +1,106 @@
+import Cashier from "../src/domain/Cashier.js";
+
+describe('Cashier 클래스 유효성 테스트', () => {
+  test.each([
+    ['제로콜라-10'],
+    ['제로콜라-2,샴페인-4'],
+    ['샴페인-3,레드와인-1,제로콜라-2']
+  ])('음료만 주문시 예외처리', (input) => {
+    expect(() => new Cashier(input)).toThrow('[ERROR');
+  });
+
+  test.each([
+    ['아이스크림-3,초코케이크-4,아이스크림-1'],
+    ['티본스테이크-3,바비큐립-4,양송이수프-3,양송이수프-1'],
+    ['시저샐러드-1,제로콜라-1,제로콜라-1,시저샐러드-4,크리스마스파스타-1']
+  ])('주문한 음식 이름이 중복되면 예외처리', (input) => {
+    expect(() => new Cashier(input)).toThrow('[ERROR]');
+  });
+
+  test.each([
+    ['제로콜라-21'],
+    ['샴페인-3,양송이수프-10,시저셀러드-8,아이스크림-10'],
+    ['티본스테이크-22,레드와인-1']
+  ])('주문 수량이 20 초과시 예외처리', (input) => {
+    expect(() => new Cashier(input)).toThrow('[ERROR]');
+  });
+
+  test.each([
+    ['아이스크림-3.1'],
+    ['초코케이크-3.a'],
+    ['티본스테이크-a'],
+    ['크리스마스파스타-0.99']
+  ])('주문 수량이 올바른 형식이 아니면 예외처리', (input) => {
+    expect(() => new Cashier(input)).toThrow('[ERROR]');
+  });
+
+  test.each([
+    ['제로콜라-1,아이스크림-19'],
+    ['티본스테이크-20'],
+    ['시저샐러드-3,양송이수프-15,레드와인-2']
+  ])('올바르게 입력시 예외를 발생시키지 않는다', (input) => {
+    expect(() => new Cashier(input)).not.toThrow();
+  });
+});
+
+describe('Cashier 클래스 메서드 단위테스트', () => {
+  test('음식 이름과 수량을 잘 짝지어서 보여주는지 테스트', () => {
+    const ORDER_MENU = '티본스테이크-2,샴페인-3,초코케이크-4,시저샐러드-5,바비큐립-3,타파스-3';
+    const RESULT = [
+    '티본스테이크 2개',
+    '샴페인 3개',
+    '초코케이크 4개',
+    '시저샐러드 5개',
+    '바비큐립 3개',
+    '타파스 3개'
+    ];
+
+    const cashier = new Cashier(ORDER_MENU);
+
+    expect(cashier.foodsListWithQuantity()).toEqual(RESULT);
+  });
+
+  test('주문한 음식들의 총 가격을 잘 계산하는지 테스트', () => {
+    const ORDER_MENU = '아이스크림-4,티본스테이크-3,샴페인-2,시저샐러드-1';
+    const RESULT = (5000 * 4) + (55000 * 3) + (25000 * 2) + (8000 * 1);
+    const cashier = new Cashier(ORDER_MENU);
+
+    expect(cashier.totalFoodsPrice()).toEqual(RESULT);
+  });
+  
+  let typeIndex = 0
+  test.each([
+    ['appetizer'],
+    ['main'],
+    ['desert'],
+    ['drink']
+  ])('해당 주문에 지정한 타입음식의 총수량을 잘 계산하는지 테스트', (input) => {
+    const ORDER_MENU = 
+    '양송이수프-3,타파스-3,' +
+    '티본스테이크-1,해산물파스타-2,바비큐립-2,' +
+    '초코케이크-3,아이스크림-1,' + 
+    '제로콜라-2,샴페인-1';
+    
+    const RESULT = [6,5,4,3];
+    const cashier = new Cashier(ORDER_MENU);
+
+    expect(cashier.totalTypeQuantity(input)).toEqual(RESULT[typeIndex]);
+    typeIndex += 1;
+  });
+
+  test('주문 금액이 12만원 이상이면 샴페인 증정 해주는지 테스트', () => {
+    const ORDER_MENU = '티본스테이크-2,양송이수프-1,타파스-1';
+    const RESULT = '샴페인 1개';
+    const cashier = new Cashier(ORDER_MENU);
+
+    expect(cashier.freebieMenu()).toEqual(RESULT);
+  });
+
+  test('주문 금액이 12만원 미만이면 없음을 표시하는지 테스트', () => {
+    const ORDER_MENU = '티본스테이크-2,양송이수프-1';
+    const RESULT = '없음';
+    const cashier = new Cashier(ORDER_MENU);
+
+    expect(cashier.freebieMenu()).toEqual(RESULT);
+  });
+});

리뷰: 테스트 꼼꼼한거 너무 좋습니다! 👍 그런데 테스트문구 양식을 하나로 통일하면 좋을 것 같아요!
해당 문구처럼 `예외를 발생시키지 않는다`. 에 맞춰서 `예외처리` -> `예외를 발생시킨다` 로 통일하면 좋을 것 같습니다!
@@ -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;

리뷰: 혹시 출력과 관련된 포맷팅 부분을 도메인에서 처리한 이유가 있으실까요? 궁금합니다! 포맷팅해주는 것도 도메인의 역할이라고 생각하셨기 때문일까요?
@@ -1,7 +1,67 @@
-export default OutputView = {
-    printMenu() {
-        Console.print("<주문 메뉴>");
-        // ...
-    }
-    // ...
-}
+import { Console } from "@woowacourse/mission-utils";
+import { ANSWER } from "./constants/PlannerMesseage.js";
+import { PRICE_REFINER, BENEFITS_REFINER } from "./constants/ViewRefiner.js";
+
+const OutputView = {
+  printIntroduce() {
+    Console.print(ANSWER.introduce);
+  },
+  
+  printProlog(date) {
+    Console.print(`${ANSWER.prolog(date)}\n`);
+  },
+
+  printOrderMenuResult(foodsArray) {
+    Console.print(ANSWER.orderMenu);
+
+    foodsArray.forEach((food) => Console.print(food));
+    Console.print('');
+  },
+
+  printTotalOrderAmountResult(amount) {
+    Console.print(ANSWER.totalOrderAmount); 
+    
+    Console.print(PRICE_REFINER.positive(amount));
+    Console.print('');
+  },
+
+  printFreebieMenuResult(freebieMenu) {
+    Console.print(ANSWER.freebieMenu);
+
+    Console.print(freebieMenu);
+    Console.print('');
+  },
+
+  printBenefitListResult(benefitArray) {
+    Console.print(ANSWER.benefitList);
+
+    BENEFITS_REFINER.benfitList(benefitArray).forEach((benefit) => Console.print(benefit));
+    Console.print('');
+  },
+
+  printTotalBenefitAmountResult(totalBenefitAmount) {
+    Console.print(ANSWER.totalBenefitAmount);
+
+    Console.print(PRICE_REFINER.negative(totalBenefitAmount));
+    Console.print('');
+  },
+
+  printFinalPaymentAmountResult(finalPaymentAmount) {
+    Console.print(ANSWER.finalPaymentAmount);
+
+    Console.print(PRICE_REFINER.positive(finalPaymentAmount));
+    Console.print('');
+  },
+
+  printBadgeResult(badge) {
+    Console.print(ANSWER.DecemberEventBadge);
+
+    Console.print(badge);
+  },
+  
+  printErrorMesseage(messeage) {
+    Console.print(`${messeage}`);
+  }
+};
+
+export default OutputView;

리뷰: 해당부분 messeage 그냥 바로 출력해도 될것 같습니다!
@@ -1,7 +1,67 @@
-export default OutputView = {
-    printMenu() {
-        Console.print("<주문 메뉴>");
-        // ...
-    }
-    // ...
-}
+import { Console } from "@woowacourse/mission-utils";
+import { ANSWER } from "./constants/PlannerMesseage.js";
+import { PRICE_REFINER, BENEFITS_REFINER } from "./constants/ViewRefiner.js";
+
+const OutputView = {
+  printIntroduce() {
+    Console.print(ANSWER.introduce);
+  },
+  
+  printProlog(date) {
+    Console.print(`${ANSWER.prolog(date)}\n`);
+  },
+
+  printOrderMenuResult(foodsArray) {
+    Console.print(ANSWER.orderMenu);
+
+    foodsArray.forEach((food) => Console.print(food));
+    Console.print('');
+  },
+
+  printTotalOrderAmountResult(amount) {
+    Console.print(ANSWER.totalOrderAmount); 
+    
+    Console.print(PRICE_REFINER.positive(amount));
+    Console.print('');
+  },
+
+  printFreebieMenuResult(freebieMenu) {
+    Console.print(ANSWER.freebieMenu);
+
+    Console.print(freebieMenu);
+    Console.print('');
+  },
+
+  printBenefitListResult(benefitArray) {
+    Console.print(ANSWER.benefitList);
+
+    BENEFITS_REFINER.benfitList(benefitArray).forEach((benefit) => Console.print(benefit));
+    Console.print('');
+  },
+
+  printTotalBenefitAmountResult(totalBenefitAmount) {
+    Console.print(ANSWER.totalBenefitAmount);
+
+    Console.print(PRICE_REFINER.negative(totalBenefitAmount));
+    Console.print('');
+  },
+
+  printFinalPaymentAmountResult(finalPaymentAmount) {
+    Console.print(ANSWER.finalPaymentAmount);
+
+    Console.print(PRICE_REFINER.positive(finalPaymentAmount));
+    Console.print('');
+  },
+
+  printBadgeResult(badge) {
+    Console.print(ANSWER.DecemberEventBadge);
+
+    Console.print(badge);
+  },
+  
+  printErrorMesseage(messeage) {
+    Console.print(`${messeage}`);
+  }
+};
+
+export default OutputView;

리뷰: 제목 부분이라서 다 띄어쓰기를 하신걸까요? 꼼꼼합니다! 👍
@@ -0,0 +1,40 @@
+export const DISCOUNT = Object.freeze({
+  christmasDate : 25,
+  christmasBasic : 1000,
+  christmasAccumulation : 100,
+  weekday : 2023,
+  weekend : 2023,
+  special : 1000,
+  freebieItem : '샴페인 1개',
+  freebieStandard : 120000,
+  freebiePrice : 25000,
+  eventStandardAmount : 10000,
+  zero : 0,  
+});
+
+export const EVENT_NAME = Object.freeze({
+  christmas : 'christmas',
+  weekday : 'weekday',
+  weekend : 'weekend',
+  special : 'special',
+  freebie : 'freebie',
+  condition : 'condition',
+});
+
+export const BADGE = Object.freeze({
+  star : 5000,
+  tree : 10000,
+  santa : 20000,
+  starName : '별',
+  treeName : '트리',
+  santaName : '산타',
+});
+
+export const BENEFIT_MESSEAGE = Object.freeze({
+  christmas : '크리스마스 디데이 할인: ',
+  weekday : '평일 할인: ',
+  weekend : '주말 할인: ',
+  special : '특별 할인: ',
+  freebie : '증정 이벤트: ',
+  non : '없음',  
+});

리뷰: 해당 샴페인은 string으로 넣기보다 선언해놓으신 상수 써도 좋을 것 같아요!
@@ -0,0 +1,40 @@
+export const DISCOUNT = Object.freeze({
+  christmasDate : 25,
+  christmasBasic : 1000,
+  christmasAccumulation : 100,
+  weekday : 2023,
+  weekend : 2023,
+  special : 1000,
+  freebieItem : '샴페인 1개',
+  freebieStandard : 120000,
+  freebiePrice : 25000,
+  eventStandardAmount : 10000,
+  zero : 0,  
+});
+
+export const EVENT_NAME = Object.freeze({
+  christmas : 'christmas',
+  weekday : 'weekday',
+  weekend : 'weekend',
+  special : 'special',
+  freebie : 'freebie',
+  condition : 'condition',
+});
+
+export const BADGE = Object.freeze({
+  star : 5000,
+  tree : 10000,
+  santa : 20000,
+  starName : '별',
+  treeName : '트리',
+  santaName : '산타',
+});
+
+export const BENEFIT_MESSEAGE = Object.freeze({
+  christmas : '크리스마스 디데이 할인: ',
+  weekday : '평일 할인: ',
+  weekend : '주말 할인: ',
+  special : '특별 할인: ',
+  freebie : '증정 이벤트: ',
+  non : '없음',  
+});

리뷰: 변수명에 가격이라는게 더 드러나면 좋을 것 같아요!
@@ -0,0 +1,40 @@
+export const DISCOUNT = Object.freeze({
+  christmasDate : 25,
+  christmasBasic : 1000,
+  christmasAccumulation : 100,
+  weekday : 2023,
+  weekend : 2023,
+  special : 1000,
+  freebieItem : '샴페인 1개',
+  freebieStandard : 120000,
+  freebiePrice : 25000,
+  eventStandardAmount : 10000,
+  zero : 0,  
+});
+
+export const EVENT_NAME = Object.freeze({
+  christmas : 'christmas',
+  weekday : 'weekday',
+  weekend : 'weekend',
+  special : 'special',
+  freebie : 'freebie',
+  condition : 'condition',
+});
+
+export const BADGE = Object.freeze({
+  star : 5000,
+  tree : 10000,
+  santa : 20000,
+  starName : '별',
+  treeName : '트리',
+  santaName : '산타',
+});
+
+export const BENEFIT_MESSEAGE = Object.freeze({
+  christmas : '크리스마스 디데이 할인: ',
+  weekday : '평일 할인: ',
+  weekend : '주말 할인: ',
+  special : '특별 할인: ',
+  freebie : '증정 이벤트: ',
+  non : '없음',  
+});

리뷰: 꼼꼼하십니당!! 👍👍👍
@@ -0,0 +1,40 @@
+export const DISCOUNT = Object.freeze({
+  christmasDate : 25,
+  christmasBasic : 1000,
+  christmasAccumulation : 100,
+  weekday : 2023,
+  weekend : 2023,
+  special : 1000,
+  freebieItem : '샴페인 1개',
+  freebieStandard : 120000,
+  freebiePrice : 25000,
+  eventStandardAmount : 10000,
+  zero : 0,  
+});
+
+export const EVENT_NAME = Object.freeze({
+  christmas : 'christmas',
+  weekday : 'weekday',
+  weekend : 'weekend',
+  special : 'special',
+  freebie : 'freebie',
+  condition : 'condition',
+});
+
+export const BADGE = Object.freeze({
+  star : 5000,
+  tree : 10000,
+  santa : 20000,
+  starName : '별',
+  treeName : '트리',
+  santaName : '산타',
+});
+
+export const BENEFIT_MESSEAGE = Object.freeze({
+  christmas : '크리스마스 디데이 할인: ',
+  weekday : '평일 할인: ',
+  weekend : '주말 할인: ',
+  special : '특별 할인: ',
+  freebie : '증정 이벤트: ',
+  non : '없음',  
+});

리뷰: 그리고 해당 `DISCOUNT` 상수에 이벤트와 관련된 모든 정보가 들어가있는데, 아예 크리스마스 이벤트, 평일 이벤트, 등등으로 상수를 쪼개거나, 혹은 중간에 공백라인을 넣으면 좋을 것 같아요! 구분되어있지 않다보니까 파악하기 조금 어려울 것 같아요!
@@ -0,0 +1,40 @@
+export const DISCOUNT = Object.freeze({
+  christmasDate : 25,
+  christmasBasic : 1000,
+  christmasAccumulation : 100,
+  weekday : 2023,
+  weekend : 2023,
+  special : 1000,
+  freebieItem : '샴페인 1개',
+  freebieStandard : 120000,
+  freebiePrice : 25000,
+  eventStandardAmount : 10000,
+  zero : 0,  
+});
+
+export const EVENT_NAME = Object.freeze({
+  christmas : 'christmas',
+  weekday : 'weekday',
+  weekend : 'weekend',
+  special : 'special',
+  freebie : 'freebie',
+  condition : 'condition',
+});
+
+export const BADGE = Object.freeze({
+  star : 5000,
+  tree : 10000,
+  santa : 20000,
+  starName : '별',
+  treeName : '트리',
+  santaName : '산타',
+});
+
+export const BENEFIT_MESSEAGE = Object.freeze({
+  christmas : '크리스마스 디데이 할인: ',
+  weekday : '평일 할인: ',
+  weekend : '주말 할인: ',
+  special : '특별 할인: ',
+  freebie : '증정 이벤트: ',
+  non : '없음',  
+});

리뷰: `star : { price :  5000, name : '별'}` 해당 형식은 어떨지 추천하고 갑니다!
@@ -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,
+});

리뷰: 해당 20도 상수로 빼면 좋을 것 같아요!