
정말 우당탕탕 굴러갔던 4주간의 프리코스가 끝났네요,, 4주차는 1~3주차 피드백을 모두 반영해서 무조건 예쁜 코드로 짜겠다는 마음을 먹고 시작했지만 놀랍게도 피드백은 커녕 기능 구현하기에 바빴던 과제 였습니다.. 일단 정말 제가 짠 코드 중 가장 스파게티 코드, 로직 이었습니다.. 또한, 예제 테스트 케이스는 통과는 했는데 로직이 결국 잘못되었음을 깨닫고 마음이 와르르 맨션이었지만 우선 회고는 해야 하니깐 작성해보겠어요 🍅

📂 폴더 구조
📦src
┣ 📂constants
┃ ┣ 📜ErrorMessage.js
┃ ┣ 📜IOMessage.js
┃ ┗ 📜MagicNumber.js
┣ 📂controller
┃ ┣ 📜Controller.js
┃ ┗ 📜productPurchase.js
┣ 📂data
┃ ┣ 📜productsData.js
┃ ┗ 📜promotionData.js
┣ 📂model
┃ ┣ 📜Membership.js
┃ ┣ 📜Products.js
┃ ┣ 📜Promotion.js
┃ ┣ 📜PurchasedList.js
┃ ┗ 📜Receipt.js
┣ 📂service
┃ ┣ 📜InputService.js
┃ ┣ 📜MembershipService.js
┃ ┣ 📜PromotionService.js
┃ ┗ 📜StockCheckService.js
┣ 📂utils
┃ ┣ 📂validator
┃ ┃ ┗ 📜InputValidator.js
┃ ┣ 📜formatInput.js
┃ ┣ 📜formatProductList.js
┃ ┗ 📜parseCSV.js
┣ 📂view
┃ ┣ 📜InputView.js
┃ ┗ 📜OutputView.js
┣ 📜App.js
┗ 📜index.js
📂 constants : ErrorMessage (에러 메시지), IOMessage (입출력 메시지), MagicNumber (상수 값)
📂 controller : controller(유효성 검사~멤버십 여부까지
📂 data: 프로모션, 재고 데이터 Md
📂 model: membership(멤버십 여부 관리), products(재고 관리), promotion(프로모션 관리), purchasedList(사용자 구매 목록 관리) , receipt(영수증 관리)
📂 service : InputService(사용자 입력 파싱), MembershipService(멤버십 적용), PromotionService(프로모션 적용), StockChec kService(재고 확인)
📂 utils
> 📂 validators : InputValidator(유효성 검사 클래스)
formatInput(사용자 입력 분리 함수), formatProductList(재고 목록 포매팅 함수), parseCSV(CSV 파일 파싱 함수)
-> 일단 딱 봐도 아시겠지만, '함수 및 메서드 10줄 이내' 라는 규칙을 지키기 위해서 굳이 함수 하나 더 만들고 그 안에서 호출하는 이상한 행동을,,많이 했습니다 (그렇지만 이것 역시 챌린징이라고 생각 중..)
이번 미션의 쟁점
1. 프로모션 재고 관리(2+1, 1+1 ...)
- Buy N get 1 의 원리로 N개 사면 1개를 더 주는 로직인데, 프로모션이 있는 상품은 프로모션 재고를 먼저 소진해야 했습니다.
1) 만약 2+1 인데 사용자가 2개만 들고온 경우 -> 1개 무료증정 받을 수 있음 안내 후 , 사용자가 받을지 여부 결정
1-1) 사용자가 Y 를 선택한 경우 : 무료 증정 받을 수 있는 상품 추가
1-2) 사용자가 N 을 선택한 경우 : 무료 증정 받을 수 있는 상품 추가하지 않음
2) 프로모션 재고 이상으로 가져온 경우 -> 일부 상품은 프로모션 혜택 없이 결제됨을 안내 후, 사용자가 그래도 구매할지 여부 결정
2-1) 사용자가 Y를 선택한 경우: 일부 수량에 대해 정가로 결제
2-2) 사용자가 N을 선택한 경우: 정가로 결제해야 하는 수량을 제외하고 결제 진행
1-1. 프로모션 기간이 정해져 있는데, 프로모션 기간 외에는 재고를 어떻게 차감할 것인지?
프로모션 기간 중이라면 프로모션 재고를 우선적으로 차감하며, 프로모션 재고가 부족할 경우에는 일반 재고를 사용한다.
프로모션 기간 중이 아니라면 -> 프로모션 재고가 결국 일반 재고와 우선순위가 동일해진다고 판단하여 프로모션 기간 종료 후에는 일반 재고와 합산해야 한다는게 개인적인 의견
2. 프로모션 재고만 있고 일반 재고는 0개인 경우
- MD 파일을 수정하면 된다, 안된다 이런 얘기도 많았고 수많은 3/4의 결과를 만들어낸 장본인,, 그치만 ,, 일단 답은 MD 파일 수정이 아닌 재고가 0개일 때의 처리 였던 것으로 보입니다. 아래 보면 오렌지 주스, 탄산수에 대한 부분이 프로모션 없는 일반 재고가 0개인 경우가 테스트 케이스에 있었는데 마크다운에는 없었던 케이스 ,,
test("파일에 있는 상품 목록 출력", async () => {
await run({
inputs: ["[콜라-1]", "N", "N"],
expected: [
/* prettier-ignore */
"- 콜라 1,000원 10개 탄산2+1",
"- 콜라 1,000원 10개",
"- 사이다 1,000원 8개 탄산2+1",
"- 사이다 1,000원 7개",
"- 오렌지주스 1,800원 9개 MD추천상품",
"- 오렌지주스 1,800원 재고 없음",
"- 탄산수 1,200원 5개 탄산2+1",
"- 탄산수 1,200원 재고 없음",
"- 물 500원 10개",
"- 비타민워터 1,500원 6개",
"- 감자칩 1,500원 5개 반짝할인",
"- 감자칩 1,500원 5개",
"- 초코바 1,200원 5개 MD추천상품",
"- 초코바 1,200원 5개",
"- 에너지바 2,000원 5개",
"- 정식도시락 6,400원 8개",
"- 컵라면 1,700원 1개 MD추천상품",
"- 컵라면 1,700원 10개",
],
});
});
이번 미션 스스로 아쉬웠던 점
1. 역할 분리 (SRP 원칙 지키기)
- 프로모션 적용에 대한 로직을 product 에서 재고를 관리한다는 이유로,, products 모델에 메서드를 둔 점이 매우 아쉬워요 🥲
사실 프로모션을 적용하는 부분은 promotion 클래스에서 하는게 맞은데, promotion 클래스엔 기간 관련 유효성 검사만 두고 applyPromotion 메서드를 두지 않았다. 이건 초기에 설계부터 ...

