Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2단계 - 행운의 로또 미션] 곤이(김기융) 미션 제출합니다. #40

Merged
merged 15 commits into from
Mar 1, 2021

Conversation

yungo1846
Copy link

@yungo1846 yungo1846 commented Feb 24, 2021

안녕하세요! 곤이입니다.
항상 바쁘신 와중에도 소중한 시간 내주셔서 감사합니다 😀😀


이전 미션에서 추가로 다음과 같은 기능과 테스트를 추가했습니다.

🎯🎯 step2 당첨 결과 기능

  • 결과 확인하기 버튼을 누르면 당첨 통계, 수익률을 모달로 확인할 수 있다.
  • 로또 당첨 금액은 고정되어 있는 것으로 가정한다.
  • 다시 시작하기 버튼을 누르면 초기화 되서 다시 구매를 시작할 수 있다.

🔗 기능 상세

  • 당첨번호와 보너스 번호를 인풋으로 받는다.
    • 당첨번호와 보너스 번호는 중복되서는 안된다.
    • 당첨번호와 보너스 번호는 1 ~ 45
  • 결과 확인하기 버튼을 눌렀을 때의 다음과 같은 기능을 수행한다.
    • 당첨번호와 보너스 번호의 유효성을 검사한다.
    • 구입한 로또 번호와 일치하는 당첨번호의 개수를 확인한다.
    • 당첨금액을 합산하여 수익률을 계산한다.
    • 당첨 통계, 수익률을 확인할 수 있는 모달을 띄운다.
    • 다시 시작하기 버튼을 클릭한 경우 초기화 한다.

🎞 테스트 케이스

  • 구입 금액은 단위 금액의 양의 배수 값을 갖는다.
    • 몫은 양의 정수값, 나머지는 0인 값을 받는다.
  • 구입 금액을 입력한 뒤 버튼을 클릭했을 때, 알맞은 개수의 로또를 렌더링한다.
  • 토글 버튼을 클릭했을 때, 모든 복권 번호를 렌더링한다.
  • 적절한 당첨 번호를 입력 받는다.
    • 중복된 숫자를 입력받지 않는다.
    • 1 ~ 45의 숫자를 입력 받는다.
  • 결과 확인하기 버튼을 누르면 모달을 확인할 수 있다.
  • 다시 시작하기 버튼을 누르면 초기화 된다.

🙋‍♂️ 궁금한 점

카일과 미션을 진행하면서 커스텀 DOM 라이브러리를 만들어 사용해보았습니다. 커스텀 DOM 라이브러리를 직접 만들어서 사용하니 이전보다 더 코드를 깔끔하고 효율적으로 짤 수 있다는 생각을 했습니다. 그러나, 같은 DOM을 조회해도 생성자를 이용하기 때문에 인스턴스가 새로 생성된다는 점에서 더 좋은 방법이 있을지 고민하고 있습니다. 이 외에도 코드를 보시면서 보이는 문제점에 대해서 말씀해주시면 많은 도움이 될 것 같습니다!

이전 미션에서 DOM을 중복해서 조회하는 것보다 저장을 해놓는 편이 좋다는 피드백을 주셨습니다. 당시에는 말씀해주신대로 중복된 DOM 사용을 피하는 것이 당연하다고 생각하여 코드를 수정했습니다. 그러나 DOM을 공부하다보니 DOM의 속도는 자바스크립트 엔진과 비교해서 느리지 않다는 사실을 알게 됐습니다. DOM 조작의 경우에는 리플로우가 발생하여 최대한 DOM 조작을 최소화하는 것이 맞지만 단순히 DOM을 조회하는 것 역시 과연 비용이 클까? 라는 의문이 생겼습니다.

🧶데모 사이트


@pocojang pocojang requested a review from ysm-dev February 24, 2021 10:18
@yungo1846 yungo1846 force-pushed the step2 branch 4 times, most recently from 0d5364c to d69f3c1 Compare February 26, 2021 09:02
igy95 and others added 11 commits February 26, 2021 21:13
- rename file (camelCase)
- dependency injection
- DOM selector (class -> id, dataset)
- form tag event
- private field
- test valid winning numbers
- check winning numbers
- render winning result
- reset
- remove Parentnode
- check winning numbers
- check modal
- check reset
- change earning rate
Copy link

