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

웹 프론트엔드 자판기 미션 뼈대 코드를 만들고 유틸리티 라이브러리를 사용하여 자판기 미션을 구현해 본다. - 8월 30일 #86

Closed
woowahan-pjs opened this issue Jul 12, 2021 · 26 comments

Comments

@woowahan-pjs
Copy link
Contributor

No description provided.

@zereight
Copy link

zereight commented Jul 12, 2021

출제자 도비
출제 코드 작성완료

응시자 콜린 시험예정

체크 목록

  • 특정 코드/에약어로 인해 테스트 코드가 에러나는 경우가 있는가?
  • 출제자의 의도가 드러나는가?
    • 의도를 파악하기 힘든 부분이 있다면 표시하기
  • 난이도는 어떠한가? (너무 쉬운지? 너무 어려운지?)
  • 이건 좀 억지다 싶은게 있는가?
  • 제공된 코드에서 이상한 점(버그, 가독성이 떨어지는 코드)가 있는가?
  • 응시자로 부터 일어날 수 있는, 기존 테스트 코드로는 커버하지 못하는 예외적인 상황이 있는가?
  • (생각나면 추가)

@2SOOY
Copy link

2SOOY commented Jul 18, 2021

응시 코드

  • 기존 방식과 비교해 작성할 코드량이 적고, 어느정도 가이드 라인이 있어 난이도 측면에서 쉬웠습니다.
  • 다만, 코드 구조를 강제하는 것이 좋은 방법인지는 의문
  • 새로운 방식을 적용하려면 더 큰 규모로 뼈대 코드를 제공해야 할 것 같습니다.
  • README 또는 각 메서드의 주석으로 어떤 역할을 해야 하는지 남겨주면 좋을 것 같습니다.

  • 다음은 랜덤과 같은 테스트를 위한 유틸 제작을 진행하면 될 것 같습니다.

@woowahan-pjs woowahan-pjs changed the title 웹 프론트엔드 미션 뼈대 코드 및 채점 코드를 작성해 본다. - 7월 21일 웹 프론트엔드 미션 뼈대 코드 및 채점 코드를 작성해 본다. - 7월 26일 Jul 19, 2021
@zereight
Copy link

최종적인 목표는 우아한테크코스 프리코스 응시자들의 코드 채점을 최대한 자동화하기 위한 범용적인 라이브러리와 미션 설계이다.

  1. [범용적인 라이브러리 개발] 범용적인 라이브러리라 함은, 로또나 자동차 경주미션에서 사용될 Random 함수등을 모듈로 제공하여 input/output 형식을 강제하여 테스터블한 코드를 만들기 위함이다.
    ex) 랜덤함수를 제공하지 않을시, 랜덤한 3자리수를 구해야하는 경우
    응시자1. => Math.random을 3번돌려서 정수자리 숫자 3개 get
    응시자2. => Math.random을 1번돌려서 소수점자리 숫자 3개 get
    랜덤 값을 구하는 로직이 다르므로 랜덤함수의 input/output을 예측할 수 없어 채점할 수 없다.

  2. [테스트 프레임워크 선택] 테스트 결과 자동화를 위해 테스트 프레임워크를 사용해야한다.

    • 브랜/썬이 개발하는 지원 플랫폼에서 응시자의 PR을 읽고 테스트코드를 돌려서 점수를 계산할 수 있어야한다.

    • 후보는 cypress, jest이다.

      • cypress

        • 브라우저(또는 headless 브라우저)가 필요하다.
        • 스크립트로 구동할 수 있다.
        • E2E로 주로 사용된다.
        • 브라우저 사용시, 테스트 동작을 눈으로 확인할 수 있다.
      • jest

        • 브라우저가 필요없고 터미널 상으로만 동작한다.
        • 스크립트로 구동할 수 있다.
        • 단위, 통합 테스트로 주로 사용된다.
        • 테스트 동작을 시각적으로 확인이 불가하다.
  3. [미션 형식 논의] 전체적인 요구사항을 테스트하기 위해 응시코드 문제 구조를 정해야 한다.

    문제 구조의 종류는 다음과 같다.

    1. 기존 프리코스처럼
      간단한 Html 제공(또는 제공안함)하고
      주요 엘리먼트의 id, class를 제공하여
      사용자에게 id, class를 직접 적용하고 구조도 알아서 작성하게 한다.

      • js형식을 자유롭게 하여 응시할 수 있다.

      • 사용자가 어떻게 구현할지 정확히 알기 어려우므로 테스트 코드의 신뢰도가 낮다.

      • 기본적인 html구조 또는 제공이 안된 상태로, js를 처음부터 작성해야 하기에 응시자의 체감 난이도는 상대적으로 높다.

      • id, class를 제공하므로 cypress와 jest모두 사용가능하다.

    2. 프로그래머스 미션 형식에서 얻은 아이디어로,
      Class 컴포넌트 구조를 사전에 제공하고 html 구조도 제공한다.
      class는 DOM요소를 사전에 멤버변수로 저장하고 메서드이름도 사전에 정의를 해놓는다.핵심 메서드의 내용을 비워놓고 응시자에게 작성하도록 한다.

      • 1개의 view를 담당하는 class가 필요한 DOM요소와 메서드를 모두 가지고 있으므로, 해당 동작에 대한 테스트가 용이하다.
      • 응시자는 정해진 틀안에서만 코드를 작성해야만 한다.
      • Html 구조와 기본적인 flow를 모두 제공하므로 응시자의 체감 난이도가 낮을 수 있다.
      • class, .bind(this) 에 대한 사전 지식이 필요하다.
      • id, class를 제공하지 않으므로 cypress보다는 jest가 적합하다.