2. 설계 및 MVC 패턴 적용
- 내가 이해한 MVC: view에서는 UI 를 표시하고, model에서는 데이터를 처리하는 로직을 담고 있고, controller에서는
사용자 요청을 처리하고, 모델과 뷰 사이의 상호작용을 관리하는 것
- 내가 구현한 MVC:
View - 입, 출력 관련 메시지를 띄우는 역할
Controller - 데이터를 가공, 로직을 실행하여 모델과 뷰를 연결하는 역할 (Model, View 연결)
InputService(입력값 파싱 및 유효성 검사) -> processProductPurchase(구매리스트에 추가) -> handlePromotion(프로모션 적용) -> receipt(영수증에 아이템 추가) -> updateStock (재고 업데이트) -> handleMembership(멤버십)
Model - 데이터를 관리하고 보관하는 역할
PurchasedList, Products, Membership, Promotion, Receipt 5개로 나누고, Service에는 각 모델의 메서드를 순서대로 묶어놓았습니다
Service - 비즈니스 로직
여기서 바로 아쉬운 부분이 나옵니다,, Service에서 비즈니스 로직을 처리했어야 하는데 Model에 비즈니스 로직을 다 때려넣고 그 로직들의 메서드 길이를 줄이기 위해 순서를 짜집기한 함수를 넣어 버렸습니다.. 어떤건 클래스고 어떤건 또 함수네요 :)
3. 프로모션 로직
- > 이 부분은 수식에 오류가 있어 세부적으로 다음 글에서 톺아보겠어요

4주간의 느낀 점 🍅
1. '몰입' 에 대해 알게 되다.
일단 글을 쓰고 있는 지금,, 프리코스 여파로 몸에 병을 얻어서 정상적이지 못한 상태로 쓰고 있다는 점,, ㅠㅠ 근데 진짜 4주간 프리코스를 하면서 '몰입' 이라는 것에 대해 배울 수 있었던 것 같아요 ! 디코 채널에 동물원이라고 있는데, 거기 고정 멤버들과 함께 밤샘 코딩을 이틀 정도 했습니다 (무려 이틀이나,,) 근데 사람의 의지란 원래 혼자 하면 더 자고 싶고,, 그런법인데 진짜 같이 하니까 멀쩡하게 버틴거 있죠? 아마 극한의 상황이라 더 그런 것 같긴한데,, 그래도 같이 버텨주신 동물원 멤버들 너무 감사합니다
2. 왜 이 코드를 쓰는지에 대해 이유를 찾게 되다.
코드리뷰, 스터디를 통해서도 정말 많이 배웠습니다 ! 물론 어느 코드가 정답이다 이건 없지만 적어도 제가 설계한것 보단 나은게 뭔지를 알 수 있겠더라구요 ! 다른 코드에서 참고한 부분을 사용하면서 그 코드가 어떤 장점이 있고, 어떤 이유에서 사용하는지에 대해서도 스스로 찾아서 공부해보고, 공식 문서들을 많이 참고해볼 수 있었다는 장점도 있었습니다! 또한, 개발에 있어서 많은 분들이 고민하는 주제(유효성 검사 위치 등) 에 대해 함께 고민해볼 수 있게 되었어요 ! 1차 결과가 어떻게 나올지 모르겠지만, 우선 최종 코테 열심히 준비해볼 생각입니다 ㅎㅎ 다시 구현해볼 수 있다는 장점,, !!!! 이것도 꽤나 큰 재미라고 생각해요 :) 이 글을 보신 우테코 프리코스 7기 많은 분들과도 우테코에서 함께할 수 있으면 너무 좋을 것 같아요 😃🍅 마지막 주차 과제, 혹은 앞으로의 계획에 대해 나누고 싶으신 분들 언제든 디코에서 만나요 (토마토 프로필을 찾아주세요)

'우아한 테크코스 > 우당탕탕 우테코 프리코스' 카테고리의 다른 글
| 우당탕탕 우테코 7기 최종 코테 후기 🔥 (3) | 2024.12.15 |
|---|---|
| 우당탕탕 우테코 7기 3주차 프리코스 회고 🔥 (2) | 2024.11.05 |
| 우당탕탕 우테코 7기 2주차 프리코스 회고 🔥 (3) | 2024.10.29 |
| 우당탕탕 우테코 7기 1주차 프리코스 회고 🔥 (6) | 2024.10.22 |