@ysm-dev ysm-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

카일과 미션을 진행하면서 커스텀 DOM 라이브러리를 만들어 사용해보았습니다. 커스텀 DOM 라이브러리를 직접 만들어서 사용하니 이전보다 더 코드를 깔끔하고 효율적으로 짤 수 있다는 생각을 했습니다. 그러나, 같은 DOM을 조회해도 생성자를 이용하기 때문에 인스턴스가 새로 생성된다는 점에서 더 좋은 방법이 있을지 고민하고 있습니다. 이 외에도 코드를 보시면서 보이는 문제점에 대해서 말씀해주시면 많은 도움이 될 것 같습니다!

  • 좋은 시도입니다. 👍

  • 다만 이렇게 많은 동작들이 추상화 되게 되면, 다양한 trade off가 있습니다.
    당장 작성하는 어플리케이션쪽 코드는 짧고 깔끔해질지 몰라도, 추상화 수준이 높아지면 높아질수록 이 DOM 라이브러리 코드는 더 복잡해지고 비대해질 것이구요. 심할경우 이러한 추상 인터페이스들을 정말 잘 문서화해놓고 사용법을 잘 정리해놓고 유지보수해주지 않으면, 당장 이 DOM 라이브러리를 사용할줄 모르는 다른 팀원이나 신규팀원들은 이 인터페이스를 익히지 못하면 코드를 작성하지 못하는 수준에 이를 수 있습니다.

  • 이러한 라이브러리를 만들어보는 것은 굉장히 좋은 시도이지만, 실제 실무에서 적용해본다면 위에서 말씀드린 것과 같은 비용도 충분히 고민해보셔야합니다. (그리고 대부분의 경우에는 직접 만들기보다 잘 만들어진 jQuery, React 같은 라이브러리를 쓰는 경우가 많은데, 왜 직접 만들어 쓰지않고 이런 잘 만들어진 라이브러리를 쓸까? 를 고민해보시면 좋을 것같아요.)

  • 같은 DOM을 조회했을때 querySelect를 새로하는 문제는 캐시로 해결할 수 있습니다.

  • selector key값을 받아서, 해당 키값으로 select된 DOM ref를 저장해두고, 다음에 같은 key값을 받았을때 다시 querySelect하는 것이 아닌, 캐시에 저장해둔 값을 반환하면 됩니다. (단, 이러한 방법은 모든 key가 변하지않는 유니크한 DOM ref를 반환한다는 보장이 있어야 안전합니다.)

  • Lodash 와 같은 유틸 라이브러리에 포함되어있는 memoize 함수가 비슷한 동작을 합니다. 어떻게 구현되어있는지 알아보고 memoization에 대해 공부해보세요. 👍

이전 미션에서 DOM을 중복해서 조회하는 것보다 저장을 해놓는 편이 좋다는 피드백을 주셨습니다. 당시에는 말씀해주신대로 중복된 DOM 사용을 피하는 것이 당연하다고 생각하여 코드를 수정했습니다. 그러나 DOM을 공부하다보니 DOM의 속도는 자바스크립트 엔진과 비교해서 느리지 않다는 사실을 알게 됐습니다. DOM 조작의 경우에는 리플로우가 발생하여 최대한 DOM 조작을 최소화하는 것이 맞지만 단순히 DOM을 조회하는 것 역시 과연 비용이 클까? 라는 의문이 생겼습니다.

  • '단순히 DOM을 조회하는 것이 비용이 클까?' 라는 질문에는 그럴수도 있고 아닐 수도 있습니다. 비용이 큰지 작은지를 비교하기 위해서는 전제조건이 필요합니다.
  • MDN querySelector 문서를 보시면 DOM tree를 depth-first pre-order traversal(깊이 우선 preorder 탐색) 한다고 되어있는데요. 이말은 즉, querySelector의 성능은 DOM tree의 크기와 어느정도 비례한다는 것입니다.
  • 전체 문서의 크기가 굉장히 커서 탐색해야할 노드가 많다면, 성능은 더 나빠지겠죠.
  • 반대로말하면 전체 DOM tree가 작음을 보장할 수 있다면, 매번 querySelect하더라도 큰 성능차이를 느끼지 못할 수도 있습니다.

