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

[1단계 - 자판기] 호프(김문희) 미션 제출합니다. #4

Merged
merged 43 commits into from
Mar 31, 2022

Conversation

moonheekim0118
Copy link

@moonheekim0118 moonheekim0118 commented Mar 24, 2022

✨ 데모페이지

안녕하세요 헤인티 ! 만나뵙게 되어 영광입니다 :) 리뷰이 호프라고 합니다 ~! 이번 미션동안 잘부탁드려요 !

이번에는 특별한 패턴을 정하지 않고 페어와 인터페이스 작성 -> 도메인 구현 -> 도메인 단위테스트 작성 -> UI 구현 순으로 코드를 작성했습니다.
인터페이스 먼저 작성하고, 도메인을 구현하니 도메인 구현할 때 훨씬 메서드의 역할들이 분리가 잘 되었고, UI 와 도메인의 분리도 쉬웠습니다.
그리고 UI 구현 할 때 도메인 코드를 직접 참고하지 않고 인터페이스 부분만 참고해도 되었기에 굉장히 편리했어요.
그리고 단위테스트를 바로바로 구현하니, 구현 할 때 놓쳤던 예외사항들을 잘 처리 할 수 있었기에 좋았습니다.

✅ Step1 구현 목록

  • 최초 상품 목록은 비워진 상태이다.
  • 상품명, 가격, 수량을 입력해 상품을 추가할 수 있다.
    • 상품명은 최대 10글자까지 가능하다.
    • 상품 가격은 100원부터 시작하며, 최대 10,000원까지 가능하다. 그리고 10원으로 나누어 떨어져야 한다.
    • 한 제품당 수량은 최대 20개까지 넣을 수있다.
  • 관리자는 추가한 상품을 확인할 수 있다.
  • 관리자는 추가한 상품을 수정, 삭제할 수 있다.
    • 수정 시 상품명, 가격, 수량 정보 영역 자체가 인풋 영역으로 변경된다.
    • 삭제 시 confirm을 활용하여 사용자에게 다시 한번 확인한다.
  • 잔돈 충전탭은 자판기가 보유할 금액을 충전하는 기능을 수행한다.
  • 잔돈 충전 탭에서 최초 자판기가 보유한 금액은 0원이며, 각 동전의 개수는 0개이다.
  • 잔돈 충전 입력 요소에 충전할 금액을 입력한 후, 충전하기 버튼을 눌러 자판기 보유 금액을 충전할 수 있다.
  • 잔돈은 10원으로 나누어 떨어지는 금액만 투입할 수 있다. 보유할 수 있는 최대 금액은 100,000원이다.
  • 자판기 보유 금액만큼의 동전이 무작위로 생성된다.
  • 자판기 보유 금액을 누적하여 충전할 수 있다. 추가 충전 금액만큼의 동전이 무작위로 생성되어 기존 동전들에 더해진다.

✅ src 파일 구조

📦src
 ┣ 📂css
 ┃ ┣ 📜index.css
 ┃ ┗ 📜productPage.css
 ┣ 📂js
 ┃ ┣ 📂constant
 ┃ ┃ ┗ 📜index.js
 ┃ ┣ 📂domain
 ┃ ┃ ┣ 📜changeProcessMachine.test.js
 ┃ ┃ ┣ 📜changesProcessMachine.ts
 ┃ ┃ ┣ 📜productProcessMachine.test.js
 ┃ ┃ ┗ 📜productProcessMachine.ts
 ┃ ┣ 📂interface
 ┃ ┃ ┣ 📜changes.interface.ts
 ┃ ┃ ┗ 📜product.interface.ts
 ┃ ┣ 📂moderator
 ┃ ┃ ┣ 📜changesModerator.js
 ┃ ┃ ┗ 📜productModerator.js
 ┃ ┣ 📂template
 ┃ ┃ ┣ 📜changes.template.js
 ┃ ┃ ┗ 📜product.template.js
 ┃ ┣ 📂ui
 ┃ ┃ ┣ 📜changePageView.js
 ┃ ┃ ┗ 📜productPageView.js
 ┃ ┣ 📂util
 ┃ ┃ ┗ 📜event.js
 ┃ ┗ 📜app.js
 ┗ 📜index.ts

이번 스텝은 다음과 같은 고민들을 하면서 진행했습니다.

1. 도메인과 UI 를 분리하기

  • 도메인 영역 ( 상품 구매, 잔돈 충전)과 이를 UI 에 그려주는 영역을 분리했습니다.
  • UI 가 변경되어도 도메인 로직에 영향이 없도록 구현하였습니다.