현재

  • 범용적인 라이브러리는 아직 개발하지 않음.
  • 미션 형식은 1,2 모두 작성해보았고, 2가 좀 더 테스트 자동화하기 용이하다는 판단을 내림.
    • 하지만 2는 틀을 너무 많이 제공한다는 단점과 상대적으로 난이도가 낮아질 수 있음
    • 미션 형식 2는 jest가 적합
  • 코치님들의 의견을 듣고 미션 형식 2가 괜찮다면, 저 방식으로 확정하되 좀 더 틀을 덜 제공하면서 테스터블한 형식이 고안된다면 유동적으로 적용하여 미션을 다음 주 부터 제작할 계획임.
  • 이번 주는 이 미션(자판기)뿐만 아니라, 백엔드에서 진행하고 있는 자동차 경주, 로또에서 사용가능할만한 범용적인 라이브러리를 제작할 예정임 (이렇게하면 다음 주 백엔드 미션제작시작과 일정 싱크 맞출 수 있음)

@2SOOY
Copy link

2SOOY commented Jul 24, 2021

210724 랜덤 유틸 라이브러리 제작

  • BE 교육 제작팀이 제작한 유틸을 바탕으로 랜덤 유틸 라이브러리를 제작하였습니다
  • FE 랜덤 유틸 라이브러리 repo
    • 메서드명, 인자명, 에러 메시지 등 BE측과 동일하게 맞추었습니다.
    • 양수를 검증하는 validatePositiveRange 메서드의 내부 로직만 0 or 음수이면 에러가 발생하도록 변경하였습니다.

@wmakerjun
Copy link

wmakerjun commented Jul 26, 2021

피드백

현재 방법2로 테스트코드 작성 및 채점을 위한 설계를 고민해주고 있느라 너무 고생이 많습니다 🙏🏻
이미 진행된 코드와 구현부분들을 보면서 아래 2가지 정도만 함께 고려해주면 좋을 것 같아요.

1. initDOM을 직접 구현하게 하면 어떨까요?

프리코스에서는 html과 js에 대한 기본적인 개념들을 스스로 학습하고 활용하는 것을 기대했는데요. DOM 핸들링 또한 프리코스에서 학습하길 바라는 부분이에요~ 코드를 보니 지금 제공되는 class들에서 이미 initDOM이 모두 구현되어 있는데, 한 객체 정도만 샘플로 제공하고 나머지 객체들은 직접 구현하게 하면 어떨까요~? 예를 들면 아래처럼 문제를 제공하는거에요~!

아래와 같은 html 태그를 화면에 그릴 수 있게 initDOM 메서드를 구현해주세요

<section>
  <h2>구매 내역</he>
</section>

2. 유틸은 최대한 덜 제공하고, 지원자가 스스로 모듈화하거나, 추상화할 수 있게 해주면 좋을 것 같아요!

이미 추상화가 잘 되어 있는 코드로 제공한다면 지원자들이 직접 구조를 설계하는 측면이나, 모듈을 스스로 분리하는 경험, 유틸을 직접 만들어 보는 생각을 해 볼 여지가 별로 없는 것 같아요. 문제가 너무 잘 셋팅 되어있다면 지원자들이 기능 구현을 위한 메서드 위주로만 코드를 바라보게 될 것 같아요. 우테코는 인턴이나 신입을 뽑느게 아니고 자바스크립트를 접한지 얼마 안된 사람들도 지원을 하는 곳이다보니 학습이 이루어져야하는 부분을 생각했을 때 코드가 좀 더 길어지더라도 덜 추상화하여 제공하는것도 좋을 것 같아요.
그래서 아래와 같은 유틸 코드나,Component class의 경우에도 제공하지 않는다면 어떨까요~?

const $ = (selector, $target = document) => $target.querySelector(selector);
const $$ = (selector, $target = document) =>
  Array.from($target.querySelectorAll(selector));

export { $, $$ };

@woowapark
Copy link

피드백

도비X콜린 공유해주신 사항들 잘 확인해보았습니다 👏
미션 제작 이어서 고민해주실 때 아래에 ✅ 표시한 항목들에 대해서 추가로 함께 고려해주시면 어떨까 해요

방식 2(구조를 제공하고 내용을 채워넣는 방식)에 대해

  • 지난주 미팅에서도 이야기되긴 했지만, 프리코스 미션 중 1개 정도에 대해 적용해보는 걸 목표로 해보는 건 좋은 시도같아요.
  • 다만 콜린, 도비가 후기로도 남겨주셨듯이,
    방식 1에 비해 사전에 알아야 하는 지식은 더 많은데 & 체감 난이도는 오히려 낮은 부분은 보완책이 필요할 것 같아요 🤔
    공유해주신 repo 들어가서 보니 정말로 메서드 단위로 채워넣는 수준이 되는 것 같아서요.
  • ✅ 방식 2의 틀 안에서 지원자가 스스로 구조화를 할 수 있도록 하는 방안이 있을 지

테스트 툴에 대해

  • cypress headless 모드보다 jest가 테스트해보기 용이했을까요? (궁금)
  • 방식 2에서의 테스트 코드에서도 렌더링 테스트이거나 사용자 입장에서의 기능 테스트라 cypress보다 jest가 적합하다고 느껴졌던 요구사항 같은 게 있었는 지 궁금쓰합니다 :)

혼합 방식(?)

  • 두 가지 방식으로 해주신 걸 보니,
    아예 고정으로 주는 틀은 html만으로 하고, js 코드를 자율적으로 짜게 한 뒤에 E2E 테스트로 검증하는 방식은 어떨지 싶기도 하네요
    • html에 대한 학습은 다른 미션에서 한다는 전제 하에, 미션 하나 정도에 대해서?
    • html을 아예 주니 지원자가 직접 id, class를 달도록 할 필요는 없고
      E2E로 하면 자유도를 준 상태에서 테스트 되지 않을까 해서요
      (제일 처음에 아마 이야기는 되었던 것 같은데, 실제로 적용해본 적은 없는 것 같아 남겨봅니당)
  • ✅ 방식 2를 개선하는 일과도 결국은 통하는 게 있지 않을까 싶네요.
    제공하는 걸 html로 한정 짓는 것 외에도
    해본 방식들 중에서 채택할 요소들을 적절히 취사선택해서 개선안을 정리해볼 수 있을 지

