@@ -0,0 +1,167 @@
+## 한 줄로 표현하는 핵심 기능!
+
+> 🎄날짜와 주문 내역의 조건에 맞춰 12월 할인 이벤트를 적용하기
+
+---
+
+### 기능 요구 사항
+
+1️⃣ 12월 이벤트와 관련된 정보 입력받기
+
+-[x] 인삿말 출력
+-[x] 예상 방문 날짜 입력받기
+    -[x] ⚠️ 유효하지 않은 값을 받았을 때 예외처리
+        -[x] 숫자를 입력하지 않았을 때
+        -[x] 1일에서 31일 사이의 수가 아닐 때: *[ERROR] 유효하지 않은 날짜입니다. 다시 입력해 주세요.*
+    -[x] 유효하지 않은 값을 입력받았을 경우, 유효한 값을 입력할 때까지 다시 입력받기
+-[x] 주문 메뉴 입력받기
+    -[x] ⚠️ 유효하지 않은 값을 받았을 때 예외처리
+        -[x] 메뉴판에 없는 메뉴를 입력하는 경우: *[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요.*
+        -[x] 메뉴의 주문 개수가 1 이상의 숫자가 아닌 경우: *[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요.*
+        -[x] 음료만 주문한 경우: *[ERROR] 음료만 주문할 수 없습니다. 다시 입력해 주세요.*
+        -[x] 메뉴 형식이 예시와 다른 경우
+            -[x] `메뉴명-개수`의 형식으로 이루어져 있지 않은 경우
+            -[x] `메뉴명-개수`가 ,를 통해 구분되지 않는 경우
+        -[x] 중복 메뉴를 입력한 경우: *[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요.*
+        -[x] 주문한 메뉴의 총 개수가 20개를 초과한 경우: *[ERROR] 메뉴는 최대 20개까지만 주문할 수 있습니다. 다시 입력해 주세요.*
+    -[x] 유효하지 않은 값을 입력받았을 경우, 유효한 값을 입력할 때까지 다시 입력받기
+
+2️⃣ 주문 메뉴 출력하기
+
+-[x] 입력받은 주문 메뉴 출력
+    -[x] 주문 메뉴의 출력 순서는 자유롭게 : 🔥에피타이저 - 메인 - 디저트 - 음료 순서면 더 좋을 것 같다
+    -[x] 포멧: 메뉴 "{메뉴 이름} {x개}"   ex) 제로콜라 1개
+
+3️⃣ 할인 전 총주문 금액: MenuService
+
+-[x] 할인 전 총주문 금액 출력
+    -[x] `메뉴의 가격 * 수량`의 총 합계
+
+4️⃣ 증정 메뉴✨
+
+-[x] 총 주문 금액을 확인하고, 금액에 따라 증정 여부 결정
+    -[x] 전달받은 날짜를 통해 증정 여부 결정
+        -[x] `총주문 금액`이 `120,000원` 이상인 경우, 증정 개수 1로 설정
+        -[x] `총주문 금액`이 `120,000원` 미만인 경우, 증정 개수 0으로 설정
+    -[x] 조건에 따라 증정 결과 출력
+        -[x] `총주문 금액`이 `120,000원` 이상인 경우, "샴페인 n개" 출력
+        -[x] `총주문 금액`이 `120,000원` 미만인 경우, "없음" 출력
+
+5️⃣ 혜택 내역✨ : DiscountService -> EventService
+
+-[x] 혜택을 받을 수 있는 조건인지 확인
+    -[x] `총주문금액`이 10,000원 이상인지 확인
+-[x] 크리스마스 디데이 할인
+    -[x] 1일부터 25일 사이의 날짜에만 이벤트 적용
+    -[x] 1일에 1000원부터 시작하여, 하루가 지날수록 100원씩 추가 할인
+    -[x] "크리스마스 디데이 할인: -1,200원" 형태로 출력
+-[x] 평일 할인
+    -[x] 일요일~목요일 진행
+    -[x] `디저트`메뉴를 `1개당 2023원` 할인
+    -[x] "평일 할인: -4,046원" 형태로 출력. 단 할인이 안되는 경우, 출력을 별도로 하지 않음
+-[x] 주말 할인
+    -[x] 금요일~토요일 진행
+    -[x] `메인`메뉴를 `1개당 2,023원` 할인
+    -[x] "주말 할인: -1,000원" 형태로 출력. 단 할인이 안되는 경우, 출력을 별도로 하지 않음
+-[x] 특별 할인
+    -[x] 이벤트 달력에 별이 있는 경우(매주 일요일 + 25일)
+    -[x] `총 금액`에서 `1000원` 할인
+    -[x] "특별 할인: -1,000원" 형태로 출력. 단 할인이 안되는 경우, 출력을 별도로 하지 않음
+-[x] 혜택 내역에 대해 출력
+    -[x] 포맷은 {종류} 할인: -{할인 가격}원. 이 때, 가격은 1000의 단위로 쉼표(,)를 넣는다
+    -[x] 만일, 모든 혜택을 받지 못한 경우에는 "없음"으로 표시한다
+
+6️⃣ 총혜택 금액 : DiscountService -> EventService
+
+-[x] 총혜택 금액에 대해 계산 및 출력
+    -[x] 크리스마스 디데이, 평일, 특별, 증정 이벤트 할인을 모두 합한 가격을 표시한다 (총 할인 금액 + 증정 메뉴의 가격)
+    -[x] 앞에 -가 붙으며, 1000의 단위마다 쉼표(,)를 추가한다
+
+7️⃣ 할인 후, 예상 결제 금액
+
+-[x] 할인 후 예상 결제 금액에 대해 계산 및 출력
+    -[x] `할인 전 총주문 금액` - `총혜택 금액`을 계산한 결과를 출력한다
+    -[x] 1000의 단위마다 쉼표(,)를 추가한다
+
+8️⃣ 12월 이벤트 배지
+
+-[x] 이벤트 배지: `총 혜택 금액`에 따라 배지 부여 및 출력
+    -[x] 이벤트 배지에 대해 계산
+        -[x] 5000 <= x < 10,000 : 별
+        -[x] 10,000 <= x < 20,000 : 트리
+        -[x] 20,000 <= x : 산타
+
+---
+
+### 프로그래밍 요구 사항
+
+-[x] ApplicationTest의 모든 테스트가 성공해야 한다.
+-[x] indent depth는 2까지 허용한다.
+-[x] 메서드의 길이가 15를 넘어가지 않도록 한다.
+-[x] 사용자가 잘못된 값을 입력한 경우, `IllegalArgumentException`을 발생시키고, `[ERROR]`로 시작하는 에러 메시지를 출력한 후, 그 부분부터 입력을 다시 받는다.
+-[x] 입력과 출력을 담당하는 클래스를 별도로 구현한다.
+    -[x] InputView: readDate()...
+    -[x] OutputView : printMenu()...
+-[x] Console.readLine()을 활용한다.
+
+---
+
+### 3주차 피드백 내용
+
+-[x] 3주차 공통피드백 지키기!
+-[x] `Integer.parseInt()`를 사용하면 정수의 범위가 아닐 때에도 예외가 발생하는데, 예외 메시지르 조금 더 꼼꼼하게 챙기자
+-[x] Enum에서 문자열을 합칠 때 `+`보다는, `String.format()`을 사용하자
+-[x] `System.lineSeperator()`와 `String.format("%n")`은 같은 역할을 한다. 활용해보자!
+-[x] 요구사항을 꼼꼼하게 읽자. (세자리마다 쉼표를 넣어준다던지...)
+-[x] 상수를 enum으로 뺐으면 이를 활용하자! 매직 넘버의 사용을 줄이자! 확장성을 고려한 구조를 만들자!
+-[x] 예외를 다시 받는 방법으로 재귀를 사용했는데, 메모리가 터질 가능성이 있다. `Supplier`를 도입해보자.
+-[x] 검증(Validate)과 파싱(Parsing)의 로직을 어디에 두면 좋을까? 고민해보자.
+-[x] 디미터의 법칙!
+-[x] `Console.close()`를 통해 사용 완료한 콘솔을 닫아주자
+
+---
+
+### 개발 중 작성하는 리팩토링 목록
+
+-[x] IoC 컨테이너 적용하기
+-[x] Enum이 너무 우후죽순 생긴 것 같다! 정리할 수 있는 부분은 정리해보자
+-[x] InputView, OutputView에서 `readLine()`과 `System.out.print` 부분 추상화하기
+-[x] `Supplier`를 이용하여 재입력 처리하기
+-[x] Validator(검증)의 역할이 적절하게 분배되어 있는지 확인
+    -[x] MenuService의 validate 함수들에 대해 중복되어있는 코드 처리하기
+-[x] MenuService의 코드가 조금 난잡한 것 같음
+-[x] Message의 %n에 대해 어떻게...처리 좀 하기
+-[ ] Parser에서 parseToDate, parseToAmount의 코드가 겹친다. 전달하는 예외 메세지만 다른데... 방법을 찾아보자.
+-[x] DiscountResult에 너무 많은 책임이 있는 것 같다! DiscountService에게 책임을 더 부여하자.  
+ -> DiscountResult -> EventResult -> EventService로 변경 및 역할 부여
+-[x] 메서드, 변수명이 적절한지 확인 후 수정
+-[x] 메뉴를 잘못입력했을 때 `IndexOutOfBounds`가 발생하면서 종료된다.
+-[x] OutputView에서 formatting을 하면서 겹치는 코드가 곳곳에 있다. 수정하자!
+
+---
+
+### 구현하면서 집중했던 부분들! 고민거리!
+
+#### ✅ Discountable(Eventable로 변경) 인터페이스에 제너릭을 적용하자
+
+> 🧐 고민 내용 🧐  
+> 크리스마스 디데이, 증정 이벤트, 평일 할인, 주말 할인, 특별 할인 모두 각자만의 고유한 할인 조건들이 있다.
+> 크리스마스 디데이와 증정이벤트는 `총 주문 금액`과 `날짜`를 확인하면 됐는데, 이들은 모두 int형으로 처리가 가능했다.
+>
+> 하지만 평일, 주말 할인은 `날짜`만 받는 것이 아니라, 메뉴에 대한 최소한의 정보가 추가적으로 필요했다.  
+> 모든 할인 클래스들이 공통으로 가지고 있어야 하는 것들을 `Discountable 인터페이스(Eventable 인터페이스로 변경)`로 표현하고 싶은데 어떻게 하면 좋을까?
+
+이에 대해 생각난 해답은 바로 `제너릭`을 사용하는 것이었다.  
+`제너릭`을 사용하면 `canDiscount`의 매개변수에 자료형에 상관없이 전달하고 싶은 데이터를 전달할 수 있기 때문이다.  
+따라서 `Discountable` 인터페이스의 `canDiscount()`의 매개변수로 전달되는 조건(`condition`) `제너릭 <T>`를 적용했다.
+
+<br>
+
+#### ✅ View에서 적절히 변환해서 전달하자. 꼭 String으로 전달할 필요가 없다.
+
+<br>
+
+#### ✅ 다른 계층과 데이터를 주고 받을 때에는 DTO를 이용하자.
+
+
+

리뷰: 제네릭을 사용해 Discountable로 표현한 것이 매우 인상깊네요! 코드 리뷰할때도 보면서 공부하도록 하겠습니다 🫡