2. 커스텀 이벤트를 사용해서 뷰-컨트롤러의 의존성을 분리하기

  • 이번에 처음 사용해봤는데, 커스텀 이벤트를 사용해서 View 에서 걸어준이벤트를 Moderator 가 바로 감지할 수 있도록 구현했습니다.

✅ 고민하고 있는 점

1. SPA 구현 - 해쉬뱅 사용

  • 먼저 페어와 history api 를 사용했는데, 새로고침 시 서버로 요청을 보내서 not found 가 뜨는 문제 때문에 해쉬뱅으로 수정했습니다.
  • 그런데 다시 찾아보니 web pack historyApiFallback 이란 옵션을 통해서 history api 사용 - 새로고침 시, 웹팩에서 처리해줄 수 있더라고요! 그런데 이 역시 서버에서 직접 처리해주는게 아니라 클라이언트에서의 임시방편 같은 역할이고, 404 발생시 index.html 로 리다이렉트 해주는 역할을 하기 때문에, 완벽한 해결책(서버에서 처리)은 아니라고 생각하여 일단은 온전히 클라이언트에서 처리해 줄 수 있는 대응방안이라고 생각한 해쉬뱅으로 구현하였습니다. 혹시 리뷰어님은 저의 의견에 대해 어떻게 생각하시는지 궁금합니다. History api 를 사용하구 historyApiFallback 을 설정하는게 아무래도 이점 (seo..)이 있기에 더 좋을까요? @.@…

2. 이벤트 해제

  • 이는 고민하고 있는 부분인데요, 현재는 페이지가 이동되어도 해당 페이지에 등록되어있는 이벤트들을 해지(Remove)하고 있지는 않습니다. 그 이유는 탭(페이지)간 이동이 계속 되는데 이벤트를 해지하는 것도 비용이라고 생각했기 때문인데요! 이에 대해 고민입니다. 페이지가 바뀌면 해당 페이지에 등록되어있는 이벤트들을 해지하는게 메모리상 이점이 있기 때문에, 이벤트들을 해지해주는게 좋을지 고민 중입니다.

그럼 감사합니다 👍 👍

Copy link

@HyeonaKwon HyeonaKwon left a comment

Choose a reason for hiding this comment

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

안녕하세요 호프! 앞으로 미션동안 잘 부탁드립니다 :)

전체적으로 코드를 보면서 놀랐네요! 구조도 좋고 가독성도 좋아서 읽기 좋았습니다 👍
세부적인 것은 코멘트로 남겼구요, 전체적으로 궁금한 것이 모든 함수를 typing 하셨는데 반환값만을 typing 하는 방식이 아니라 파라미터 없는 함수들까지 inteface 파일에 추가하는 방식을 선택한 이유가 궁금합니다! 예를 들어 GenerateCoins 같은 함수들이요!

<질문>

  1. 질문을 읽으면서 역질문을 드리고 싶은데요! hash history 와 history api 를 이용해서 history 를 관리하는 것의 차이는 무엇일까요?
  2. 호프의 코드를 예로 들면, ChangePageView 와 ProductPageView 모두 this.$page 의 submit 이 일어날 때 각자의 핸들러를 실행시키고 있는데요! event 를 해제하지 않으면 상품 페이지에서 잔액 페이지로 갔을 때 두 핸들러 모두 실행되겠죠? 물론 호프의 코드는 target 으로 return 해주고 있지만, 실행되지 않아야할 핸들러가 실행되는 것 자체가 문제입니다. 이런 관점에서 생각해보고 반영되면 좋겠네요!

Comment on lines 16 to 17
this.productPageView.renderInputForm();
this.productPageView.initDOMS();

Choose a reason for hiding this comment

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

코드 순서상 Init 이 먼저 된 다음에 render 를 해야겠죠?

Suggested change
this.productPageView.renderInputForm();
this.productPageView.initDOMS();
this.productPageView.initDOMS();
this.productPageView.renderInputForm();

Copy link
Author

Choose a reason for hiding this comment

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

지금보니 정말...순서가 말도 안되네요 😭
이 부분은 코드에서 Dom Element를 다루는 방법을 바꾸면서 수정되었습니다 :)
감사합니다!


