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단계 - 웹 기반 로또 게임] - 버건디(전태헌) 미션 제출합니다. #296

Merged
merged 106 commits into from
Mar 2, 2024
Merged
Show file tree
Hide file tree
Changes from 91 commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
fdfcd07
chore: eslint prettier 세팅
lurgi Feb 20, 2024
c253530
docs: REQUIREMENT 작성
lurgi Feb 20, 2024
69229a1
test: 구매 금액에 해당하는 만큼 로또 발행
lurgi Feb 20, 2024
f6a82ea
feat: 구입 금액에 해당하는 금액 만큼 로또 발행
lurgi Feb 20, 2024
30663f4
test: 1~45이하의 숫자가 아닌 경우 에러 발생
lurgi Feb 20, 2024
95befe2
test: 로또 번호 중복 숫자 혹은 6개 넘을 시 에러
lurgi Feb 20, 2024
809ad41
feat: 로또 클래스 유효성 검증
lurgi Feb 20, 2024
bc8db2a
feat: 무작위 1~45 숫자 6개 생성
lurgi Feb 20, 2024
397fa59
refactor: Lotto Number 클래스 분리
lurgi Feb 20, 2024
78789df
test: 로또 번호를 통해 등수를 저장한다.
lurgi Feb 20, 2024
40534e9
chore: eslint 불필요한 기능 수정
lurgi Feb 20, 2024
725017c
refactor: Lotto 테스트 winNumbers -> winObj으로 수정
lurgi Feb 20, 2024
c472560
feat: 당첨 번호를 입력 받아서 몇 등인지 저장한다
lurgi Feb 20, 2024
afa9e77
refactor: Lotto 테스트 명세 수정
lurgi Feb 21, 2024
c6887ec
docs: 설계 이미지 추가
lurgi Feb 21, 2024
508421f
test: WinLottoNumber 보너스 숫자 유효성 테스트
lurgi Feb 21, 2024
9e7379c
test: WinLottoNumber 테스트 수정
lurgi Feb 21, 2024
1eb10a2
feat: WinLottoNumber 유효성 검증 구현
lurgi Feb 21, 2024
fd87bfc
test: 1000원 미만 입력인 경우 에러를 던진다
lurgi Feb 21, 2024
70c32e1
feat: 1000원 미만의 경우 유효성 검증 구현
lurgi Feb 21, 2024
57e8da5
feat: 로또 구입 금액을 입력받는다.
lurgi Feb 21, 2024
b231ab2
fix: 함수 표현식 수정
lurgi Feb 21, 2024
3e6406d
feat: 로또 번호는 오름차순으로 정렬하여 출력
lurgi Feb 22, 2024
a6b5882
feat: 우승 번호 보너스 번호 입력 받는다
lurgi Feb 22, 2024
664aa91
refactor: WinLottoNumber 테스트 코드 수정
lurgi Feb 22, 2024
69137d9
feat: 로또 등수 반환
lurgi Feb 22, 2024
418ce55
feat: 당첨 내역 출력
lurgi Feb 22, 2024
15cf4ce
feat: 로또 결과 출력
lurgi Feb 22, 2024
2e569a2
feat: 우승 로또 숫자, 보너스 숫자 재실행
lurgi Feb 22, 2024
10f90da
feat: 통계 출력 이후 재시작/종료 여부 입력
lurgi Feb 22, 2024
1cc0870
refactor: 상수 분리
lurgi Feb 22, 2024
6d49a41
refactor: 상수 줄바꿈 수정 및 에러 메세지 분리
lurgi Feb 22, 2024
b16c0fb
feat: 깊은 동결 유틸함수 작성
brgndyy Feb 24, 2024
449235f
feat: 커스텀 에러 클래스 생성
brgndyy Feb 24, 2024
cef738a
feat: 상수 관련 파일들 생성
brgndyy Feb 24, 2024
0a25e49
refactor: 기존 WinLottoNumbers 클래스를WinningLotto로 변경
brgndyy Feb 24, 2024
9d864e6
refactor: Controller 클래스를 LottoController로 변경
brgndyy Feb 24, 2024
ac843b7
feat: 입력값을 받을때의 try-catch 구문을 담은 유틸함수 생성
brgndyy Feb 24, 2024
496c66b
refactor: Lotto 클래스는 단일 6개의 숫자만 취급하도록 수정
brgndyy Feb 24, 2024
faefdb8
refactor: LottoMachine 클래스 수정
brgndyy Feb 24, 2024
33ef117
feat: 당첨 결과를 관리하는 RewardGenerator 클래스 생성
brgndyy Feb 24, 2024
45bb854
feat: 시작값부터 끝의 범위 안의 랜덤 값을 만들어주는 유틸함수 생성
brgndyy Feb 24, 2024
1277912
refactor: inputview, outputview 코드 리팩토링
brgndyy Feb 24, 2024
96e58fa
refactor: 테스트코드 재작성
brgndyy Feb 24, 2024
7b08843
refactor: 필요없는 파일 삭제 및 진입점 파일 컨트롤러 이름 수정
brgndyy Feb 24, 2024
85b106e
refactor: js 확장자 붙이기
brgndyy Feb 26, 2024
c85d82a
refactor: 유효성 검사후 필드로 저장, 순서 바꾸기
brgndyy Feb 26, 2024
a91b64a
refactor: 필드 수 제한 조건 충족을 위한 Money 클래스 생성
brgndyy Feb 26, 2024
86164ee
refactor: LottoMachine 클래스 생성자 인자 없도록 수정
brgndyy Feb 27, 2024
dc51b8a
refactor: 결과 아예 도메인에서 sort해서 보내주기
brgndyy Feb 27, 2024
a42dc1b
refactor: money 클래스 생성자 없는 방식으로 리팩토링
brgndyy Feb 27, 2024
de31467
refactor: 상수 메세지 인자로 받도록 하기
brgndyy Feb 27, 2024
dd817cf
feat: 헤더 및 전체적인 body 레이아웃 구성
brgndyy Feb 27, 2024
e0f5e40
style: 헤더 및 바디 css 코드 작성
brgndyy Feb 27, 2024
5736c0f
feat: 컨텐츠 관련 컨테이너 레이아웃 생성
brgndyy Feb 27, 2024
0ddc5d4
style: 메인 컨텐츠 컨테이너 관련 css 코드 작성
brgndyy Feb 27, 2024
7320cc8
feat: 구매한 로또 목록 레이아웃 작성
brgndyy Feb 27, 2024
41a9e0d
feat: 클래스 인스턴스들을 담은 instaces.js 작성
brgndyy Feb 27, 2024
8c5635c
refactor: Outputview에 js 확장자 추가
brgndyy Feb 27, 2024
e787be9
style: 구입금액 입력 관련 css 코드 작성
brgndyy Feb 27, 2024
a082919
feat: 구입금액 입력 후, 구매 로또 렌더링 기능 구현
brgndyy Feb 27, 2024
f8f09bb
feat: 당첨번호 입력 레이아웃 작성
brgndyy Feb 27, 2024
d877f0c
style: 당첨번호 관련 css 코드 작성
brgndyy Feb 27, 2024
a43db49
feat: winningLotto 인스턴스 추가
brgndyy Feb 27, 2024
859a7c8
feat: 당첨번호 입력 기능 구현
brgndyy Feb 27, 2024
9406ad6
feat: footer 레이아웃작성
brgndyy Feb 27, 2024
8e7563c
style: footer 스타일링
brgndyy Feb 27, 2024
71d5908
feat: 당첨 통계 모달 레이아웃 작성
brgndyy Feb 27, 2024
ed2f44c
style: 모달 관련 css 코드 작성
brgndyy Feb 27, 2024
68771df
feat: 당첨 통계 모달 기능 구현
brgndyy Feb 27, 2024
12c69ef
test: Money 클래스 관련 테스트 코드 작성
brgndyy Feb 27, 2024
6ea399d
style: 모달 border 색상 투명도 변경
brgndyy Feb 27, 2024
2053d88
fix: css 파일 경로 수정
brgndyy Feb 27, 2024
2c50958
style: step2.config.js에 프리티어 적용
brgndyy Feb 27, 2024
23d0398
refactor: css js에서 임포트해오기
brgndyy Feb 27, 2024
722e096
chore: npm build 명령어 추가
brgndyy Feb 27, 2024
50aae06
fix: html 오타 수정
brgndyy Feb 27, 2024
38b29a9
feat: build 결과물 올리기
brgndyy Feb 27, 2024
3e14516
refactor: css 링크 html에 작성
brgndyy Feb 27, 2024
13353c6
Merge branch 'step2' into production
brgndyy Feb 27, 2024
ffdd462
feat: 빌드 후 배포
brgndyy Feb 27, 2024
c9b2342
feat: 빌드 후 재배포
brgndyy Feb 27, 2024
0f557fb
feat: 재배포
brgndyy Feb 27, 2024
e45034c
feat: 재배포
brgndyy Feb 27, 2024
d248b5c
feat: 재배포하기
brgndyy Feb 27, 2024
db823ea
refactor: js 파일 경로 변경
brgndyy Feb 28, 2024
01a8094
refactor: 재배포
brgndyy Feb 28, 2024
cf389cf
refactor: 재배포 10:58
brgndyy Feb 28, 2024
cc62e16
docs: step2 관련 README.md 파일 작성
brgndyy Feb 28, 2024
733f435
merge branch
brgndyy Feb 28, 2024
189aea0
Merge branch 'brgndyy' into step2
brgndyy Feb 28, 2024
726f3ed
docs: README.md 파일명 수정
brgndyy Mar 1, 2024
6b35665
Merge remote-tracking branch 'origin/step2' into step2
brgndyy Mar 1, 2024
45b5d15
remove: step2 빌드 결과물 삭제
brgndyy Mar 1, 2024
a841560
refactor: css 변수명 컨벤션에 맞게 변경
brgndyy Mar 1, 2024
74f70e6
feat: 기능 요구사항에 충족 못했을시 alert 에러창을 띄워주는 유틸 함수 생성
brgndyy Mar 1, 2024
428dc81
refactor: 유저 이벤트 중 에러 발생시, alert 에러창 띄워주기
brgndyy Mar 1, 2024
d9ab863
refactor: 불필요한 링크 첨부 제거
brgndyy Mar 1, 2024
0e5ef18
refactor: 에러 메세지 프로퍼티 추가
brgndyy Mar 1, 2024
1b076c3
refactor: 당첨 메세지 변경 된 요구사항에 맞게 수정
brgndyy Mar 1, 2024
dc13d2d
refactor: 최대 구입금액 상수 프로퍼티 추가
brgndyy Mar 1, 2024
95a4b3b
refactor: Money 클래스의 입력값 받는 함수명 변경
brgndyy Mar 1, 2024
b59570a
test: 테스트코드 수정
brgndyy Mar 1, 2024
07475e7
refactor: html 레이아웃 변경된 사항에 맞게 수정
brgndyy Mar 1, 2024
bba910f
refactor: step2-index.js 변경된 요구사항에 맞게 수정
brgndyy Mar 1, 2024
b87b28e
refactor: LottoMachine 공백 라인 제거
brgndyy Mar 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions __tests__/Money.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Money from '../src/Domain/Money.js';

