본문 바로가기
Developer/후기

[FE] 우아한 테크코스 6기 프리코스 4주차 회고: 크리스마스 이벤트 플래너

by 청량리 물냉면 2023. 11. 14.
반응형
 

 

시작

3주차 미션 목표는 클래스 분리, 단위 테스트 연습이었다.

이번 주차에서 중점으로 삼아야 하는 목표는 클래스 분리 심화이다.

주어진 요구사항에 맞추어서 클래스 분리에 신경쓰며 과제를 진행해 보기로 했다.

함수 분리와 커밋 메시지 컨벤션 지키기도 역시 주의하며 진행할 예정이다.

 

 

기능 요구 사항

크리스마스 이벤트 구현하기

 

구현 기능 목록

구현한 기능 목록은 다음과 같다.  

입력받기 
[ ✔ ] 식당 방문 예상 날짜 (숫자만)
[ ✔ ] 주문할 메뉴와 메뉴 개수(e.g. 해산물파스타-2,레드와인-1)

예외 
[ ✔ ]  식당 방문 예상 날짜: 숫자가 아닌 경우
[ ✔ ]  식당 방문 예상 날짜: 1 ~ 31 범위를 벗어난 숫자를 입력한 경우
[ ✔ ]  주문할 메뉴와 메뉴 개수: 메뉴판에 없는 메뉴를 입력한 경우
[ ✔ ]  주문할 메뉴와 메뉴 개수: 1개 미만의 수를 입력한 경우
[ ✔ ]  주문할 메뉴와 메뉴 개수: 메뉴 형식이 지정된 형식과 다른 경우
[ ✔ ]  주문할 메뉴와 메뉴 개수: 메뉴를 중복 입력한 경우

계산하기
[ ✔ ] 할인 및 증정 메뉴에 따라 총 혜택 금액 계산 (총 혜택 금액 = 할인 금액의 합계 + 증정 메뉴의 가격) 

[ ✔ ] 크리스마스 이벤트에 따라 할인 및 증정 메뉴 계산
    [ ✔ ] 크리스마스 디데이 할인 계산
    [ ✔ ] 평일 할인 계산
    [ ✔ ] 주말 할인 계산
    [ ✔ ] 특별 할인 계산
[ ✔ ] 증정 이벤트 계산
[ ✔ ] 이벤트 배지 계산

계산하기 (주의 사항)
[ ✔ ] 총주문 금액 10000원 이상인 경우에만 이벤트 적용
[ ✔ ] 음료만 주문 시 주문 불가
[ ✔ ] 메뉴는 최대 20개까지만 주문 가능

결과 출력하기 

[ ✔ ] 주문 메뉴

[ ✔ ] 할인 전 총주문 금액
[ ✔ ] 증정 메뉴
[ ✔ ] 혜택 내역
[ ✔ ] 총 혜택 금액
[ ✔ ] 할인 후 예상 결제 금액
[ ✔ ] 12월 이벤트 배지 내용

 

폴더 구조  설계

src
  ├── App.js
  ├── index.js
  ├── planner
  │   ├── eventData.js
  │   ├── EventPlanner.js
  │
  ├── utils
  │   ├── constants.js
  │   ├── DateUtils.js
  │   ├── InputValidation.js
  │
  ├── views
  │   ├── InputView.js
  │   ├── OutputView.js

 

 

소감

이번 과제는 이전의 과제와는 달리 요구사항도 많고 예외 처리할 것도 많은 편이었다. 따라서 처음에는 난이도가 이전 과제보다 훨씬 높게 느껴졌지만, 리드미에 요구 사항을 정리한 뒤 하나씩 구현하다 보니 예상보다 수월하게 과제를 완성할 수 있었다.

이번 과제에서는 이전과 달리 Unit Test라는 개념을 숙지하고 주요 함수마다 테스트를 적용해 보았다. 처음에는 이벤트 계산에 필요한 값을 계산하는 private 함수들까지 테스트 해 보려 했지만, private로 정의된 함수들은 테스트하지 않는 것이 좋다는 조언을 참고하여 public 함수 위주로 테스트를 진행했다. public 함수를 테스트함으로써 연계된 private 함수의 기능을 테스트할 수 있도록 최대한 하나의 기능을 정확히 수행하는 함수를 작성하였다.