class ProductPageView {
constructor() {
this.$page = document.querySelector("#page");

Choose a reason for hiding this comment

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

이 코드는 아래 17라인인 initDOMS 에서 실행하지 않는걸까요?

Copy link
Author

Choose a reason for hiding this comment

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

그러게요! 지금보니 이것도 Dom 을 초기화해주는건데 initDoms 에 넣어놨어야했네요!
지금은, init 메서드 내부에서 init Doms , bindEvents 를 모두 처리하도록 수정했습니다.
지적 감사드려요 👍

on(this.$page, "click", this.onClick);
};

initDOMS = () => {

Choose a reason for hiding this comment

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

DOMS 는 왜 대문자일까요?

Copy link
Author

Choose a reason for hiding this comment

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

이 부분에 대해서 페어와 깊게 상의하지 않고 네이밍한것같아요.
해당 함수는 지워졌지만, 만약 다시 필요하게 된다면 initDoms 혹은 initDomElements 정도로 네이밍을 변경할 것 같아요.

try {
this.productProcessMachine.add({ name, price, count });
const products = this.productProcessMachine.getProducts();
this.productPageView.renderProductStatus(products);

Choose a reason for hiding this comment

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

product 하나를 추가할 때마다 모든 products 를 다시 그리는군요??

Copy link
Author

Choose a reason for hiding this comment

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

넵 이 부분 문제점 인지하고 수정했습니다! 아래 Pr 메시지에 자세하게 적어놓을게요 :) !
이게 문제라고 생각하지는 않았는데, 헤인티 리뷰를 받고나서보니..정말 비효율적이네요! 변경된 엘리먼트만 수정해주면 되니까요..?!
좋은 지적 정말 감사드려요! 👍

try {
this.productProcessMachine.update(idx, name, price, count);
const products = this.productProcessMachine.getProducts();
this.productPageView.renderProductStatus(products);

Choose a reason for hiding this comment

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

업데이트도 마찬가지로 하나 업데이트 할 때마다 모든 products를 다시 그려야하네요??

Copy link
Author

Choose a reason for hiding this comment

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

이 부분도, 위의 답변과 마찬가지 입니다 👍 👍

this.$changesTableBody = document.querySelector("#changes-table-body");
};

renderHaveChanges = (changes) => {

Choose a reason for hiding this comment

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

have 를 붙이는건 매우 어색하네요! renderCurrentChanges 정도는 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

넵 감사합니다 :) 지금 보니까 동사를 명사 앞에 붙이니 매우 부자연스럽네요 😭 currentChanges 로 수정했습니다 :D

this.$haveChanges.innerText = `현재 보유 금액: ${changes}`;
};

renderChangesTable = () => {

Choose a reason for hiding this comment

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

음.. UI 의 종류를 template 이 아닌 view 까지 알고 있어야 할까요?
예를 들어 동전의 리스트를 표가 아닌 그래프로 그린다면 요런 메소드들은 Table -> Graph 로 전부 바꾸어줘야 하네요!
어떤 것을 렌더링하는지만 나타내면 어떨까 싶습니다. 예를 들어 renderCurrentCoins() 이런식으로요!

Copy link
Author

Choose a reason for hiding this comment

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

UI 가 바뀔 수도 있는데, UI 의 종류를 함수에 넣는게 옳지 않다는 의견에 동의합니다 👍
그래서 renderCoinStatus 으로 바꾸어봤습니다 ㅎㅎ

50947e3


const newCoins = this.generateCoins(money);
this.accumulateCoins(newCoins);
console.log(this.coins);

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.

앗 죄송합니다. 깜빡하고 안지웠네요 !! 이랑 같이 불필요한 주석도 제거했습니다 :) 👍 👍 짚어주셔서 감사해요!

Comment on lines 14 to 20
this.changePageView.renderInput();
const changes = this.changeProcessMachine.getTotalChanges();
const coinStatus = this.changeProcessMachine.getCoins();
this.changePageView.renderChangesTable();
this.changePageView.initDOM();
this.changePageView.renderHaveChanges(changes);
this.changePageView.renderChangeStatus(coinStatus);

Choose a reason for hiding this comment

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

여기도 productModerator 와 같은 맥락인데요, 사소하지만 함수를 읽어가면서 어떤 흐름인지를 알 수 있도록 순서를 조정해보면 어떨까요?