describe('돈을 담당하는 클래스에 관한 테스트 코드 작성', () => {
test.each([[1000], [8300]])('1000원 이상이 되는 금액을 투입 했을때, 1000으로 나눈 몫을 저장한다', (validInput) => {
const money = new Money();

money.fromInputValue(validInput);

expect(money.getMoney()).toBe(validInput);
});

test('1000원 미만의 금액을 투입하면 예외 처리 한다.', () => {
const invalidInput = 999;

const money = new Money();

expect(() => money.fromInputValue(invalidInput)).toThrow();
});
});
1 change: 1 addition & 0 deletions dist/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!doctype html><html lang="ko"><head><meta charset="UTF-8"/><title>🎱 행운의 로또</title><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Document</title><link rel="stylesheet" href="./src/step2/styles/content.css"/><link rel="stylesheet" href="./src/step2/styles/footer.css"/><link rel="stylesheet" href="./src/step2/styles/header.css"/><link rel="stylesheet" href="./src/step2/styles/main.css"/><link rel="stylesheet" href="./src/step2/styles/modal.css"/><link rel="stylesheet" href="./src/step2/styles/moneyInput.css"/><link rel="stylesheet" href="./src/step2/styles/winningLottoInput.css"/><link rel="preconnect" href="https://fonts.googleapis.com"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/><link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet"/><script defer="defer" src="step2-bundle.js"></script></head><body><div id="app" class="mainCard"><div class="headerCard"><h1 class="headerBannerLogo">🎱 행운의 로또</h1></div><div class="contentCard"><div class="contentContainer"><div class="contentTitle"><h1>🎱 내 번호 당첨 확인 🎱</h1></div><div class="lottoInputContainer"><form class="moneyInputForm" id="moneyInputForm"><div class="labelAndInputContainer"><label for="lottoInput" class="inputLabel">구입할 금액을 입력해주세요</label> <input placeholder="금액" name="moneyInput" id="moneyInput" class="moneyInput"/></div><div class="lottoBuyingButtonContainer"><button class="lottoBuyingButton" id="buyingButton" type="submit">구입</button></div></form></div><div class="resultAndWinningLottoContainer" id="resultAndWinningLottoContainer"><div class="resultContainer"><div class="resultText" id="resultText"></div><div class="boughtLottosContainer" id="boughtLottosContainer"></div></div><div class="winningLottoFormContainer"><p class="winningLottoFormBanner">지난 주 당첨번호 6개와 보너스 번호 1개를 입력해주세요.</p><form class="winningLottoForm" id="winningLottoForm"><div class="winningLottoWrapper"><div class="winningLottoNumbersContainer"><label for="winningLottoNumbers" class="winningLottoLabel">당첨 번호</label><div class="winningLottoInputContainer"><input class="winningLottoInput"/> <input class="winningLottoInput"/> <input class="winningLottoInput"/> <input class="winningLottoInput"/> <input class="winningLottoInput"/> <input class="winningLottoInput"/></div></div><div class="bonusNumberContainer"><label for="bonusNumber" class="winningLottoLabel">당첨 번호</label> <input id="bonusNumberInput" class="winningLottoInput"/></div></div><div class="resultButtonContainer"><button class="resultButton" type="submit">결과 확인하기</button></div></form></div></div></div></div><div class="footerCard"><p class="footerLogo">Copyright 2023. woowacourse</p></div><div class="modalCard" id="modalCard"><div class="modalContainer"><div class="closeButtonContainer"><button id="modalCloseButton" class="closeButton" type="button">X</button></div><div class="winningStatisticsResultBannerContainer"><p class="resultBannerText">🏆 당첨 통계 🏆</p></div><div class="resultTableContainer"><div class="tableTitle"><div class="row"><p class="titleText statisticsText">일치 갯수</p></div><div class="row"><p class="titleText statisticsText">당첨금</p></div><div class="row"><p class="titleText statisticsText">당첨 갯수</p></div></div><div class="tableTitle"><div class="row"><p class="statisticsText">3개</p></div><div class="row"><p class="statisticsText">5,000</p></div><div class="row"><p class="statisticsText winningCount"></p></div></div><div class="tableTitle"><div class="row"><p class="statisticsText">4개</p></div><div class="row"><p class="statisticsText">50,000</p></div><div class="row"><p class="statisticsText winningCount"></p></div></div><div class="tableTitle"><div class="row"><p class="statisticsText">5개</p></div><div class="row"><p class="statisticsText">1,500,000</p></div><div class="row"><p class="statisticsText winningCount"></p></div></div><div class="tableTitle"><div class="row"><p class="statisticsText">5개+보너스볼</p></div><div class="row"><p class="statisticsText">30,000,000</p></div><div class="row"><p class="statisticsText winningCount"></p></div></div><div class="tableTitle"><div class="row"><p class="statisticsText">6개</p></div><div class="row"><p class="statisticsText">2,000,000,000</p></div><div class="row"><p class="statisticsText winningCount"></p></div></div></div><div class="statisticsResultTextContainer"><p class="statisticsResultText" id="statisticsResultText"></p></div><div class="retrySelectButtonContainer"><button id="retrySelectButton" class="retrySelectButton">다시 시작하기</button></div></div></div></div><script type="module" src="./dist/step2-bundle.js"></script></body></html>
2 changes: 2 additions & 0 deletions dist/step2-bundle.js

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions docs/STEP2README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# STEP 2에 관한 README.md