체크포인트 2개 모두,

  • 지원자가 좀 더 자유롭게 구조를 짤 수 있도록 할 수 있을 지
  • 지원자가 테스트만을 위한 코드(id, class같은)를 짜야 하는 건 최소화할 수 있을 지
    측면에서 조금씩 개선해볼 수 있을 지에 대한 의견으로 드려봅니다~

@woowapark
Copy link

@2SOOY
콜린 요건 미션 뼈대&채점 코드와는 별도 이슈이니 따로 이슈 따서 관리하는 게 좋을 것 같아요~!
#86 (comment)

@zereight
Copy link

zereight commented Jul 28, 2021

@woowapark @wmakerjun

1. 피드백 요약 ⇒ 방식 1로 되돌아간 이유

  • 피드백 잘 확인하였습니다 🙂
  • 방식2 형태(Class / DOM 제공 / 메서드만 채우는 방식)로 가져간 가장 큰 이유는 최대한 많은 응시자들의 코드를 testable 하게 하기 위함.
  • 하지만, 준과 공원이 준 피드백 결과 testable 한 미션을 제작하기 위해 너무 많은 것들을 제공했다고 판단.
  • 결론적으로 html코드 제공과 idclass와 같은 선택자를 강제하는 기존 프리코스 방식과 동일하게 운영하도록 결정.
  • 추가로 이번에 추가한 랜덤 유틸 라이브러리까지 사용하여 미션 제출과 응시를 해보고 그에 대한 피드백을 받고자함.

2. 제이슨이 주신 미션을 바탕으로 할 것들 나열
- 요구사항 1,2,3단계 별로 나누어서 README.md 형식의 문제 출제
#55 (comment)
- DOM에 출력할 내용형식을 통일하기 위해 포매팅함수 구현

// example

const displayCoinResult = (coin:number, num: number) => `${coin}: ${number}개`
// 응시자는 제공하는 포맷팅 함수를 이용하여 DOM에 결과를 출력해야함.
  • 포매팅 함수가 필요한 이유
    • id, class로 DOM을 선택한 후, 해당 DOM의 string 값을 검증해야함.

      ex) 100원이 6개있음을 출력하는 경우
      응시자1: 100원, 6개
      응시자2: 100원, 6개
      응시자3 100원짜리동전이 6개가 있습니다.
      응시자4: 백원 → 6개

      등등의 다양한 출력 형식이 존재.
      "100원", "백원", "6개"라는 텍스트가 존재함을 판단함으로써 검증을 할 수도 있지만

      "1100원이 66개"라는 결과물에도 "100원", "6개" 텍스트가 존재하므로 통과할 수 있는 위험성이 있음

→ 그래서 DOM 결과물을 포맷팅할 수 있도록 하는 함수 제공해야 테스트 가능함.
(또는 README.md에 동전의 출력형식은 "0원: 0개" 형식이어야 합니다.와 같은 가이드를 제공)

  • 랜덤 유틸처럼 다른 테스트에도 범용적으로 제공할 수 있는 라이브러리 추가 추출하여 작성

3. 피드백 요청

@woowapark
Copy link

@zereight @2SOOY
정리 감사합니다~! 🙏 👍

의견 주신대로 미션 제작 진행해주시면 다시 확인해볼게요 :)

  • 요구사항 중에 테스트 코드로 검증하기 어려운 항목이 있을 지
  • 유틸 함수 활용도가 얼마나 높은지, 다른 유틸 함수가 필요한 게 있을 지
    정도만 함께 확인해주시면 더 좋을 것 같습니다.

고생하셨어요 & 이어서 진행하는 미션 제작도 화이팅!

@zereight
Copy link

zereight commented Aug 2, 2021

기간을 2일 더 주셔서 감사합니다 🙇🙇

저희가 많이 돌고 돌았는데요.
그 이유가, 응시자들의 돌발행동을 최대한 완벽하게 통제하려고 접근해서 그런것 같습니다.

완벽히 통제하려다 보니, 많은 것들을 제공하게 되고 오히려 시험응시에 방해가 되었고,
통제를 느슨하게 하자니, 응시자들이 기상천외한 방법으로 출력한 결과를 어떻게 테스트할지 막막했었습니다.

그래서 어느정도 응시자들을 믿기로 했습니다..!

README 요구사항으로 제공된 html구조와 출력형식을 정의만 해놓는 방향으로 접근하기로 했습니다!
(그래서 포매팅 함수도 일단 뺐습니다.)

아마 준의 프리코스 방식과 많이 흡사해질것 같습니다. (준이 근본이었다.)