또한 이번 과제에서는 도메인 로직과 UI 로직을 분리하기 위해 노력했습니다. 이를 위해 EventPlanner 클래스에는 도메인 로직을, OutputView에는 화면에 출력되는 내용을 작성하였다. 다만 작동하는 프로그램이 완성되자 도메인 로직을 담은 EventPlanner 클래스 길이가 너무 길다는 사실에 고민이 되었다. 함수를 계산 로직/출력 로직으로 구분할까도 생각해 봤지만, 모든 함수가 클래스와 관련성이 높았기 때문에 우선은 그대로 유지하였다.
프리코스를 진행하며 하나의 기능만 담당하도록 함수 분리하는 것에는 이제 어느 정도 익숙해졌지만, 클래스 분리는 아직도 어려운 점이 많다. 클래스 분리와 관련해서는 더 공부하고 적용해 보아야 할 것 같다.

이로써 4주간의 모든 과제가 마무리되었다.
프리코스를 진행하면서 가장 많이 성장한 것은 테스트 코드 작성 능력이었다.
이전까지는 코드를 수정할 때마다 일일이 애플리케이션을 실행시켜 예외 사항을 테스트했었는데, 이제는 테스트 코드를 통해 내 프로그램이 제대로 작동하는지를 간단히 테스트해 볼 수 있게 되었다. 테스트 코드의 유용함을 체감하였기 때문에, 앞으로도 테스트 코드 관련 공부를 꾸준히 해나갈 생각이다.
또한 과제가 끝날 때마다 동료 참가자분들의 다양한 코드와 코드 리뷰를 살펴보면서 많은 도움을 받았다. 코드 리뷰를 직접 받은 적은 없지만 다른 사람의 코드와 코드 리뷰를 살펴보는 것만으로도 제가 놓쳤던 사소한 코딩 습관(forEach대신 for문 사용 등)이나 컨벤션 사용 오류 등 많은 부분에 있어 개선을 이룰 수 있었다. 많은 사람이 더 나은 코드를 위해 고민하는 모습을 보면서 저도 어떻게 하면 더 좋은 코드를 작성할 수 있을지 고민하는 기회를 가졌다.
그 외에도 함수 분리나 클래스 분리, 커밋 컨벤션, 자바스크립트 컨벤션을 지키고 다른 사람의 눈의 직관적인 코드를 작성하기 위해 노력하는 등의 과정을 통해 프로그래밍에 대한 이해를 높이고 프로그래머로서 한 층 더 성장할 수 있었다.

앞으로도 프리코스에서 배운 모든 내용을 잊지 않고 프로그래밍에 적용하여 다른 개발자와 소통할 수 있는 코드를 작성하는 프로그래머가 되고 싶다.

 

 

새롭게 학습한 내용

🎆 도메인 로직 vs 서비스 로직

도메인 로직과 서비스 로직은 소프트웨어 개발에서 특정 역할과 책임을 가지는 코드를 나타내는 용어이다.

 

도메인 로직 (Domain Logic)
도메인 로직은 주로 비즈니스 도메인에 집중한 코드를 나타낸다. 즉, 실제 문제 도메인에 특화된 비즈니스 규칙, 규칙 검증, 상태 관리 등을 다루는 코드를 의미한다. 주로 엔터프라이즈 애플리케이션에서는 이러한 도메인 로직이 전체 시스템의 핵심이 된다.

예를 들어 은행 애플리케이션에서 계좌의 잔액을 갱신하거나, 주문 처리와 같은 비즈니스 도메인에 특화된 작업들은 도메인 로직에 해당한다. 도메인 로직은 주로 도메인 모델을 기반으로 하며, 해당 도메인의 엔터티, 밸류 등과 상호작용한다.


서비스 로직 (Service Logic)

서비스 로직은 주로 다양한 업무 로직을 처리하는 코드를 의미한다. 이는 특정 도메인에 종속되지 않는 비즈니스 로직이며, 여러 도메인 간의 연동, 외부 시스템과의 통합, 데이터 처리 등을 다룬다. 서비스 로직은 주로 업무 프로세스를 관리하고, 각 단계 간의 흐름을 제어한다.
예를 들어, 사용자 인증, 데이터 검증, 메일 발송과 같은 기능들은 서비스 로직에 해당한다. 서비스 로직은 도메인과는 조금 떨어져 있을 수 있으며, 여러 도메인에서 공통으로 사용되는 기능들을 담당한다.