> [배포 링크](https://brgndyy.github.io/javascript-lotto/)

## - 도메인

### 1. Lotto

단일 로또에 관한 클래스입니다. 숫자 6개를 받아서 숫자 배열로 관리해주는 기능을 합니다.

### 2. LottoMachine

금액을 입력 받아서, 구입 금액에 맞는 랜덤 로또를 발행해주는 기능을 합니다.

또한 당첨 번호를 받아서, 1등부터 5등까지의 등수 결과 객체를 반환해줍니다.

### 3. Money

돈을 입력 받아서, 해당 구입금액에 대한 유효성을 검사합니다.

### 4. RewardGenerator

구매한 로또와 입력받은 당첨번호를 대조해보면서 각 매치카운트를 계산해서 1등부터 5등까지의 랭크를 지정합니다.

### 5. WinningLotto

당첨 번호, 보너스 번호를 입력받아서 관리합니다.

---

## - 레이아웃 구성

<img width="1081" alt="스크린샷 2024-02-28 오전 11 54 43" src="https://github.com/brgndyy/javascript-lotto/assets/109535991/8ea07b1e-c900-40d7-9552-129acb2fe106">
157 changes: 154 additions & 3 deletions index.html
Copy link

Choose a reason for hiding this comment

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

id와 class를 작성하는 기준이 있으실까요?

Copy link
Author

Choose a reason for hiding this comment

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

class 는 단순히 styling을 위한 명,

id는 js에서 직접 하나의 값을 불러와서 이벤트를 처리해주어야할때 라는 기준으로 작성했습니다!

하지만 당첨 번호 관련된 인풋들 같은 경우에, 동일한 도메인이지만 하나의 인풋만 처리해주는것이 아니다보니 class로 가져와서 여러 인풋을 한번에 처리해주려고 했습니다.

정리하자면 id => js내에서 동적으로 이벤트를 핸들링 하기 위해서 고유한 값을 부여
class => js 내에서 여러개의 동일 속성을 핸들링 하기 위해서 부여할수도 있지만, 스타일링을 먼저 고려해서 부여

라고 말씀드려볼 수 있을것 같습니다.

혹여나 제가 잘못생각하고 있는 부분이 있다면 짚어주신다면 감사하겠습니다! 🙇

Copy link

Choose a reason for hiding this comment

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

잘못 생각하신 건 아니고 버건디의 기준이 궁금해서 여쭤봤습니다 :) 다만 저라면, js와 css로 구분 두기보다는 후반에 설명 주신 것처럼 '유일한 요소'와 '다중 요소'로 기준을 두어 css, js 내에서 각 선택자를 유연하게 사용하는 편이 DX 상 적합한 방식이지 않을까 싶어요!