현재 레벨 1,2,3 요구사항과 html구조는 도출된 상태입니다. (https://github.com/woowacourse/javascript-vendingmachine/tree/doby-0802)

  • level1은 html구조를 제공 후 별도의 강제 x
  • level2도 html구조를 제공하는데, 최종 제출에서는 html에 app요소만 있게할것
  • level3은 data-* 사용 및 새로고침시 상태유지 (고려중)

하지만 이 중에 테스트 코드로 구현이 뭐가 어려울지와 어떤 유틸함수를 어떻게 적용할지에 대해 어느정도 논의가 필요한 상태입니다.

수요일까지 모두다 해놓겠습니다 🙏🙏

@woowahan-pjs woowahan-pjs changed the title 웹 프론트엔드 미션 뼈대 코드 및 채점 코드를 작성해 본다. - 7월 26일 웹 프론트엔드 미션 뼈대 코드 및 채점 코드를 작성해 본다. - 8월 4일 Aug 2, 2021
@woowapark
Copy link

woowapark commented Aug 3, 2021

@zereight @2SOOY

level1은 html구조를 제공 후 별도의 강제 x
level2도 html구조를 제공하는데, 최종 제출에서는 html에 app요소만 있게할것
level3은 data-* 사용 및 새로고침시 상태유지 (고려중).

요 부분은 아직 README에는 반영되지 않은 사항인 것이지요? (세 단계 모두에 마크업에 붙여야 할 id, class 에 대한 요구사항이 있어서요~)

  • alert으로 에러 상황을 체크하는 걸 테스트하기 더 좋은 방식이 있다면 고려해봐도 좋을 것 같네요.

    • 요건 두 분이 어떤 유틸함수가 있으면 좋을 지 마저 논의하실 때 참고만 해주세요 🙏
  • 새로고침 시 상태 유지와 같은 요구사항의 경우, 지원자가 어떤 개념을 학습하고 적용해야 할 지 키워드 정도가 있으면 어떨까요? (프리코스에서 유사하게 안내받으셨던 사항이 있었다면 참고해주세요)

  • 이 문제 자체를 그대로 쓴다기보다는 현재는 채점 방식을 테스트해보기 위한 용도로 사용하고 있는 미션이라,
    요구사항 자체에는 크게 다른 의견 없습니다~ 말씀해주신 것처럼 채점 방식에 대해 확인해볼 사항들만 함께 잘 확인해서 진행 부탁드릴게요!

    ✅ 아마도 확인해볼 사항들

    • 결과적으로 어떤 채점 방식을 사용하는 것이 좋을 것 같은 지에 대한 의견
    • 해당 방식에서 채점하기 어려운 요구사항
    • 유틸로 제공하면 좋을 것 같은 모듈이 있을 지

@zereight
Copy link

zereight commented Aug 3, 2021

level1은 html구조를 제공 후 별도의 강제 x
level2도 html구조를 제공하는데, 최종 제출에서는 html에 app요소만 있게할것
level3은 data-* 사용 및 새로고침시 상태유지 (고려중).

요 부분은 아직 README에는 반영되지 않은 사항인 것이지요? (세 단계 모두에 마크업에 붙여야 할 id, class 에 대한 요구사항이 있어서요~)

새로고침 상태유지 빼고는 README에 반영되어있지 있습니다!
세단계 모두 마크업에 붙여야할 id, class가 정해져있습니다.
단, 2,3 단계에서는 html에 app요소만 있게 제출하도록 강제하는 것입니다! (document.createElement나 innerHTML 으로 DOM 구조 직접 제작)

alert으로 에러 상황을 체크하는 걸 테스트하기 더 좋은 방식이 있다면 고려해봐도 좋을 것 같네요.
고려해보겠습니다!

새로고침 시 상태 유지와 같은 요구사항의 경우, 지원자가 어떤 개념을 학습하고 적용해야 할 지 키워드 정도가 있으면 어떨까요? (프리코스에서 유사하게 안내받으셨던 사항이 있었다면 참고해주세요)

로컬스토리지 사용을 의도하려했습니다! (아래는 프리코스때 받은 메일)
스크린샷 2021-08-03 오후 7 51 28

이 문제 자체를 그대로 쓴다기보다는 채점 방식을 테스트해보기 위한 용도로 사용하고 있는 미션이라,
요구사항 자체에는 크게 다른 의견 없습니다~ 말씀해주신 것처럼 채점 방식에 대해 확인해볼 사항들만 함께 잘 확인해서 진행 부탁드릴게요!

넵!

@zereight
Copy link

zereight commented Aug 3, 2021

level 1,2,3 요구사항 정리 및 README.md 작성완료했고
cypress test 코드 목록을 뽑아놓았습니다.

결과적으로 어떤 채점 방식을 사용하는 것이 좋을 것 같은 지에 대한 의견

  • 현재처럼, html 구조를 정해주고 README에 명시 및 gif로 안내해서 응시자가 그렇게 구현할것이라고 믿기로 했기 때문에,
    지금 채점방식으로 가도 될것 같습니다.

  • cypress 로 mocking, localStorage, reload 테스트 모두 가능한것으로 판단되어서 테스트 프레임워크를 cypress로 유지해도 될것 같습니다.

해당 방식에서 채점하기 어려운 요구사항

  • 이 방식에서 어려운 사항이 아니라, 그냥 채점하기 어려운 요구사항인데요. ⭐️⭐️⭐️⭐️⭐️
    자판기에 입력한 금액만큼 동전의 개수가 랜덤으로 생성되는 로직을 다시 논의해야할 것 같습니다.
    백엔드와 동일한 pick메서드를 사용해야 하는데, 어떻게 해야 예측이가능할지...
    (pick을 호출했을때 나오는 동전을 고정하도록 mocking 해야하나?)

  • level2,3은 index.html의 #app 요소 내부에 아무것도 없는 상태로 제출하도록 하기 떄문에 이에대한 테스트가 필요합니다.
    어떻게 구현할지 논의가 필요합니다.

유틸로 제공하면 좋을 것 같은 모듈이 있을 지

  • localStorage 테스트를 위해 (응시자용 x), 별도의 유틸을 사용하면 좋을 것 같습니다.

  • 전반적인 cypress 테스트용 유틸이 있으면 테스트코드를 작성하는데 많은 도움이 될 것 같습니다.

    • mocking용 유틸
    • localStorage용 유틸(위와 같은 내용)
    • reload용 유틸
    • alert/confirm 문구 체크용 유틸

기타

제이슨이 작성해주신
2단계 - 돈통의 3번째 요구사항
사용자가 입력한 금액에 대한 잔돈을 반환할 수없는 경우 입력한 금액을 그대로 반환한다.
3단계 - 자판기의 3번째 요구사항
잔돈이 상품 최소 금액보다 적은 경우 바로 잔돈을 돌려준다.

은 아래와 같은 내용으로 바꾸었습니다.
2단계 - 돈통의 3번째 요구사항
보유한 동전으로 최대한 반환하고 반환할 수 없는 남은 금액은 반환하지 않는다.
3단계 - 자판기의 3번째 요구사항
반환하기 버튼을 눌러야만 동전이 반환된다.

@2SOOY
Copy link

2SOOY commented Aug 4, 2021

@woowapark

안녕하세요! 공원:)
기능 요구 사항 및 테스트 항목 관련 1차 피드백 요청드립니당

진행사항

