Skip to content

[행성 로또] 김희주 미션제출합니다.#55

Open
lucykim05 wants to merge 16 commits intowoowacourse-precourse:mainfrom
lucykim05:lucykim05
Open

[행성 로또] 김희주 미션제출합니다.#55
lucykim05 wants to merge 16 commits intowoowacourse-precourse:mainfrom
lucykim05:lucykim05

Conversation

@lucykim05
Copy link

javascript-planetlotto-precourse

기존 요구사항 설계

기존 요구사항의 경우에는 예전에 풀었던 로또 문제와 과정이 동일하였다. 프로그램의 진행 방향에 대해서 먼저 생각해보았고, 방향은 다음과 같다.

  1. 구입 금액 입력
  2. 로또 발행
  3. 로또 출력
  4. 당첨 번호 입력
  5. 보너스 번호 입력
  6. 로또 결과 도출
  7. 결과 출력

역할 분리를 하기 전에 사용자와 내부로직이 직접적으로 상호작용하는 Controller의 역할에 대해서 먼저 정의 해보았다.

GameController

  • 구입 금액 입력 -> 검증
  • 당첨 번호 입력 -> 검증
  • 보너스 번호 입력 -> 검증
  • 게임 로직 실행
  • 결과 출력

다음과 같이 정의된 controller에 맞춰서 필요한 게임 로직을 담은 LottoGame 객체를 추가로 생성하기로 하였다.

LottoGame

  • 금액 입력 받아 저장
  • 로또 발행 하여 저장, return
  • 당첨 번호 입력 받아 LottoResult 생성
  • 결과 return

일단 위의 로직부터 하나하나 살펴보면 입력은 controller에서 진행하고 있으며, 발행의 경우에는 LottoGame 내부에서 하기보다는 새로운 파일을 만들어서 로또 발행만을 담당하도록 하는 것이 좋겠다라는 생각을 하게 되었다.

LottoMaker

  • 로또 발행
    • Random 메서드 사용 -> 랜덤한 숫자 가져옴
    • 해당 숫자를 담은 new Lotto 생성
    • return

로또가 return되었고, LottoGame에 저장되었기 때문에 이 Lotto 배열들을 돌며 번호를 전달 -> 결과를 도출하도록 해야한다. 이 로직을 담당하는 추가 파일을 생성하였다

LottoResult

  • 당첨번호, 보너스 번호 저장
  • 등수 결과 담을 객체 생성
  • total(전체 상금) 초기 세팅
  • 로또 결과 도출 로직
    • 로또 번호(하나의 로또) 입력 받음
    • 해당 로또에 당첨번호가 몇개 있는지 확인
    • 보너스 번호가 있는지 확인
    • 등수 계산하여 객체에 저장
    • 해당 로또에 대한 상금 계산 -> total에 더함
  • 로또 결과 return

return된 내용은 등수마다 몇개의 로또가 있는지, 그리고 총 상금이다. 또한 로또 결과 도출 로직이 만약에 복잡해지게 되면 이 내용을 담당하게 될 Calculator를 미리 설계해두었다.

Calculator

  • LottoResult 생성 시 생성되어 저장(LottoResult에는 당첨, 보너스 번호 저장하지 않고, calculator를 저장하게 됨)
  • 위의 로또 결과 도출 로직을 진행하게 된다.

정리하자면 LottoGame에 있는 내용으로는

  • 구매 금액
  • 발행된 로또 객체로 이루어진 배열
  • 등수마다의 개수가 들어있는 객체
  • 수익률(혹은 total?)

이렇게 정리할 수 있으며, 로또 발행 결과는 출력하였기 때문에 Controller에서 객체와 수익률을 가져와서 출력하면 마무리 될 수가 있다.

src/
├── constants/
│   └── constants.js       # 상수 (프롬프트, 에러, 기본 상수 등)
│
├── controller/
│   └── GameController.js      # 전체 게임 흐름 제어
│
├── model/
│   ├── Lotto.js                 # 로또 객체
│   ├── LottoGame.js             # 게임 로직
│   ├── LottoMaker.js            # 로또 발행
│   ├── LottoResult.js           # 로또의 결과 도출
│   ├── Calculator.js            # 수익률 계산
│   └── Validator.js             # 검증 로직 통합
│
├── view.js                    # 입출력
├── App.js                     # 프로그램 실행
├── index.js                   # 진입점
└── README.md                  # 프로젝트 설명

구현 체크리스트

InputView

  • 구입 금액 입력
  • 당첨 번호 입력
  • 보너스 번호 입력

OutputView

  • 로또 발행 결과 출력
  • 로또 결과 출력