Copy link
Author

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차 pr을 한후에 제가 시멘틱 태그와 기본적인 css에 관해서 너무 무지했었다는걸 깨닫게 되었습니다..!

이번에 pr을 준비하면서는 최대한 시멘틱 태그를 지키고, css 컨벤션을 지켜보려고 해보았습니다..!

하지만 아직 BEM 방식에 익숙치 않아, 네이밍이 매끄럽게 된건지는 확실치 않은것 같습니다..!

Copy link

Choose a reason for hiding this comment

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

스킴하면서 보긴 했는데, 나쁘진 않은 듯 합니다. 만일 네이밍에 대한 기준이 어렵다면 아래의 방식대로 해보면 어떨까 싶어요.

  1. 본인이 할 수 있는 한 '최대한' 구체적인 이름을 명시하기 (저는 이름의 길이보다는 구체성이 훨씬 중요하다고 생각해요)
  2. 리뷰를 받으면서 네이밍을 하면서 꼭 없어도 되는 부분(e.g. 전치사 등)이라고 생각이 든다면 조금씩 줄여나가보기

저도 요새 많이 느끼는 부분이긴 하지만, 상대방에게 나의 의도를 명확하게 관철하기 위해서는 본인이 생각하는 범위 그 이상으로 구체적으로 작성하도록 노력하는 부분이 중요하다고 봅니다. (단, 장황한 것과 구체적인 것은 구분 필요)