브랜치

  • step1 / step2 / step3 에 대한 기능 요구 사항 작성 📌 링크
  • 미션을 구현하기 위한 기본적인 html 구조 (실제 프리코스에서는 제공하지 않을 것 입니다. 참고용) 📌 링크
  • step2 / step3에 대한 주요 테스트 항목 목록
    • 📌 step2 / 📌 step3
    • ✅ step2에서 실제 잔돈을 충전하고 무작위 동전이 생성된 후, 사용자가 상품 구매를 한 이후 동전 반환시 어떻게 테스트를 할 수 있을지는 논의가 필요합니다
  • 이번 미션을 수행하기 위한 랜덤 유틸 (현재는 NPM에 배포하지 않고 lib내부 디렉토리에 위치시켰습니다.) 📌 링크
  • 렌더링에 필요한 간단한 포매팅 함수 📌 링크
  • 저 같은 경우는 도비와 달리 모든 STEP들을 통합하여 1개의 디렉토리로 관리하여 step1의 경우 step2, step3와 기능이 겹치는 부분이 많기 때문에 step1에 대한 테스트 목록은 따로 작성하지 않았습니다.

결론

결과적으로 어떤 채점 방식을 사용하는 것이 좋을 것 같은 지에 대한 의견
해당 방식에서 채점하기 어려운 요구사항

  • 미션 진행 방식 자체에는 DOM의 id, class, data 속성값을 착오 없도록 잘 명시한다면 채점을 하는 데 있어 큰 요구사항은 없을 것이라고 판단됩니다.
  • step2의 무작위 동전 생성 -> 상품 구매 -> 최소 동전 반환에 대한 검증을 어떤 방식으로 진행할 지는 논의가 필요할 것 같습니다.

유틸로 제공하면 좋을 것 같은 모듈이 있을 지

  • 이번 경우에 구매한 상품 목록에 대한 contents를 결정하는 포매팅 유틸 함수를 하나 추가하였습니다.
  • 이외 유틸들은 여러 상황들을 마주하면서 고민해보겠습니다.

@woowapark
Copy link

고생하셨어요! 도비 콜린 두 분 다 꼼꼼하게 정리해주셔서 감사합니다 🙏
오늘 중에 링크 남겨주신 것들 확인하고 다시 코멘트로 피드백 남겨둘게요~!

@woowapark
Copy link

@zereight @2SOOY 콜린 도비 안녕하세요~
_
콜린의

step2에서 실제 잔돈을 충전하고 무작위 동전이 생성된 후, 사용자가 상품 구매를 한 이후 동전 반환시 어떻게 테스트를 할 수 있을지는 논의가 필요합니다

내용과
도비의

자판기에 입력한 금액만큼 동전의 개수가 랜덤으로 생성되는 로직을 다시 논의해야할 것 같습니다.
백엔드와 동일한 pick메서드를 사용해야 하는데, 어떻게 해야 예측이가능할지...
(pick을 호출했을때 나오는 동전을 고정하도록 mocking 해야하나?)

코멘트는 같은 이야기가 맞을까요? + 제작근로 채널에서 스레드로 백엔드 크루들과도 논의한 것으로 보았는데,
해당 논의에서 확인해본 방식을 동일하게 고려해봐도 좋을 것 같습니다.
지금보다 좀 더 제한적으로 -> pick에 옵션들을 넣으면 옵션 중 하나를 랜덤으로 리턴

_

level2,3은 index.html의 #app 요소 내부에 아무것도 없는 상태로 제출하도록 하기 떄문에
렌더링을 시켜서 테스트하는 방법이 필요하겠네요 🤔 렌더용 함수의 인터페이스만 제공해보는 건 어떨까요? (그냥 생각)

_
틀을 주는 방식이 적정 난이도&테스트 가능성의 균형을 맞추기 어려워 현재같은 방식을 사용해야 한다면,
툴은 cypress 괜찮을 것 같아요

_

  • 포매팅은 요구사항과 구현해주신 걸 보니 워낙 간단한 친구들이라, 테스트에 도움이 된다면 계속 추가해서 사용해도 좋을 것 같네요
  • 랜덤 유틸은 첫 번째 코멘트에서와 같은 내용으로 확인해주시고 & 계속 테스트 해보면 좋을 것 같고,
  • 그 다음으로 필요한 유틸이 코멘트 주신 것 중 어떤 것일 지는 이후 작업 진행하면서 고민해봐주세요.
    개인적으로는 reload같은 건 아마 테스트 도구에서 확인하거나..? 유틸로 만들기에는 적합하진 않지 않나 싶네요 🤔

@zereight
Copy link

zereight commented Aug 8, 2021

@woowapark

코멘트는 같은 이야기가 맞을까요?

넵 맞습니다!

공원이 피드백 해준 내용들을 적용하여,
백엔드에서 진행하는 것처럼 유틸리티 라이브러리를 사용하여 자판기 미션을 최대한 구현해보도록 하겠습니다.

그 이후에 채점 코드를 작성해보고, 한번 더 피드백을 받도록 하겠습니다!

@woowapark
Copy link

네엡~ 🙂
요청 주시면 다시 확인해보겠습니다

@woowahan-pjs woowahan-pjs changed the title 웹 프론트엔드 미션 뼈대 코드 및 채점 코드를 작성해 본다. - 8월 4일 웹 프론트엔드 자판기 미션 뼈대 코드를 만들고 유틸리티 라이브러리를 사용하여 자판기 미션을 구현해 본다. - 8월 11일 Aug 9, 2021
@woowapark
Copy link

@zereight @2SOOY
채점 자동화 가능할 지 확인 부탁드리며 조금 혼동되게 전달된 부분이 있을 수 있을 것 같아, 확인 차원에서 다시 코멘트 남겨둡니다~!