Controller

  • 구입 금액 입력 후 검증
  • LottoGame 생성(금액 전달)
  • Lotto 발행 결과 받아 출력
  • 당첨 번호 입력 후 검증
  • 보너스 번호 입력 후 검증
  • LottoGame에 번호 전달하며 로직 실행
  • 결과 가져와서 출력

LottoGame

  • 기본 생성
    • 금액 저장
    • 결과 객체 생성
    • total 세팅
  • 로또 발행
    • LottoMaker 통해 로또 발행
    • 발행 결과 저장 및 return
  • 로또 게임 실행
    • 당첨 번호, 보너스 번호 입력 받아 LottoResult 생성
    • LottoResult 내부 로직 진행
    • 결과 받아 출력

LottoMaker

  • 랜덤 숫자 만들어서 Lotto 생성
  • 생성한 Lotto 객체 return

LottoResult

  • 당첨번호, 보너스 번호 저장
  • 기본 세팅(순위 객체, total)
  • 결과 도출 로직
    • Lotto내부에 당첨번호 몇개인가
    • 보너스 번호 있는가
    • 위의 내용 바탕으로 순위, 상금 return 및 저장

구현

구현 과정에서 나왔던 실수들과 기록해두고 싶은 점들을 이야기해보자면

예외처리

두번째 테스트코드가 '500j'를 입력하였을 때 예외처리 되는 내용이라는 것을 알게되었을 때, view.js 파일안에 있는 askAmount 메서드를 살펴보았다. 일단 구매금액 입력까지는 같은데, numparseInt되어 있다는 것을 알게되었다. 여기서 첫번째 의문점이 생겼다. 일단 테스트 케이스의 진행과정을 정리해보면

  1. 500j입력
  2. 500jparseInt('500j', 10) 처리
  3. 그러면 500이 됨...
  4. 그럼 isNaN(num) === false가 되기 때문에 에러처리가 되지 않음

에러처리가 되어야함에도 불구하고 에러처리가 되지 않아, 다른 방향에서 처리가 가능한지 확인하기 위해 찾아보았으나, 해당 메서드를 변경하지 말라는 내용이 있었고, 입력을 받는 메서드는 해당 메서드 하나뿐이었기 때문에 아무리 생각을 해봐도 방법이 없었다. 따라서 임의로 readAmount 메서드를 생성 -> parseInt 하지 않고 isNaN을 확인하게 되었다.

여기서 더 나아가서 그냥 기존 메서드의 parseInt를 Number로 변환하여 사용하기로 하였다.

결과 출력

결과 출력의 경우 2가지를 생각해야만 했다.

  1. 로또 출력
  2. 결과 출력

일단 첫번째 로또 출력의 경우, 나는 처음에는 Lotto 객체를 반환 -> 그 로또마다 출력을 하려고 했으나, 내부 내용을 보니

map(lotto=>lotto.join)

이렇게 되어있었다. 그래서 로또번호로 이루어진 배열을 들고 있는 이중배열을 return시켰다.


다음 결과 출력의 경우, 처음에는 map이라는 것만 확인을 하였다. 기존 설계의 경우 객체로 진행하려고 하였으나, map이라는 것을 확인하고 결과 저장을 map으로 방향 변경하였다. 하지만 map으로 할 때 key세팅을 String으로 하였고, 이것을 결과 출력 로직에 가서야 깨닫게 되었다.

해당 내용은 메서드 위에 적혀있는 내용으로 확인할 수 있다.

   * @param {Map<number, number>} countsByRank

미리 0번은 미당첨이라는 것을 파악해둔 덕에 0개 일치는 0번 index 즉, 맨앞에 두는 것까지는 미리 해놨었는데 key를 number로 하지 못했었고, 그래서 key를 변경 -> 결과 출력에 성공하였다.

도전과제

도전 과제로 주어진 것은 크게 2가지입니다.

  • 리팩토링
  • 기능확장

일단 기능확장에 대해 생각해봤을 때, 나온 아이디어는 다음과 같습니다.

  • 수동 구매 가능
  • 등수 계산 조건 입력

위의 내용을 구현하고자 했을 때 기존 구현한 내용들이 영향을 받는지 확인해보았고, 낸 결론은 만약 추가 input이 없을 때를 대비하면(테스트 케이스에는 정해진 input들이 있기 때문에) 가능하다.입니다.

이유를 설명해보자면,

현재 mockQuestions에 들어있는 내용은 금액, 당첨번호, 보너스 번호 입니다. 그리고 Random을 돌렸을 때 나오는 내용들도 정해져있습니다. 즉, 보너스 번호 입력 다음의 로직을 구현하게 되고, input이 없을 때를 대비하면(input이 없을 때에는 자동구매 내용 그대로 진행) 가능합니다.