Copy link
Author

Choose a reason for hiding this comment

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

말씀 감사합니다! 한번 다듬어 나가보겠습니다!

Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,163 @@
<title>🎱 행운의 로또</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./src/step2/styles/content.css" />
<link rel="stylesheet" href="./src/step2/styles/footer.css" />
<link rel="stylesheet" href="./src/step2/styles/header.css" />
<link rel="stylesheet" href="./src/step2/styles/main.css" />
<link rel="stylesheet" href="./src/step2/styles/modal.css" />
<link rel="stylesheet" href="./src/step2/styles/moneyInput.css" />
<link rel="stylesheet" href="./src/step2/styles/winningLottoInput.css" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"
rel="stylesheet"
/>
</head>

<body>
<div id="app">
<h1>🎱 행운의 로또</h1>
<div id="app" class="mainCard">
<div class="headerCard">
<h1 class="headerBannerLogo">🎱 행운의 로또</h1>
</div>
<div class="contentCard">
<div class="contentContainer">
<div class="contentTitle">
<h1>🎱 내 번호 당첨 확인 🎱</h1>
</div>
<div class="lottoInputContainer">
<form class="moneyInputForm" id="moneyInputForm">
<div class="labelAndInputContainer">
<label for="lottoInput" class="inputLabel">구입할 금액을 입력해주세요</label>
<input type="text" placeholder="금액" name="moneyInput" id="moneyInput" class="moneyInput" />
Copy link

Choose a reason for hiding this comment

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

(질문) labelfor는 어떤 목적으로 사용하는 걸까요?

Copy link
Author

Choose a reason for hiding this comment

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

input의 name 값과 label의 for 값을 매칭시켜주어서 label을 클릭하면 input에 포커싱이 가도록 사용자의 편의성을 고양시켜주는 것으로 알고 있는데요..!

지금 살펴보니 label for 속성 값과 input의 name 값이 다르네요..

짚어주셔서 감사합니다..!

Copy link

Choose a reason for hiding this comment

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

넵 의도에 맞게 답변 주신 듯 하네요 👍

</div>
<div class="lottoBuyingButtonContainer">
<button class="lottoBuyingButton" id="buyingButton" type="submit">구입</button>
</div>
</form>
</div>
<div class="resultAndWinningLottoContainer" id="resultAndWinningLottoContainer">
<div class="resultContainer">
<div class="resultText" id="resultText"></div>
<div class="boughtLottosContainer" id="boughtLottosContainer"></div>
</div>
<div class="winningLottoFormContainer">
<p class="winningLottoFormBanner">지난 주 당첨번호 6개와 보너스 번호 1개를 입력해주세요.</p>
<form class="winningLottoForm" id="winningLottoForm">
<div class="winningLottoWrapper">
<div class="winningLottoNumbersContainer">
<label for="winningLottoNumbers" class="winningLottoLabel"> 당첨 번호 </label>
<div class="winningLottoInputContainer">
<input type="text" class="winningLottoInput" />
<input type="text" class="winningLottoInput" />
<input type="text" class="winningLottoInput" />
<input type="text" class="winningLottoInput" />
<input type="text" class="winningLottoInput" />
<input type="text" class="winningLottoInput" />
Copy link

Choose a reason for hiding this comment

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

이렇게 동일한 요소가 반복되는 경우 js를 이용해서 동적으로 처리할 수 있는 방법은 없을까요~?

Copy link
Author

Choose a reason for hiding this comment

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

제가 현재 알고 있는 바로는, html에서는 필요한 부분을 일단 다 작성을 해주고 js 에서 기능적인 부분 (에를 들어서 값을 따로따로 받아야할때)에 관해서는 querySelectorAll 이나 각각 input에 다른 id 값들을 주어서 처리하는 방식인데요..!