채점 코드 마무리 해주시면서,
구현 요구사항에 대해서도 혹시 추가로 의견 주실 부분이 있을 지
요 이슈에서 오간 이야기들 마무리로 정리하는 차원에서 함께 확인 부탁드릴게요 🙏

  • 백엔드 크루들이 의견 준 것과 같이 요구사항만 보았을 때 구현할 때 헷갈리는 부분이 있을 지
  • 랜덤 유틸 개발한 것으로 사용에 문제 없을 지 & 해당 라이브러리 사용에 대한 요구사항 문구 추가
  • 요 미션을 그대로 사용하게 되었을 때 구현 및 테스트에 문제없는 최종 요구사항 합본은 어떤 저장소 기준으로 보면 될 지

+) 질문이나 이슈 있으시면 계속 코멘트로 남겨주시면 확인할게요!
백엔드 크루들과도 함께 확인할 부분 있다면 주간회의에서 말했던 것처럼 수요일에 함께 확인해보면 될 것 같습니다~

(미리) 고생 많으셨어요!

@2SOOY
Copy link

2SOOY commented Aug 10, 2021

어제 회의 때 요청해주셨던 구현된 결과에 대한 이미지 첨부합니다 :)

branch 링크

돈통

image

상품 구매

image

@woowahan-pjs woowahan-pjs changed the title 웹 프론트엔드 자판기 미션 뼈대 코드를 만들고 유틸리티 라이브러리를 사용하여 자판기 미션을 구현해 본다. - 8월 11일 웹 프론트엔드 자판기 미션 뼈대 코드를 만들고 유틸리티 라이브러리를 사용하여 자판기 미션을 구현해 본다. - 8월 30일 Aug 11, 2021
@2SOOY
Copy link

2SOOY commented Aug 17, 2021

자판기 미션 요구 사항 종합 정리

기능 요구 사항

공통

  • 상단에 메뉴가 존재하며 각 탭에 따라 적절한 기능을 수행한다.
    • 상품 구매탭은 사용자가 금액을 충전할 수 있으며, 금액에 맞춰 상품을 구매하고, 남은 금액에 대해서는 잔돈을 반환하는 기능을 수행한다.
    • 잔돈 충전탭은 자판기가 보유할 금액을 충전하는 기능을 수행한다.
    • 상품 관리탭은 자판기가 보유하고 있는 물품을 추가하는 기능을 수행한다.

잔돈 계산 모듈

  • 상품 구매 탭에서, 잔돈 반환 시 다음과 같은 규칙을 통해 잔돈을 반환한다.
  • 최소 개수의 동전으로 잔돈을 돌려준다.
    • 예) 1000원 넣고 650원짜리 음료를 선택했다면, 잔돈은 100, 100, 100, 50원으로 반환한다.
  • 지폐를 잔돈으로 반환하는 경우는 없다고 가정한다.
  • 모든 금액에 대해 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다.
    • 예) 동전이 500,100,50,10원이 각각 1개씩 있는데 654원을 반환해야하는 경우 50원(1개), 100원(1개), 50원(1개) 총 3개를 반환하고, 4원은 반환하지 않는다.
  • 동전의 개수를 나타내는 정보는 {개수}개 형식으로 나타낸다.
    • 예) 1개 (o) / 1 개 (x) / 1 (x)

돈통

  • 잔돈 충전 탭에서, 다음과 같은 규칙으로 자판기 보유 금액을 충전한다.
  • 관리자는 자판기가 보유한 금액을 충전할 수 있다.
    • 최소 충전 금액은 100원이며, 10원으로 나누어 떨어지는 금액만 충전이 가능하다.
  • 충전 버튼을 누르면 자판기가 보유한 금액이 보여지며, 자판기가 보유한 금액 만큼의 동전이 무작위로 생성된다.
    • 동전은 500원, 100원, 50원, 10원의 동전만 생성된다.
  • 동전의 개수를 나타내는 정보는 {개수}개 형식으로 나타낸다.
    • 예) 1개 (o) / 1 개 (x) / 1 (x)
  • 다른 탭을 클릭하여도 자판기가 보유한 금액은 유지되어야 한다.

상품 구매

  • 상품 구매탭에서, 다음과 같은 규칙을 바탕으로 금액을 충전하고, 상품을 구매하며, 잔돈을 반환한다.
  • 사용자는 상품 구매를 위해 금액을 충전할 수 있다.
    • 금액은 10원으로 나누어 떨어지는 금액만 충전이 가능하다.
  • 금액은 누적으로 충전이 가능하다.
    • 1,000원 충전 -> 500원 충전 => 1,500원
  • 사용자는 충전한 금액을 바탕으로 상품을 구매할 수 있다.
  • 상품 구매에 성공하면, 충전한 금액이 상품 금액만큼 차감 된다. 또한 상품의 수량도 차감된다.
    • 수량이 0인 상품은 구매할 수 없다.
  • 모든 상품 구매가 완료되면, 사용자는 반환하기 버튼을 통해 잔돈을 반환 받을 수 있다.
  • 잔돈은 자판기가 보유한 동전을 바탕으로 최소 개수로 반환한다.
    • 잔돈 반환 규칙은 잔돈 계산 모듈 요구사항의 규칙을 따른다.

상품 추가

  • 상품 관리탭에서, 다음과 같은 규칙을 바탕으로 상품을 관리한다.
  • 상품명, 수량, 금액을 추가할 수 있다.
    • 상품 추가 입력 폼에 상품명, 가격, 수량을 차례로 입력한다.
    • 상품명, 가격, 수량은 공백이 불가능하다.
    • 상품의 최소 수량은 1개여야 한다.
    • 상품의 최소 가격은 100원이며, 10원으로 나누어 떨어져야 한다.
      • 예) 콜라 / 110원 / 5개
      • 예) 사이다 / 100원 / 100개
  • 같은 상품명의 데이터를 추가하면 기존의 상품에 해당하는 데이터는 새로운 상품으로 대체된다.
    • 콜라 / 1000원 / 12개(전) -> 콜라 / 1500원 / 10개(후) => 콜라 / 1500원 / 10개(결과)
  • 사용자는 추가한 상품을 확인할 수 있다.
    • 상품의 이름, 가격, 수량 순으로 상품 목록이 보여진다.
  • 상품 목록은 탭을 이동하여도 기존의 상태가 유지되어야 한다.