일단 리팩토링을 진행한 다음, 추가 기능을 구현하기로 하였습니다.

리팩토링 설계

상수화

첫번째르 매직넘버 적용을 하고자 하였습니다. 또한 에러메세지도 상수화 시키고자 하여 적용하게 되었습니다.

  • 매직넘버 상수화
  • 에러메세지 상수화

프라이빗 필드

첫번째 구현을 완료하였을 때, private field를 전혀 사용하지 않은 상태였습니다.

현재 객체지향 프로그래밍을 우선적으로 하고 있기 때문에, 캡슐화와 은닉화를 위해 private field, method를 생성하기로 하였습니다.

추가 기능 설계

수익률 출력

기존의 3주차 미션에 있던 수익률 출력 기능을 추가하였다.
로또 한개의 등수를 구할 때 총상금도 함께 구해서 수익률을 구하도록 하였다.
상금은 기존에 계산해뒀기에, 구입금액을 입력하여 수익률을 구하였고, 출력하였다.

수동구매

수동 구매의 경우에는 순서를 다음과 같이 설정하였습니다.

  1. 수동구매를 하시려면 금액을 입력해주세요.
  2. 구매할 로또의 번호를 입력해주세요.
  3. 랜덤한 당첨번호와 보너스 번호 생성해서 처리

다음과 같이 설정하였으며, 결과 처리는 기존 로직과 동일하여 사용하였다.

랜덤한 당첨번호를 처리한 이유는, 먼저 당첨번호와 보너스번호를 입력하기 때문에, 당첨될 로또를 발행하는게 가능해진다. 그렇기 때문에 미리 구매한 로또들은 저번주 결과라고 치고, 이번주 결과라고 생각한 다음 랜덤한 당첨 번호와 비교하였다.

또한 랜덤한 당첨번호를 중복이 없을 때까지 반복하기 보다는, 기존에 쓰던 메서드를 사용 -> 랜덤한 index번호를 가져와서 그 번호에 해당되는 번호를 보너스 번호로 설정하기로 하였다.

결과

구입금액을 입력해 주세요.
10000
20개를 구매했습니다.
[1, 16, 21, 23, 26]
[4, 13, 15, 19, 27]
[3, 6, 14, 19, 20]
[1, 7, 8, 12, 26]
[6, 7, 8, 27, 30]
[2, 5, 9, 12, 15]
[1, 7, 20, 26, 28]
[11, 12, 14, 17, 18]
[7, 8, 11, 17, 22]
[3, 5, 17, 26, 30]
[14, 20, 23, 26, 28]
[5, 6, 21, 26, 28]
[9, 15, 23, 26, 30]
[2, 4, 22, 24, 30]
[9, 13, 15, 16, 27]
[1, 12, 24, 28, 29]
[2, 5, 8, 21, 29]
[3, 16, 17, 20, 27]
[2, 3, 5, 18, 25]
[9, 10, 15, 19, 21]
지난 주 당첨 번호를 입력해 주세요.
1,2,3,4,5
보너스 번호를 입력해 주세요.
6
이번주 수동 구입할 금액을 입력해주세요.
500
구입하실 로또의 번호를 입력해주세요.
1,2,3,4,5
당첨 통계
---
5개 일치 (100,000,000원) - 0개
4개 일치, 보너스 번호 일치 (10,000,000원) - 0개
4개 일치 (1,500,000원) - 0개
3개 일치, 보너스 번호 일치 (500,000원) - 0개
2개 일치, 보너스 번호 일치 (5,000원) - 0개
0개 일치 (0원) - 7개
총 수익률은 0.0%입니다.

수동 구매 결과입니다.
당첨 통계
---
5개 일치 (100,000,000원) - 0개
4개 일치, 보너스 번호 일치 (10,000,000원) - 0개
4개 일치 (1,500,000원) - 0개
3개 일치, 보너스 번호 일치 (500,000원) - 0개
2개 일치, 보너스 번호 일치 (5,000원) - 0개
0개 일치 (0원) - 7개
총 수익률은 0.0%입니다.

일반 당첨 결과와 수동 당첨 결과를 차례대로 출력하였으며, LottoGame과 Result 내부가 너무 복잡해졌지만... 일단 수동구매 로직을 구현하고자 했던 목표는 달성하였다.

@lucykim05 lucykim05 changed the title Lucykim05 [김희주] Jan 10, 2026
@lucykim05 lucykim05 changed the title [김희주] [행성 로또] 김희주 미션제출합니다. Jan 10, 2026
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.

1 participant

Comments