혹시 카일이 말씀하시는 부분은 기능적인 부분이 아니라, 아예 저 input 태그를 js를 통해 반복적으로 렌더링해주는걸 말씀하시는 걸까요 ??

만약 그렇다면 createElement 메서드를 통해서 아예 js 코드가 실행될때 바로 input 태그를 생성해줄수 있을거라고 예상하는데,

근데 만약 이렇다면 직접적으로 DOM에 접근을 하게 되는거라서 비용이 많이 들지 않을까? 라는 생각도 듭니다..!

만약 100개가 넘을정도로 많은 동일 요소가 필요하다면 js 내에서 동적으로 처리해주는것이 맞겠으나, 현재는 필요한 동일 요소가 6개이기 때문에 직접 적어주어도 괜찮지 않을까 ?라는 생각도 동시에 들긴 드는데 카일의 의견도 한번 말씀 주시면 감사하겠습니다!

Copy link

Choose a reason for hiding this comment

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

타당한 의견이라고 생각합니다. 다만 아래와 같은 부분을 같이 고려해보시면 좋을 것 같아요.

  1. DOM 요소를 처리하는 메서드의 내부 로직은 최적화가 꽤 잘 되어있다.
  2. 동적으로 동작하면서 규모있는 웹 앱을 만들기 위해서는 미시적인 성능 최적화보다 유지보수성, 확장성이 더 요구된다.

따라서 어떤 방식을 사용하는 데 있어 트레이드 오프를 고려하는 습관은 지향하는 게 좋지만, 어느 한쪽에 치우쳐 이미 제공되고 있는 방법론을 아예 배제하는 자세는 경계해야 하는 부분이라고 생각해요. 저라면 DOM을 조작하는 방식은 적극적으로 사용하되, 성능을 고려한 코드 패턴을 찾아보시면서 (이벤트 위임, reflow 최소화 등) 본인만의 타협점을 찾아보면 어떨까 싶네요!

+ 성급한 성능 최적화를 지양해야 하는 이유에 대해서도 같이 찾아보시면 좋을 것 같습니다~

Copy link
Author

Choose a reason for hiding this comment

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

키워드들 감사합니다! 한번 알아보도록 하겠습니다~!

</div>
</div>
<div class="bonusNumberContainer">
<label for="bonusNumber" class="winningLottoLabel"> 당첨 번호 </label>
<input type="text" id="bonusNumberInput" class="winningLottoInput" />
</div>
</div>
<div class="resultButtonContainer">
<button class="resultButton" type="submit">결과 확인하기</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="footerCard">
<p class="footerLogo">Copyright 2023. woowacourse</p>
</div>
<div class="modalCard" id="modalCard">
<div class="modalContainer">
<div class="closeButtonContainer">
<button id="modalCloseButton" class="closeButton" type="button">X</button>
</div>
<div class="winningStatisticsResultBannerContainer">
<p class="resultBannerText">🏆 당첨 통계 🏆</p>
</div>
<div class="resultTableContainer">
<div class="tableTitle">
<div class="row">
<p class="titleText statisticsText">일치 갯수</p>
</div>
<div class="row">
<p class="titleText statisticsText">당첨금</p>
</div>
<div class="row">
<p class="titleText statisticsText">당첨 갯수</p>
</div>
</div>
<div class="tableTitle">
<div class="row">
<p class="statisticsText">3개</p>
</div>
<div class="row">
<p class="statisticsText">5,000</p>
</div>
<div class="row">
<p class="statisticsText winningCount"></p>
</div>
</div>
<div class="tableTitle">
<div class="row">
<p class="statisticsText">4개</p>
</div>
<div class="row">
<p class="statisticsText">50,000</p>
</div>
<div class="row">
<p class="statisticsText winningCount"></p>
</div>
</div>
<div class="tableTitle">
<div class="row">
<p class="statisticsText">5개</p>
</div>
<div class="row">
<p class="statisticsText">1,500,000</p>
</div>
<div class="row">
<p class="statisticsText winningCount"></p>
</div>
</div>
<div class="tableTitle">
<div class="row">
<p class="statisticsText">5개+보너스볼</p>
</div>
<div class="row">
<p class="statisticsText">30,000,000</p>
</div>
<div class="row">
<p class="statisticsText winningCount"></p>
</div>
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.

이 또한 현재 상수 객체로 분리해서 js 파일 내에서 createElement를 통해 직접 만들어주는 방법이 생각납니다..!

카일의 리뷰를 보다보니, 제가 js를 통해 직접 DOM에 내용물을 추가하는 것을 비용적으로 많이 드는 것이라고 생각하여 무의식적으로 계속 지양했던것 같다는 생각이 듭니다.

예를 들어서 아예 텍스트가 없다가, 어떠한 기능이 실행 된후에 텍스트가 생겨야만 하는 상황이라면 (직접 DOM에 내용물을 삽입해야하는경우) js를 사용 할수밖에 없지! 라고 생각했었는데요.