프로그래밍 요구 사항

DOM 선택자

메뉴

  • 금액 충전상품 구매, 잔돈 반환을 하기 위한 메뉴 id는 product-purchase-menu이다.
  • 자판기에 잔돈 충전을 위한 메뉴 id는 vending-machine-manage-menu이다.
  • 자판기에 상품 추가를 위한 메뉴 id는 product-manage-menu이다.

상품 구매 및 금액 충전 메뉴

  • 금액 충전 입력 요소의 id는 charge-input이다.

  • 충전 버튼 요소의 id는 charge-button이다.

  • 충전된 금액을 확인하는 요소의 id는 charge-amount이다.

  • 반환하기 버튼 요소의 id는 coin-return-button이다.

  • 반환된 동전의 개수는 테이블 형태이다.

    • 각 동전의 개수에 해당하는 요소의 id는 다음과 같다.
    • 500원: coin-500-quantity
    • 100원: coin-100-quantity
    • 50원: coin-50-quantity
    • 10원: coin-10-quantity
  • 각 상품의 구매 버튼에 해당하는 요소의 class명은 purchase-button이다.

  • 각 상품 목록의 이름에 해당하는 요소의 class명은 product-purchase-name이다.

  • 각 상품 목록의 가격에 해당하는 요소의 class명은 product-purchase-price이다.

  • 각 상품 목록의 수량에 해당하는 요소의 class명은 product-purchase-quantity이다.

  • 각 상품 목록의 이름은 dataset 속성을 사용하고 data-product-name 형식으로 저장한다.

  • 각 상품 목록의 가격은 dataset 속성을 사용하고 data-product-price 형식으로 저장한다.

  • 각 상품 목록의 수량은 dataset 속성을 사용하고 data-product-quantity 형식으로 저장한다.

자판기 잔돈(보유 금액) 충전 메뉴

  • 동전을 무작위로 생성하는 기능은 /lib/ 내부의 랜덤 유틸 중 Random.pick 메서드를 활용해서 구현한다.
  • 자판기가 보유할 금액을 충전할 요소의 id는 vending-machine-charge-input이다.
  • 충전하기 버튼에 해당하는 요소의 id는 vending-machine-charge-button이다.
  • 충전된 금액을 확인하는 요소의 id는 vending-machine-charge-amount 이다.
  • 보유한 동전의 개수는 테이블 형태이다.
    • 각 동전의 개수에 해당하는 요소의 id는 다음과 같다.
    • 500원: vending-machine-coin-500-quantity
    • 100원: vending-machine-coin-100-quantity
    • 50원: vending-machine-coin-50-quantity
    • 10원: vending-machine-coin-10-quantity

상품 추가 메뉴

  • 상품 추가 입력 폼의 상품명 입력 요소의 id는 product-name-input이다.
  • 상품 추가 입력 폼의 상품 가격 입력 요소의 id는 product-price-input이다.
  • 상품 추가 입력 폼의 수량 입력 요소의 id는 product-quantity-input이다.
  • 상품 추가를 위한 추가 버튼 요소의 id는 product-add-button이다.
  • 추가한 상품 목록의 이름에 해당하는 요소의 class명은 product-manage-name이다.
  • 추가한 상품 목록의 가격에 해당하는 요소의 class명은 product-manage-price이다.
  • 추가한 상품 목록의 수량에 해당하는 요소의 class명은 product-manage-quantity이다.

기타

  • 모든 예외 발생 상황은 alert을 이용하여 처리한다.

@zereight
Copy link

Cypress 사용 시, 유틸리티 라이브러리를 모킹하려면
Cypress와 브라우저가 같이 공유하고 있는 window메서드를 모킹해야 가능하다.
(이 방법으로 Random.pick을 모킹 성공)

그런데 이렇게되면 앞으로도 Cypress로 모킹을 해야할때, window 메서드에 할당을 해야하는데 괜찮은 방법인지?

@woowapark
Copy link

woowapark commented Sep 6, 2021

@zereight @2SOOY

자판기 미션 구현 진행해보았습니다.
-> https://github.com/woowapark/javascript-vendingmachine#%EA%B2%B0%EA%B3%BC%EB%AC%BC
요구사항 관련해서 피드백 남겨둘게요!

  • 중간까지는 단계별 구분이 있었던 것 같은데, 최종 정리본에는 단계가 없어졌더라구요!
    각 스텝을 나누고, 각 스텝마다의 요구사항이 어느정도 완결성 있게 끝낼 수 있으면 레벨1까지도 고려했을 때 더 좋을 것 같습니다.
    '상품 구매'는 구현하지 않는 상태인데 잔돈 계산의 예시에서 '상품 구매를 한 상황에서의' 잔돈 계산이 들어져 있어서 조금 복잡하게 생각하게 될 수도 있을 것 같아요.
  • 동전의 '개수' 표현 포맷을 맞추는 것도 예시 이미지에 요구사항과 동일하게 있어야 헷갈리지 않을 것 같습니다.
  • 백엔드 요구사항 중 '사용자가 입력한 금액에 대한 잔돈을 반환할 수 없는 경우 입력한 금액을 그대로 반환한다.'와
    프론트 요구사항 '모든 금액에 대해 잔돈을 반환할 수 없는 경우 잔돈으로 반환할 수 있는 금액만 반환한다.'는
    각자 다르게 구현하기로 한 부분이었던가요 ?-? 최종 정리본 기준으로 어느쪽일 지 헷갈려서 남겨둡니다.
    • ex) 동전이 500원 2개 있고, 돌려줘야 하는 잔돈이 800원일 때 어떻게 하는지
      • 500원만 돌려주고 300원은 반환하지 않는다
      • 800원을 그대로 반환한다
  • '금액은 누적으로 충전이 가능하다'는 건 돈통 요구사항에도 포함되는 게 맞을까요?
    지금은 상품 구매를 위한 충전에서만 요구사항으로 명시되어 있습니다.
  • 상품 구매를 위한 '충전'과 돈통에 충전하는 '충전'을 좀 더 명시적으로 구별되는 이름을 붙여둬도 좋을 것 같아요. 용어에 혼동이 있을 수 있을 것 같습니다. (그냥 단순히 h태그나 버튼에 노출되는 텍스트를 '자판기 동전 충전' 혹은 '구매 금액 충전' 같이 설명을 덧붙이는 정도로도 될 것 같아요)
  • 구매 내역이 결과 예시 이미지에는 있는데, 요구사항에 포함되는 부분은 아닌 것 같습니다.
    동전의 '개수' 예시와 마찬가지로 요구사항과 결과 예시 이미지가 일치하지 않는 부분이 생기면 혼란이 있을 수 있을 것 같아요. 확인 필요!
  • 이건 좀 사소한데, 사용 및 구현 흐름 상 상품 추가에 대한 요구사항이 먼저 리스트업 되면 어떨까요?
  • 단계별 구분이 된다면, 프로그래밍 요구사항도 각 단계별로 묶어서 제공되면 어떨까 싶습니다.
    한번에 우다다 나오니 약간 찾아가면서 넣게 되더라고요...ㅎㅎ
  • 상태 유지되어야 하는 부분은 storage같이 따로 의도한 요구사항이 있었을까요? 없어서 특별히 storage를 따로 사용하지는 않았습니다.