    // dom 을 먼저 초기화하고
    this.changePageView.initDOM();
    // input 을 렌더링하고
    this.changePageView.renderInput();
   // 현재 잔액과 동전값을 가져와서
    const changes = this.changeProcessMachine.getTotalChanges();
    const coinStatus = this.changeProcessMachine.getCoins();
    // view 가 잔액표, 잔액, 동전 현황을 그리라고 한다.
    this.changePageView.renderChangesTable();
    this.changePageView.renderHaveChanges(changes);
    this.changePageView.renderChangeStatus(coinStatus);

이렇게 읽으면서 흐름을 느낄 수 있다면 좋을 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

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

정말 좋은 포인트 감사드립니다! 아래와 같이 productModreator, changesModerator 를 수정했습니다 😄

  init() {
 // View 를 초기화하고 
    this.changePageView.init();
// 잔액과 동전값을 가져와서 
    const changes = this.changeProcessMachine.getTotalChanges();
    const coinStatus = this.changeProcessMachine.getCoins();
// View 과 잔액표, 잔액, 동전 현황을 그리라고 한다. 
    this.changePageView.renderCurrentChanges(changes);
    this.changePageView.renderCoinStatus(coinStatus);
  }
  init() {
 // View 를 초기화하고 
    this.productPageView.init();
  // 상품 리스트를 가져와서 
    const products = this.productProcessMachine.getProducts();

// view 가 초기 상품리스트를 그리라고 한다. 
    this.productPageView.renderProductsStatus(products);
  }

Choose a reason for hiding this comment

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

척하면 척이네요! 👍

Comment on lines 1 to 29
export const ERROR_MESSAGE = {
DUPLICATED_NAME: "중복된 상품은 입력 할 수 없습니다.",
MAXIMUM_NAME_LENGTH: "상품명은 10자이하로 입력해주세요",
VALID_PRICE: "유효한 가격을 입력해주세요",
MINIMUM_COUNT: "추가하는 수량은 0이하가 될수가 없습니다.",
MAXIMUM_COUNT: "수량은 최대 20개까지 추가 가능합니다.",
DIVIDED_BY_MINIMUM_COIN: "투입된 금액은 10으로 나누어 떨어져야합니다.",
MAXIMUM_CHANGES: "최대 잔액은 100000원 입니다.",
MINIMUM_CHANGES: "금액은 0원보다 높아야합니다.",
};

export const VENDING_MACHINE_NUMBER = {
MAXIMUM_CHANGES: 100000,
MAXIMUM_PRICE: 10000,
MINIMUM_PRICE: 100,
MINIMUM_COIN: 10,
MAXIMUM_COUNT: 20,
MINIMUM_COUNT: 0,
MAXIMUM_NAME_LENGTH: 10,
};

export const EVENT_TYPE = {
CHARGE: "@charge",
ADD: "@add",
DELETE: "@delete",
EDIT: "@edit",
};

export const CONFIRM_MESSAGE = "정말로 삭제하시겠습니까?";

Choose a reason for hiding this comment

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

typescript 를 배웠다면 여기 상수들도 변경될 수 없도록 type 을 설정해봤으면 좋겠는데요, 지금은 충분히 ERROR_MESSAGE. DUPLICATED_NAME = '~~~' 로 메세지를 수정할 수 있겠죠?
typescript 를 이용해서 어떻게 수정되지 않도록 type 을 설정할 수 있을까요?

Copy link
Author

Choose a reason for hiding this comment

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

넵 이 부분 학습해서 타입스크립트의 enum 을 활용해서 아래와 같이 수정했습니다.
확실히 enum으로 정의하니, 타입정의할 때에도 편하고 좋네요 👍 👍

export enum ERROR_MESSAGE {
  DUPLICATED_NAME = "중복된 상품은 입력 할 수 없습니다.",
  MAXIMUM_NAME_LENGTH = "상품명은 10자이하로 입력해주세요",
  VALID_PRICE = "유효한 가격을 입력해주세요",
  MINIMUM_COUNT = "추가하는 수량은 0이하가 될수가 없습니다.",
  MAXIMUM_COUNT = "수량은 최대 20개까지 추가 가능합니다.",
  DIVIDED_BY_MINIMUM_COIN = "투입된 금액은 10으로 나누어 떨어져야합니다.",
  MAXIMUM_CHANGES = "최대 잔액은 100000원 입니다.",
  MINIMUM_CHANGES = "금액은 0원보다 높아야합니다.",
}

export enum VENDING_MACHINE_NUMBER {
  MAXIMUM_CHANGES = 100000,
  MAXIMUM_PRICE = 10000,
  MINIMUM_PRICE = 100,
  MINIMUM_COIN = 10,
  MAXIMUM_COUNT = 20,
  MINIMUM_COUNT = 0,
  MAXIMUM_NAME_LENGTH = 10,
}

export enum EVENT_TYPE {
  CHARGE = "@charge",
  ADD = "@add",
  DELETE = "@delete",
  EDIT = "@edit",
}

3958203

Choose a reason for hiding this comment

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

오! enum 을 적용하셨군요 👍
그치만 보통 이런 경우엔 const 를 쓰는게 맞습니다! 2단계에서 아래 리스트에 대해 공부하고 결과를 알려주시면 좋겠네요!