지금 현재 이미 하드코딩으로 레이아웃을 잡아줄수 있는 부분들이 있다면, 굳이 js로 렌더링을 안해주려고 했던것 같습니다.

갯수가 수십, 수백개여서 제가 직접 수동으로 일일히 넣어주기 힘든 경우가 아니라고 판단해서 직접 html 내에서 작성해주었던것 같아요..!

이런 관점에 대해서 카일은 어떻게 생각하실지 여쭈어 보고 싶습니다!

Copy link

Choose a reason for hiding this comment

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

동일 코멘트일 듯 하여 이미 작성한 코멘트 첨부할게요!

</div>
<div class="tableTitle">
<div class="row">
<p class="statisticsText">6개</p>
</div>
<div class="row">
<p class="statisticsText">2,000,000,000</p>
</div>
<div class="row">
<p class="statisticsText winningCount"></p>
</div>
</div>
</div>
<div class="statisticsResultTextContainer">
<p class="statisticsResultText" id="statisticsResultText"></p>
</div>
<div class="retrySelectButtonContainer">
<button id="retrySelectButton" class="retrySelectButton">다시 시작하기</button>
</div>
</div>
</div>
</div>
<script type="module" src="./src/js/index.js"></script>
<script type="module" src="./dist/step2-bundle.js"></script>
Copy link

Choose a reason for hiding this comment

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

script 태그에 type="module"을 선언하면 어떤 이점이 있을까요?

Copy link
Author

Choose a reason for hiding this comment

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

이번에 자바스크립트의 module과 관련하여 pr을 올린후 정리해보았는데요..!

요약하자면, module의 선언이 없다면 각각의 스크립트는 분리되어 작성 되더라도 같은 스코프를 공유하기때문에 변수 오염이나 에러가 발생할 가능성이 크다.

하지만 module의 선언을 통해서 각각의 독립된 스코프를 보장해줄수 있다. 라고 말씀드려볼수 있을것 같습니다!

글 링크

한번 읽어봐주시고 혹여나 잘못된 부분이 있으시다면 지적해주시면 새겨 듣겠습니다..!

Copy link

Choose a reason for hiding this comment

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

오.. 모르는 지식에 대해 블로그로 바로 정리하시다니 바람직한 습관을 갖고 계시는 군요 ㅎㅎ 현재 정리하신 부분에 추가로 말씀 드리고 싶은 부분은 type="module"을 선언한다는 것은 defer 속성을 내포하고 있기 때문에 굳이 body 하단에 스크립트 태그를 명시하지 않아도 된다는 것이었습니다!

  • 추천 키워드 - script 태그 내의 async, defer / rendering blocking resources

Copy link
Author

Choose a reason for hiding this comment

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

키워드 말씀주셔서 감사드려요! 추가적으로 더 정리해보도록 하겠습니다~!