요약
도메인 로직: 주로 비즈니스 도메인에 특화된 로직으로, 도메인 모델과 상호작용하여 비즈니스 규칙을 다룬다.
서비스 로직: 다양한 업무 로직을 처리하는 코드로, 특정 도메인에 종속되지 않는 비즈니스 로직을 다루며, 서비스의 기능적인 부분을 담당한다.

이 둘은 종종 혼용되어 사용될 수 있으며, 애플리케이션의 구조 및 규모에 따라 다르게 해석될 수 있다. 하지만 일반적으로는 도메인 로직은 특정 도메인에 관한 비즈니스 규칙을 다루고, 서비스 로직은 다양한 업무 로직을 처리한다.

 

🎆 접근자

 

JavaScript - 접근자 프로퍼티 (getter, setter)

접근자 프로퍼티(accessor property) : 값이 없음. 프로퍼티를 읽거나 쓸 때 호출하는 함수를 값 대신에 지정할 수 있는 프로퍼티입니다. 접근자 프로퍼티의 본질은 함수인데, 이 함수는 값을 획득(get)

velog.io

 

🎆 정규식

 

RegExp.prototype.test() - JavaScript | MDN

test() 메서드는 주어진 문자열이 정규 표현식을 만족하는지 판별하고, 그 여부를 true 또는 false로 반환합니다.

developer.mozilla.org

 

 

📚 JavaScript 정규 표현식 문법 총정리 + 응용 예제

정규 표현식(Regular Expression) 정규식(Regular Expression)은 문자열에서 특정 내용을 찾거나 대체 또는 발췌하는데 사용된다. 대표적으로 입력칸에 전화번호나 이메일을 입력하라고 했을때 옳지 않은

inpa.tistory.com

 

🎆 object 사용하기 (object의 정보 불러오기)

만약 #orderedList에 다음과 같은 구조로 데이터가 들어있다면

#orderedList = 
[
  {
    '해산물파스타': { price: 35000, category: '메인', count: 2 }
  },
  {
    '레드와인': { price: 60000, category: '음료', count: 1 }
  }
]

 

Object.values(item)[0]각 주문에 대한 정보이다.

첫 번째 주문인 '해산물파스타'에 대해서는 { price: 35000, category: '메인', count: 2 }가 되고, 두 번째 주문인 '레드와인'에 대해서는 { price: 60000, category: '음료', count: 1 }가 된다.

 

ex) Object.values('해산물파스타')[0] = { price: 35000, category: '메인', count: 2 }

 

🎆 스트코드: jest - expect.stringContaining()

test("printEventBenefits(): 혜택 내역 출력", () => {
    const totalDiscount = 30000;
    const benefits = [10000, 0, 20000, 0, 0];

    const expectedOutput = [
      "<혜택 내역>",
      "크리스마스 디데이 할인: -10,000원",
      "주말 할인: -20,000원",
    ];

    OutputView.printEventBenefits(totalDiscount, benefits);
    expect(Console.print).toHaveBeenCalledTimes(3);

    expectedOutput.forEach((expected) => {
      expect(Console.print).toHaveBeenCalledWith(
        expect.stringContaining(expected)
      );
    });
  });

위의 코드는 배열 전체를 순회하면서 각각의 기대 문자열에 대해 expect.stringContaining(expected)을 사용하도록 한 코드이다.

이렇게 하면 배열의 각 요소에 대해 독립적으로 확인할 수 있다.

위와 같이 코드를 짬으로써 각각의 요소가 포함되었는지의 여부를 독립적으로 확인할 수 있다.

 

🎆 깃 커밋 컨벤션

 

[Git] 내가 보려고 정리하는 Commit Message Convention

티스토리를 처음 시작하면서, 처음 개발 글 시리즈로 작성했던 것이 "개발자로서 협업을 할 때, 같은 팀원끼리 필수로 정해야 하는 규칙"에 대한 글이었다. 그동안 써왔던 글들을 순차적으로 살

mini-min-dev.tistory.com

 

 

제출 소스 코드

https://github.com/Yoonyesol/javascript-christmas-6-Yoonyesol

 

 

 

 

4주차까지 미션 제출 완료

반응형