  1. enum 을 사용하면 안되는 이유
  2. readonly 타입이란?
  3. as const 란?

Copy link
Author

Choose a reason for hiding this comment

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

학습 키워드 알려주셔서 감사해요! 다음 미션까지 학습해서 알려드리겠습니다 👍 👍 헤인티 짱짱..감사해용 ❤️

@moonheekim0118
Copy link
Author

moonheekim0118 commented Mar 31, 2022

안녕하세요 헤인티! 먼저 리뷰 반영이 늦어진 점 정말 죄송해요. 타입스크립트 이것저것 공부해보고 적용해보느라 늦어졌습니다 ㅠ_ㅠ
그리고 정말 좋은 리뷰와 고민에 대한 답변 감사드립니다. 코드에 대해 깊게 생각해볼 수 있었어서 좋았습니다!


헤인티가 주신 질문에 대한 저의 생각이랑, 코드를 어떻게 변경했는지 간략하게 설명해보았습니다.

1. 전체적으로 궁금한 것이 모든 함수를 typing 하셨는데 반환값만을 typing 하는 방식이 아니라 파라미터 없는 함수들까지 inteface 파일에 추가하는 방식을 선택한 이유가 궁금합니다! 예를 들어 GenerateCoins 같은 함수들이요!
- 음 .. 일단 Interface 파일을 작성 할 때, 해당 클래스에 들어갈 모든 메서드를 먼저 작성했어요! 음 그런데 리뷰어님은 파라미터가 없는 함수들은 굳이 추가하지 않아도 된다고 생각하시는걸까요 ?ㅅ?

2. 질문을 읽으면서 역질문을 드리고 싶은데요! hash history 와 history api 를 이용해서 history 를 관리하는 것의 차이는 무엇일까요?

Hash api 사용법

  • hash 방식은 일단, Ajax 방식에서 history 관리가 안된다는 단점에 의해서 탄생한 방법입니다.
  • Hash 는 URI 의 fragment identifier 의 기능인 anchor 를 사용하구요, 이 때 URL 이 동일한 상태에서 hash 가 변경되어도 브라우저는 서버에 웹페이지를 요청하지 않습니다.
  • hash 는 ‘요청’이 아니라, ‘앵커’로 웹페이지 내부에서 이동을 위한 것이기 때문입니다!
  • 즉, 해쉬방식은 URL 에 따라서 서버에 새로운 요청을 보내지 않지만 페이지마다 고유의 URL이 존재하여 history 를 관리 할 수 있습니다.
  • 하지만 검색엔지니 웹사이트 수집을 위해서 자바스크립트를 실행하지 않기 떄문에, hash 방식으로 만들어진 사이트의 콘텐츠를 수집하지 못합니다! 즉 SEO 이슈가 있습니다.

History api 사용법

  • 해시뱅의 가장 큰 단점인 SEO 이슈를 보완한 방법으로 등장했습니다.
  • history api를 사용하면, pushState 메서드를 이용해서, URI 를 변경합니다.
  • 이 또한 해시뱅처럼 페이지마다 고유한 URI가 존재하여 history를 관리할 수 있습니다.
  • 하지만 새로고침 버튼을 클릭하면 , 요청이 서버로 전달되어서, 서버에서 URL에 따라 HTML로 클라이언트에 응답을 해줘야합니다.

제가 이렇게 두 가지 방법을 찾아보고 깨달은것은, 지금 현재 서버에서 서버사이드렌더링 방식으로 HTML을 그려서 응답해줄게 아니면 지금 Histroy Api 를 사용하는 것과 hash api 를 사용하는 것에 성능상 차이가 없다고 판단했습니다. 그래서 해시뱅 방식으로 유지했습니다!

3. 호프의 코드를 예로 들면, ChangePageView 와 ProductPageView 모두 this.$page 의 submit 이 일어날 때 각자의 핸들러를 실행시키고 있는데요! event 를 해제하지 않으면 상품 페이지에서 잔액 페이지로 갔을 때 두 핸들러 모두 실행되겠죠? 물론 호프의 코드는 target 으로 return 해주고 있지만, 실행되지 않아야할 핸들러가 실행되는 것 자체가 문제입니다. 이런 관점에서 생각해보고 반영되면 좋겠네요!