</body>
</html>
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"test": "jest --watch --no-cache",
"build-step1": "webpack --config step1.config.js",
"start-step1": "npm run build-step1 && node dist/step1-bundle.js",
"start-step2": "webpack serve --open --config step2.config.js"
"start-step2": "webpack serve --open --config step2.config.js",
"build-step2": "webpack --mode production --config step2.config.js"
},
"devDependencies": {
"@babel/cli": "^7.20.7",
Expand Down
2 changes: 1 addition & 1 deletion src/Constants/Messages/progressMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const PROGRESS_MESSAGE = Object.freeze({
INPUT_WINNING_LOTTO: '당첨 번호를 입력해주세요.',
INPUT_BONUS_NUMBER: '보너스 번호를 입력해주세요.',
SELECT_RE_RUN: '다시 시작하시겠습니까? (y/n)',
BUY_LOTTO: '개를 구매했습니다.',
BUY_LOTTO: (lottoLength) => `총 ${lottoLength}개를 구매했습니다.`,
RESULT_HEADER: '당첨 통계\n--------------------',
RATE_OF_RETURN_MESSAGE: (rateOfReturn) => `총 수익률은 ${rateOfReturn.toLocaleString()}% 입니다.`,
});
Expand Down
2 changes: 1 addition & 1 deletion src/Constants/lottoReward.js
Copy link

Choose a reason for hiding this comment

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

.js suffix를 붙여주게 된 이유가 있을까요? 이거 때문에 file diff가 더 생긴 거 같아서 여쭤봅니다~

Copy link
Author

Choose a reason for hiding this comment

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

현재 웹팩에서 resolve 속성에 .js가 포함이 되어있어서 step1 때는 확장자에 js파일을 붙이지 않더라도 에러가 발생하지 않았었는데요.

이번 step2에서는 왜인지 모르게 js 확장자가 없으면 에러가 발생해서, 임의로 전부 다 붙여주게 되었습니다..🥲

- step2.config.js

  resolve: {
    extensions: ['.js', '.mjs', '.css'],
  },

Copy link

Choose a reason for hiding this comment

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

넵 이해했습니다~ 현재 PR에서 다룰 영역은 아니라 이에 대한 자세한 피드백은 스킵하겠지만, 추후 webpack같은 번들러를 학습하실 때 이 문제에 대한 원인이나 해결방법도 고민해보시면 좋겠네요!

Copy link
Author

Choose a reason for hiding this comment

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

말씀 감사합니다!

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import deepFreeze from '../Utils/deepFreeze';
import deepFreeze from '../Utils/deepFreeze.js';

const LOTTO_REWARD = deepFreeze({
1: {
Expand Down
2 changes: 1 addition & 1 deletion src/Constants/matchCountCondition.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import deepFreeze from '../Utils/deepFreeze';
import deepFreeze from '../Utils/deepFreeze.js';

const MATCH_COUNT_CONDITION = deepFreeze({
FIRST: {
Expand Down
2 changes: 1 addition & 1 deletion src/Constants/retry.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import deepFreeze from '../Utils/deepFreeze';
import deepFreeze from '../Utils/deepFreeze.js';

const RETRY = deepFreeze({
YES: ['y', 'Y'],
Expand Down
6 changes: 3 additions & 3 deletions src/Domain/Lotto.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import LOTTO_SETTING from '../Constants/lottoSetting';
import ERROR_MESSAGE from '../Constants/Messages/errorMessage';
import AppError from '../Error/AppError';
import LOTTO_SETTING from '../Constants/lottoSetting.js';
import ERROR_MESSAGE from '../Constants/Messages/errorMessage.js';
import AppError from '../Error/AppError.js';

export default class Lotto {
#numbers;
Expand Down
36 changes: 12 additions & 24 deletions src/Domain/LottoMachine.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,23 @@
import LOTTO_SETTING from '../Constants/lottoSetting';
import ERROR_MESSAGE from '../Constants/Messages/errorMessage';
import generateRandomNumberFromRange from '../Utils/generateRandomNumberFromRange';
import RewardGenerator from './RewardGenerator';
import AppError from '../Error/AppError';
import Lotto from './Lotto';
import LOTTO_REWARD from '../Constants/lottoReward';

export default class LottoMachine {
#money;
import LOTTO_SETTING from '../Constants/lottoSetting.js';
import generateRandomNumberFromRange from '../Utils/generateRandomNumberFromRange.js';
import RewardGenerator from './RewardGenerator.js';
import Lotto from './Lotto.js';
import LOTTO_REWARD from '../Constants/lottoReward.js';

export default class LottoMachine {
#totalPrize = 0;

#boughtLottos;

#rewardGenerator;

constructor(money) {
constructor() {
this.#rewardGenerator = new RewardGenerator();
this.#money = money;
this.#validateMoney();
this.#makeLottoByMoney();
}

#validateMoney() {
if (this.#money < LOTTO_SETTING.MIN_PRICE) {
throw new AppError(ERROR_MESSAGE.INVALID_MIN_MONEY);
}
}

#makeLottoByMoney() {
const totalBoughtLottoCount = Math.floor(this.#money / LOTTO_SETTING.MIN_PRICE);
makeLottoByMoney(money) {
const totalBoughtLottoCount = Math.floor(money / LOTTO_SETTING.MIN_PRICE);

this.#boughtLottos = Array.from({ length: totalBoughtLottoCount }, () => {
const newLotto = this.#makeNewLotto();
Expand Down Expand Up @@ -62,7 +50,7 @@ export default class LottoMachine {
this.#rewardGenerator.calculateRewardRank(lottoNumber, totalWinningLottoInfo);
});

const totalRewardResult = this.#rewardGenerator.getTotalRewardResult();
const totalRewardResult = this.#rewardGenerator.getTotalRewardResult().sort((a, b) => b.rank - a.rank);

this.#calculateTotalPrize(totalRewardResult);

Expand All @@ -77,7 +65,7 @@ export default class LottoMachine {
});
}

getRateOfIncome() {
return Number(((this.#totalPrize / this.#money) * 100).toFixed(1)).toLocaleString();
getRateOfIncome(money) {
return Number(((this.#totalPrize / money) * 100).toFixed(1)).toLocaleString();
}
}
24 changes: 24 additions & 0 deletions src/Domain/Money.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import LOTTO_SETTING from '../Constants/lottoSetting.js';
import AppError from '../Error/AppError.js';
import ERROR_MESSAGE from '../Constants/Messages/errorMessage.js';

class Money {
#money;

#validateMoney(money) {
if (money < LOTTO_SETTING.MIN_PRICE) {
throw new AppError(ERROR_MESSAGE.INVALID_MIN_MONEY);
}
}

fromInputValue(money) {
this.#validateMoney(money);
this.#money = money;
}

getMoney() {
return this.#money;
}
}

export default Money;
2 changes: 1 addition & 1 deletion src/Domain/RewardGenerator.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import MATCH_COUNT_CONDITION from '../Constants/matchCountCondition';
import MATCH_COUNT_CONDITION from '../Constants/matchCountCondition.js';

class RewardGenerator {
#totalRewardResult = [
Expand Down
Loading