요구사항 확인을 우선 확인해서,
랜덤 라이브러리는 Random.js 파일로 가져다가 사용해보았어요.
이후에 CDN, npm 배포해주신 사항 공유 받았고,
cypress로 테스트하는 경우에도 CDN 배포한 script 를 삽입해 쓰는 방식이라면 테스트에 문제 없을 것으로 보입니다.
배포한 이슈와 요 요구사항 피드백 관련해서만 (정말정말) 최종으로 같이 확인해보고 마무리 잘 지어보아요!

@2SOOY
Copy link

2SOOY commented Sep 7, 2021

@woowapark 공원! 😄
@zereight 와 협의해서 요구사항 최종정리 진행하였습니다 :)
확인 부탁드립니당 🙏

변경사항 요약

이건 좀 사소한데, 사용 및 구현 흐름 상 상품 추가에 대한 요구사항이 먼저 리스트업 되면 어떨까요?

구현 흐름에 맞추어 요구사항 순서 변경하였습니다.
(상품 추가 -> 잔돈 충전 -> 상품 구매 -> 잔돈 반환)

동전의 '개수' 표현 포맷을 맞추는 것도 예시 이미지에 요구사항과 동일하게 있어야 헷갈리지 않을 것 같습니다.

출력과 관련한 모든 포맷 통일 시켰습니다. 추후에 이미지도 요구사항과 동일하도록 첨부하겠습니다.

ex) 동전이 500원 2개 있고, 돌려줘야 하는 잔돈이 800원일 때 어떻게 하는지
i) 500원만 돌려주고 300원은 반환하지 않는다
ii) 800원을 그대로 반환한다

상태가 유지된다는 측면 때문에 전자를 선택하였습니다.
(상품 구매 > 잔돈 계산 모듈 참조)

'금액은 누적으로 충전이 가능하다'는 건 돈통 요구사항에도 포함되는 게 맞을까요?

돈통의 금액도 누적되도록 요구사항 추가하였습니다.

h태그나 버튼에 노출되는 텍스트를 '자판기 동전 충전' 혹은 '구매 금액 충전' 같이 설명을 덧붙이는 정도로도 될 것 같아요

공원이 제시해주신 단어로 버튼 이름으로 변경하였습니다.

구매 내역이 결과 예시 이미지에는 있는데, 요구사항에 포함되는 부분은 아닌 것 같습니다.

해당 기능은 제외하였습니다.

상태 유지되어야 하는 부분은 storage같이 따로 의도한 요구사항이 있었을까요? 없어서 특별히 storage를 따로 사용하지는 않았습니다.

해당 기능도 제외하였습니다.

정리된 요구 사항
https://github.com/woowacourse/javascript-vendingmachine/blob/final-requirements/README.md

@woowapark
Copy link

@zereight @2SOOY
(코멘트 남겨주신 걸 놓쳤었네요 ^_ㅠㅜ
다음 미션 만들면서 혹시 제가 한 2일 정도 내에 보지 않으면 슬랙이나 다른 방법으로 저를 쪼아주세요ㅋㅋ!)
요구사항 최종본 문제 없을 것 같습니다~
채점 PR에 마지막 확인 사항 남겨둔 부분만 확인해주시면 될 것 같아요
woowacourse/javascript-vendingmachine#4 (comment)

+) 이런 부분은 오히려 너무 친절한 요구사항-지원자 입장에서 추가로 도출해야 하는 요구사항-이라 제거해도 될 것 같은데요ㅋㅋ
이 부분은 그냥 보여줄 지 아닐 지만 결정하면 될 것 같아서, 코치분들과 논의해볼게요!

  • 상품 구매에 성공하면, 충전한 금액이 상품 금액만큼 차감 된다. 또한 상품의 수량도 차감된다.
  • 수량이 0인 상품은 구매할 수 없다.
  • 구매하려는 상품 가격이 보유하고 있는 금액보다 높은 경우 상품을 구매할 수 없다.
  • 반환한 동전만큼 사용자가 충전한 금액이 차감된다.
  • 반환한 동전만큼 자판기가 보유하고 있는 동전도 차감된다.
  • 반환한 동전의 결과는 누적되지 않는다.

고생 많으셨어요!!

@woowapark
Copy link

@zereight @2SOOY
위에 이야기한 너무 친절한(ㅋㅋㅋ) 요구사항들은 지원자 입장에서 스스로 도출하면 좋겠는 엣지 케이스들이 될 것 같아서
최종 요구사항에서는 제거하도록 할게요~!

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

No branches or pull requests

6 participants