Skip to content

[2단계 - 웹 기반 로또 게임] 이스타 미션 제출합니다.#473

Open
Eastar-DS wants to merge 102 commits intowoowacourse:eastar-dsfrom
Eastar-DS:step2
Open

[2단계 - 웹 기반 로또 게임] 이스타 미션 제출합니다.#473
Eastar-DS wants to merge 102 commits intowoowacourse:eastar-dsfrom
Eastar-DS:step2

Conversation

@Eastar-DS
Copy link
Contributor

학습 목표

이번 미션을 통해 다음과 같은 학습 경험들을 쌓는 것을 목표로 합니다.

  • UI와 도메인 영역을 분리할 수 있는 설계를 고민해보고, 목적에 맞게 객체와 함수를 활용
  • TDD 방식으로 개발하며, 단위 테스트 기반으로 점진적인 리팩터링

제출 전 체크 리스트

  • 기능 요구 사항을 모두 구현했고, 정상적으로 동작하는지 확인했나요?
  • 기본적인 프로그래밍 요구 사항을 준수하고 있는지 확인했나요?
  • 테스트 코드는 모두 정상적으로 실행되나요?
  • (해당하는 경우) 배포한 데모 페이지에 정상적으로 접근할 수 있나요?

리뷰 요청 & 논의하고 싶은 내용

1) 이번 단계에서 가장 많이 고민했던 문제와 해결 과정에서 배운 점

  1. html, css를 모르는 상태에서 미션을 진행하려다보니 어떻게 진행해야할지 고민이 많았습니다.
    AI를 이용해서 필요한 부분을 먼저 학습하기로 결정했는데요, 제일 먼저 미션에서 쓰게될 html 태그들을 훑어보고, css를 어떻게 적용시키는건지 찾아보았습니다. 태그, 클래스, 아이디로 css를 적용시킬 수 있다는 것을 확인했고, 가능한 css는 클래스에 적용시키고 js쪽에서는 id를 이용하려고 했습니다.
  2. 피그마에서 각 컴포넌트들이 어떻게 구성되었는지 크기를 잴 수 있어 고정된 크기로 UI를 구현했는데요, 미세하게 다르게 느껴지는 부분들이 있었습니다. 기본적인 글씨체도 달랐고, 피그마에서 측정된 크기를 그대로 입력했음에도 불구하고 컴포넌트의 위치가 미세하게 다르다는 느낌이 있었습니다. 피그마에서 그려진 디자인과 html css로 구현하는 UI는 컴포넌트의 경계가 약간 다른건가 싶기도 했습니다. 일단은 피그마에서 측정된 수치로 입력했다가, 눈으로 보고 수치를 조정하며 맞추어 보았습니다. 만약 코드로 구현하는 부분에서도 컴포넌트 단위로 만들어 활용하게된다면 배치를 하는게 좀더 용이하겠다는 생각을 했습니다.

2) 이번 리뷰를 통해 논의하고 싶은 부분

  1. 현재 구현한 UI는 반응형이 아니라 크기가 고정되어있는데요, 이왕 이번 미션을 통해 html과 css에 대해 공부를 시작한겸 반응형으로는 어떻게 만들어야 할지도 학습해두는게 좋을까요?
  2. 현재 View에 해당하는 코드들도 step2-index.js에 작성되어있는데요, View와 Controller를 어떻게 분리해야할지 잘 모르겠습니다. getElementById로 가져오는 코드들은 컨트롤러에 존재하면 안되는건지, 만약 존재하는게 괜찮다면 어떤 경우에 괜찮은건지. step1에서 만들었던 코드의 흐름을 그대로 따라가도 되는건지 등 애매모호한 고민들이 계속 생겨났습니다. 분리를 할때 고려해야할 점들에 조언해주시면 감사하겠습니다!
  3. html, css파일을 하나만 사용해서 모두 작성했는데요, UI를 컴포넌트 단위로 만드는 것이 더 권장되는 방식인지 궁금합니다. 만약 컴포넌트 단위로 분리하게 된다면 html파일과 css파일도 모두 컴포넌트별로 분리하게 될거같은데, 파일이 너무 많아지는건 아닌지 걱정이 됐습니다. html 파일을 서로 연결 시키는 방법도 자연스럽지 않게 느껴졌구요.
  4. step1처럼 CLI에서 로또게임을 진행하게 되는 경우와, step2처럼 웹브라우저 환경에서 로또게임을 진행하게 되는경우 View쪽을 구현할때 고려해야할 점이 많이 다를까요? 비슷한 흐름으로 진행될거라고 생각했었는데, DOM조작 관련 코드들이 생겨서그런지 생각보다 유사하지 않게 느껴지더라구요. 두 환경에서의 흐름이 유사하게 느껴질 수 있도록 코드를 작성하는것과, 두 환경의 차이점을 고려해서 코드를 다르게 작성하는 것 중 어떤 부분이 더 중요할까요?

✅ 리뷰어 체크 포인트

1단계

  • TDD를 활용해 기능을 구현하는 과정에서 적절한 테스트 우선 접근 방식을 적용했는가? 단위 테스트의 커버리지는 충분한가?
  • 도메인과 UI의 관심사를 분리하여 적절한 모듈화가 이루어졌는가? 하나의 객체나 모듈이 너무 많은 책임을 가지고 있지는 않은가?
  • 객체의 프로퍼티를 직접 조작하기보다 메시지를 던지고 있는가?
  • 불필요한 클래스를 사용하지 않고, 함수를 적극적으로 활용하여 JavaScript다운 방식으로 로직을 구현했는가?

2단계

  • 도메인 로직에 불필요한 영향을 주지 않고 UI 변경에 대응했는가?
  • DOM 조작과 이벤트 활용을 JavaScript의 개념에 맞게 이해하고 적절하게 적용했는가?
  • 웹 표준을 준수하는 마크업을 활용하며, 스타일 작성에 일관성이 있는가?

jebiyeon02 and others added 22 commits March 6, 2026 17:03
Copy link

@eastroots92 eastroots92 left a comment

Choose a reason for hiding this comment

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

안녕하세요 이스타 고생 많으셨어요.

자잘자잘한 피드백 보다 큰 맥락에서 고민해보시면 좋을 내용이 있어 코멘트 남겨 두었어요!

이번 리뷰를 통해 논의하고 싶은 부분

현재 구현한 UI는 반응형이 아니라 크기가 고정되어있는데요, 이왕 이번 미션을 통해 html과 css에 대해 공부를 시작한겸 반응형으로는 어떻게 만들어야 할지도 학습해두는게 좋을까요?

저는 이번 과제에선 불필요하다 생각해요. 반응형 웹을 연습하기엔 너무 가벼운 기능이기도 하고, 이번 과제의 목표는 아니였다고 생각하기 때문이에요.
제가 생각하는 이번 과제의 목표는 UI로직과 도메인 로직을 잘 나누는 것, 도메인 로직을 어떻게 하면 콘솔 UI와 웹 UI를 둘다 호환 할 수 있는 설계를 만들 수 있을까? 라고 생각해요.
그런 의미에서 반응형 웹을 고민하기보단 이번 목표 관점에서 한번 더 고민해보시면 좋겠어요.
(단 반응형 웹은 많은 연습이 필요한 것은 맞아요. 틈틈히 연습하시는 것을 추천해요!)

View와 Controller를 어떻게 분리해야할지, 분리를 할때 고려해야할 점

step1에서 만든 코드의 흐름을 그대로 따라가도 된다고 생각해요. 도메인 로직(Lotto, WinningLotto, ScoreBoard)은 동일하고 View 영역만 콘솔 -> 웹으로 바뀌는 것이기 때문이에요.
위에 언급 한 것 처럼 "관심사를 잘 분리하는 것"이 이번 과제의 목표였다고 생각해요.

getElementById가 컨트롤러에 있어도 되는가? 여부는 상황에 따라 다른 것 같아요. 컨트롤러의 역할이 무엇이냐에 따라 다르기 때문이에요. 다만 지금은 의도적으로 관심사를 분리하는 것 이기 때문에.
View(UI 로직) - Controller(연결다리) - Model(로또 로직) 를 의도적으로 분리해보시면 좋겠어요.

html, css파일을 하나만 사용해서 모두 작성했는데요, UI를 컴포넌트 단위로 만드는 것이 더 권장되는 방식인지 궁금합니다.

이 부분은 제가 직접 답변하기보다 SPA와 번들링 관련하여 공부해보시는 것을 추천해요.
더 엄밀히는 웹 렌더링의 변천사를 살펴보시며 왜 이렇게 바뀌었을까? 를 고민해보시면 좋겠어요.
지금 이스타가 고민하신 것 처럼 처음에는 단순히 하나의 html, css 파일로 시작했을 텐데 점점 규모가 커지고 요구사항이 많아지며 지금의 React와 같은 방식이 나왔기 때문이에요.
(다만 이게 무조건 React 같은 방식이 좋다는 것은 아니고 상황에 따라 적절한 선택이 필요해요)

step1처럼 CLI에서 로또게임을 진행하게 되는 경우와, step2처럼 웹브라우저 환경에서 로또게임을 진행하게 되는경우 View쪽을 구현할때 고려해야할 점이 많이 다를까요?

변하지 않는 것과 변하는 것을 분리해서 생각해보시면 좋아요.
변하지 않는 것은 로또 로직이고 변하는 것은 입출력이에요.
콘솔은 입력 > 처리 > 출력 이 명확하게 순차적으로 진행되지만 웹은 이게 동시다발로 동작하기에 이벤트 기반으로 동작해요. 이 특성을 이해해 보시면 좋겠어요.

고생 많으셨습니다.

@@ -1,16 +1,129 @@
<!DOCTYPE html>
<!doctype html>

Choose a reason for hiding this comment

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

P5;

아래 피드백은 제품 관점에서 고민해볼 수 있는 부분이라 첨부해 보았어요.
당장 고칠 필요는 없고 유저 사용성을 위해 이런 부분도 신경 써볼 수 있구나 정도로 이해해주세요.

Image

지난주 로또 번호를 쉽게 찾을 수 있게 링크를 첨부해 보세요.
가장 최고는 자동으로 지난 로또 번호를 가져오는 것 이겠지만, 중간 대안으로 링크를 제공하여 쉽게 로또 번호를 찾을 수 있게 하는 것이란 생각이 들었어요.

Choose a reason for hiding this comment

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

P4; 에러내용이 불친절해요.

Image

현재 에러 발생시 ERROR 문구만 노출하고 있어요.
어떤 에러가 난 것인지 친절하게 안내하면 좋을 것 같아요.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

에러 내용을 구체적으로 알 수 있도록 상수를 추가하고 유효성을 검사하는 부분에서 해당 메세지를 사용하도록 수정했습니다.

Choose a reason for hiding this comment

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

질문!
등수 밖 로또에서 undefined 키가 생기는데 의도한 내용인지 궁금해요.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

undefined 키가 생기는것은 의도하지 않은 내용이였습니다!
step1에서 undefined가 생기는 것은 알고 있었지만 문제없이 로또게임이 진행되어 별 생각없이 넘어갔었는데요(ㅎㅎ...), 리뷰를 받아보니 양심이 찔리네요ㅠㅠ

코드를 수정하는 방법으로 두가지가 생각났었는데요, 하나는 스코어보드의 getRank 메소드에서 1~5등이 아니면 null을 반환하는 방법, 두번째는 constant에 당첨 이외의 등수를 추가하고 getRank 메소드에서 해당 값을 반환하는 방법이였습니다.

저는 두번째 방법을 택했는데요, 혹여 로또게임 결과를 반환하는 과정에서 당첨되지 않은 로또의 수도 출력해야할 수 있을 것 같아서 "NONE"으로 미리 추가해두는게 좋다고 생각했습니다.
NONE의 MATCH_COUNT는 일단 0으로 설정해두었는데요, NONE은 getRank에서 마지막줄에 기본값으로 사용할 상수이기 때문입니다. 이부분에서 질문이 있는데요, 0으로 설정해두면 아무번호도 일치하지 않는경우로 착각될수가 있고, -1같은 값으로 설정해두면 실제 불가능한 상태인 -1개를 입력해두어야해서 모두 약간의 부자연스러움이 느껴졌는데요, 혹시 두번째 방법에서 더 괜찮은 방법이 있는지 궁금합니다. 혹은 제가 택한 두번째방법보다 첫번째 방법이 선호되는 방법인지도 궁금합니다!

document.getElementById("rank-3rd").textContent = `${allRankCount.THIRD}개`;
document.getElementById("rank-2nd").textContent = `${allRankCount.SECOND}개`;
document.getElementById("rank-1st").textContent = `${allRankCount.FIRST}개`;
profitRate.innerHTML = `당신의 총 수익률은 <strong>${rate}</strong>%입니다.`;

Choose a reason for hiding this comment

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

p3; innerHTML 사용은 XSS 위험이 있어요
지금은 rate가 toFixed(1)로 생성된 숫자 문자열이라 안전하지만, innerHTML은 습관적으로 쓰면 XSS취약점으로 이어질 수 있어요. 가능하면 textContent를 쓰거나, HTML 구조가 필요하다면 index.html에 태그를 미리 만들어두고 그 안의 textContent만 교체하는 방식이 더 안전해요.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

리뷰해주신 내용 덕분에 XSS 위험이라는 것을 처음 알게 되었습니다. 감사합니다!
innerHTML에 변수를 넣으면 그 변수에 HTML 코드가 들어있을 경우 그대로 실행되는 문제라고 이해했습니다.
리뷰해주신 수익률 출력쪽의 코드는 말씀해주신대로 index.html 파일의 태그에 id를 추가하고 해당 태그안의 텍스트만 교체하는 것으로 수정했습니다!
추가적으로 innerHTML이 있지만 빈 문자열이라 XSS 위험은 없는 부분인 lottoList.innerHTML = ""; 도 습관적으로 innerHTML을 사용하는 것을 막기 위해 while문을 이용해서 대체해보았습니다.

@@ -2,3 +2,164 @@
* step 2의 시작점이 되는 파일입니다.

Choose a reason for hiding this comment

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

P1;

step1에 비해 step2는 역할분리가 덜 되어있는 것 같아요.
큰 맥락에서 로또나 스코어보드 로직을 동일하게 사용하는 것은 맞으나 Input, Output 역할이 분리되어 있지 않고, 혼재되어있는 것 같아요.

웹에서 만약 로직과 UI의 input, output을 나누어 관리한다면 어떻게 해볼 수 있을까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

일단은 step1과 가능한 유사하게 로직과 UI를 분리하려고 노력해보았습니다.
step1의 InputView, OutputView와 유사하게
step2에서는 InputViewWeb, OutputViewWeb로 분리하였습니다.
컨트롤러에서는 이벤트리스너를 추가해야하는 html 태그만 document.getElementById()로 불러와서 사용했습니다.

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