  • 이 부분에 대해서 헤인티의 리뷰를 받고 이벤트를 제거해주는 방향으로 수정했는데요,생각해보니 바뀐 코드에서는 해시뱅으로 페이지가 새로 렌더링 된 후 해당 페이지에 있는 엘리먼트에 직접 이벤트를 바인딩해줬기 때문에 굳이 이벤트를 제거해주지 않아도 된다고 판단했습니다.
  • 엘리먼트가 DOM에서 제거되면, GC가 알아서 엘리먼트의 이벤트리스너도 제거해주기 때문에요!

수정한 점

  1. Product 객체를 따로 만들었습니다.
  • 이전에는 단순히 객체 배열로 저장을 했는데, 이럴 경우 Product 자체의 관리가 어렵고, 데이터구조가 바뀔 때 마다 일일이 변경해야하는 점이 번거롭게 느껴져서, Product 객체를 생성했습니다.
  1. Product 별로 Id를 고유하게 만들도록 했습니다.
  • 이전에는, 배열 index 로 id 를 판별을 했는데, 그렇게 하다보면 id 값에 따라서 엘리먼트를 가져오는게 어렵게 되더라구요! 그래서 최대한 고유하게 만들어보고자, Date.now 와 Math.random 함수를 이용해서 프로덕트별 id 를 생성했습니다.
  1. Element 업데이트 방식 수정
  • 이전에 헤인티가 말씀해주신대로, 수정/삭제/추가 시에 모든 Product를 다시 화면에 그려주는 문제를 발견했고, 이를 수정되야 할 부분만 화면에 다시 그려주도록 수정했습니다.
  1. 화면에 고정적으로 필요한 Element Container 들을 createElement로 생성하여, 그 Element 를 조작하도록 수정했습니다.

  2. 모든 Js 코드를 TS 로 변경해보았습니다.

  • 아직 많이 부족하지만, 일단 최대한 Ts와 친해져보고자 작성해봤습니다!
  1. Interface 변수명 앞에 I- prefix를 붙였어요.
  • 이거는 취향차이인 것 같은데 ,저는 I 를 붙이는게 더 깔끔하고 읽기 쉽다고 생각하여 이렇게 변경해보았습니다!

그럼 다시 한번 늦게 리뷰요청 보내드려서 죄송하구, ㅠ_ㅠ 정말정말 감사드립니다. 많은 도움이 되었어요 🙇

Comment on lines 146 to 152
`<td>${name}</td>
<td>${price}</td>
<td>${count}</td>
<td>
<button class="edit-button process-button">수정</button>
<button class="delete-button process-button">삭제</button>
</td>`,

Choose a reason for hiding this comment

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

요 친구도 template 이겠죠?

Copy link
Author

Choose a reason for hiding this comment

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

넵 지적해주셔서 감사합니다 :) 따로 빼도록 할게요~~!

Comment on lines +1 to +4
export const $ = (
selector: string,
target: Element | Document = document
): Element => target.querySelector(selector);

Choose a reason for hiding this comment

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

이 함수가 항상 Element 를 return 하는게 맞을까요?
그리고 아래 src/js/util/event.ts 파일에서 generic 을 사용하셨는데요, 요 함수도 generic 으로 표현해보면 좋겠네요!

Copy link
Author

Choose a reason for hiding this comment

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

오호...넵 감사합니다! 사실 별 생각 없이 쿼리셀렉터로 엘리먼트를 가져오니까, Element를 리턴할거라고 생각했어요! HTML 엘리먼트 관련 타입 더 공부하고 적용해보겠습니다 👍

Copy link

@HyeonaKwon HyeonaKwon left a comment

Choose a reason for hiding this comment

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

와 호프! 정리해주신 것과 수정사항 모두 확인했습니다. 자세히 적어주셔서 감동받았네요 👍

2단계에서 #4 (comment), #4 (comment) 이렇게 두 개 피드백 주시면 좋겠습니다!

2단계에서 봬요~ 고생 많으셨습니다!

@HyeonaKwon HyeonaKwon merged commit 5400a21 into woowacourse:moonheekim0118 Mar 31, 2022
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