alertMessage && checkAlert(alertMessage);
cy.get(input).should('have.value', alertMessage ? '' : value);
// cy.get(input).should('have.value', alertMessage ? '' : value);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

주석이 남아있네요! 👀

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

주석이 있었네요..! 알려주셔서 감사합니다.

@@ -1,3 +1,6 @@
import { UNIT_AMOUNT } from './standard.js';

export const MSG_INVALID_PURCHASE_AMOUNT = `금액을 ${UNIT_AMOUNT}원 단위로 입력해주세요!`;
export const MSG_OVERLAPPED_LOTTO_NUMBERS = `중복된 숫자를 입력하셨습니다. 다시 입력해주세요!`;
export const MSG_OUT_RANGED_LOTTO_NUMBERS = `범위 밖의 숫자를 입력하셨습니다. 1부터 45 사이의 숫자를 입력해주세요!`;
export const MSG_BLANK_INPUT = `빈 칸을 입력하셨습니다. 다시 입력해주세요!`;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

다른 수강생들의 리뷰를 참고해서 이 빨간 마크가 왜생기는지 알아볼까요? 👀 !

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end of file에 대한 내용은 공통 피드백 시간에서 다뤘음에도 불구하고 놓쳐버렸네요 😂
vscode setting에서 "files.insertFinalNewline": true를 추가했습니다.

}

get numbers() {
return [...this._numbers];
return [...this.#numbers];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그냥 return this.#numbers 하지 않고 spread해서 새로운 배열로 반환하는 이유가 있을까요? 👀

Copy link
Author

@yungo1846 yungo1846 Feb 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

최초의 목적은 배열은 객체이기 때문에 배열 자체를 넘겨주는 경우, 값의 변경이 가능하다고 판단하였습니다. 따라서 이를 외부에서 수정하지 못하도록 배열을 복사하여 은닉화를 하려고 했습니다. 그러나 getter만 있는 경우, 값을 재할당하려는 시도가 있을 때 에러를 띄우므로 불필요한 것 같습니다!

@@ -19,6 +19,22 @@ export const $ = (() => {
return this;
};

constructor.prototype.map = function (callBack) {
if (!callBack || typeof callBack !== 'function') {
return;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

라이브러리 사용자가 라이브러리 제작자가 의도하지 않은 방향으로 사용할 때에는
undefined를 리턴하는것 보다는, 명시적으로 자바스크립트가 에러를 뱉고 동작을 정지할 수 있도록 throw new Error를 하는 것이 좋아보입니다.
undefined를 리턴할 경우, 사용부에서 에러가 나지않으면, 이 라이브러리를 잘못 사용했는데도 그 원인이 어디에있는지 파악하기 어려울 수 있습니다.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와... 라이브러리는 사용자가 아닌 개발자를 위한 것이기 때문에 오히려 에러를 정확히 알려주는 게 중요하군요! 짚어주셔서 감사합니다 😀

MSG_INVALID_PURCHASE_AMOUNT,
UNIT_AMOUNT,
} from '../constants/index.js';

const isRangeOf = (min, max, numbers) => numbers.every(number => min <= number && number <= max);

const isOverlapped = numbers => numbers.length !== new Set(numbers).size;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isDuplicated 라는 이름이 더 적절해보여요! 👍

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정했습니다!

@yungo1846
Copy link
Author

안녕하세요 리뷰어님 :)

리뷰어님께서 말씀해주신 Lodash의 memoize 함수를 참고하면서 많은 부분을 새롭게 알 수 있었습니다. Object 보다 해싱에 최적화된 Map이라는 객체가 존재한다는 사실과 캐싱을 통해 성능을 끌어올릴 수 있다는 것을 알게 됐습니다. Lodash의 memoize 함수를 참고하여 좀 더 단순한 memoize 함수를 만들어봤습니다. 부족한 부분 알려주시면 감사하겠습니다 🙋‍♂️

이 외에도 정말 많은 부분에서 인사이트를 얻을 수 있었습니다. 항상 감사드립니다 😄

Copy link

@ysm-dev ysm-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants