Skip to content

[1주차] 전시원 미션 제출합니다.#6

Open
siwonblue wants to merge 17 commits intoCEOS-Developers:masterfrom
siwonblue:siwonblue
Open

[1주차] 전시원 미션 제출합니다.#6
siwonblue wants to merge 17 commits intoCEOS-Developers:masterfrom
siwonblue:siwonblue

Conversation

@siwonblue
Copy link

[1주차 전시원 미션 제출합니다.]

안녕하세요. CEOS 15기 프론트 전시원입니다. 일주차 과제 제출드립니다.
우선 완전한 기능 구현을 못 한 상태로 제출하게 되어서 죄송합니다.

  • 할일 <=> 완료를 뒤늦게 확인 (‘할일 => 완료’ & localStorage 로 데이터 저장까지 코드작성)
  • 그러려면 상태 관리가 필요한데 상태 관리를 하지 않은 상태로 코드를 작성
  • 고치려다 보니 form.addEventListner(‘submit’, 콜백)에서 콜백 지옥에 빠짐
  • css 구현 최소화
  • 시간 부족( 21학점 + 세오스 + 학회 … 하핫)

계속 시도하다 이전 커밋으로 revert 한 후 그 내용으로 제출드립니다.
배포 링크 : https://vanilla-todo-15th-delta.vercel.app/

image [그림1 원래 생각했던 구조]

image [그림2 망한 이유]

새롭게 배운 점

  • git fork, branch, revert, reset, pull request 사용
  • vercel 배포
  • 바닐라 자바스크립트를 이용한 DOM 조작 및 상태 관리
  • 김주현 프론트 파트장님 코드 보고 form.submit 말고 다른 방식으로 접근하면 되는 것을 깨달음

부족했던 점

  • 요구 사항 이해 부족
  • 동작 방식 설계 오류

어딘가 이상한 점

  • 커밋 메세지(제목+본문) 영어로 작성 (그래야 하는줄 알았습니당)
  • 커밋 순서 엉망 (다음부턴 예시를 잘 읽겠습니다)
  • 변수명이 가끔 이상함
  • 그냥 코드가 이상함

시간 내주셔서 코드 리뷰 해주시는 분들께 감사 인사 드리고 싶습니다.
저를 성장시키는 critic 언제나 환영입니다.

Question to mentor

  • 'fork => 로컬에 clone => 기능 구현 => commit => 기능 구현 => … 반복 => 마지막 완성 후 push' 인지
    아니면 기능구현때마다 push 해야하는지 질문드리고 싶습니당..

[Key Question]

  • DOM 은 무엇인가요?

    • 자바스크립트라는 언어가 동작하는 환경을 호스팅 환경이라 하는데, 웹브라우저는 대표적인 자바스크립트 호스팅 환경입니다. 각 호스팅 환경에서는 객체와 함수를 제공하고 웹브라우저는 웹페이지를 제어하는 역할을 하는 객체와 함수를 제공합니다. 그 중에 문서 객체 모델인 DOM(Document Object Model, DOM) 은 웹 페이지 내의 모든 콘텐츠를 객체로 나타내고 이 객체를 수정하여 웹 페이지를 조작할 수 있게 해줍니다.
      image [그림3 DOM 조작]
      image[그림4 JS로 DOM 조작]
  • HTML (tag) Element를 JavaScript로 생성하는 방법은 어떤 것이 있고, 어떤 방법이 가장 적합할까요?
    DOM 에서 각 요소들을 노드라고 부르는데 대표적인 노드로는 HTML tag 가 있습니다. 이 tag node 를 생성하는 방법은 다음과 같은 걸로 알고 있습니다. const div = document.createElement(‘div’)

  •  태그에서 발생하는 Event에는 어떤 것이 있고, 어떤 방법이 가장 적합할까요?

    • ‘change’ 인풋에 변화가 생길 때 해당 내용을 확인할 수 있어서 주로 사용하는 방법 중 하나인 걸로 알고 있습니다.
  • Flexbox Layout은 무엇이며, 어떻게 사용하나요?

    • 보통 container 를 설정하고 container에 display : flex, 속성을 추가하는 걸로 알고 있습니다.
    • container 의 자식들이 flex 속성을 통해 조작할 수 있는 요소가 됩니다.
    • flex-direction 을 통해서 주축을 설정하고 justify-contents 를 이용하여 주축 main-aixs 레이아웃을 설정합니다.
    • align-items 를 이용하여 교차축 cross-axis 에 대한 레이아웃을 설정할 수 있습니다.
  • JavaScript가 다른 언어들에 비해 주목할만한 점에는 어떤 것들이 있나요?

    • 자바스크립트는 사용자 친화적인 하이레벨 랭귀지입니다. 웹 브라우저에서 DOM tree 를 조작하기 위하여 만들어졌고 위에서 언급했듯이 웹 브라우저를 호스팅 환경으로 가지고 있습니다. 이에 더해 node.js 라는 새로운 호스팅환경이 제시되면서 서버사이드에서도 동작할 수 있게 됩니다. 이로 인해 하나의 언어를 이용하여 프론트와 서버를 동시에 다룰 수 있어 높은 생산성을 나타냅니다. 하지만 지나치게 유연하게 동작하기 때문에 디버깅에 취약하다는 약점을 가지고 있고 이를 대체하기 위해 typeScript 를 사용하는 추세입니다.
  • 코드에서 주석을 다는 바람직한 방법은 무엇일까요?

    • 가장 좋은 주석은 주석이 필요없는 코드, 주석이 길어지고 이상하면 코드를 수정
    • 코드를 쓰는 이유 설명
    • 코드를 쓰면서 주석을 같이 작성

전시원 added 17 commits March 15, 2022 11:03
Dom tree read
Set variable
If form value submitted, then eventListner execute callback function.
Callback function include:
1. preventDefault to refresh when value summitted
2. assign value variable name 'val'
3. assign 'val' object name 'obj'
4. push 'obj' to array name 'yetArr'
5. two othe function execute ( setYet, setYetLocal which will be mentioned later)
If localStorage has some value,
1. Pasrse value
2. Render that value

In this case, we use two category of localStorage:
[yetList,doneList]
Func1 setYetLocal include:
1. Set value in localStorage using localStorage.setItem('key','value').
   In this case, should use JSON type in value of localStorage.
   So we you JSON.stringify().

Func2 setValue include:
Same as Func1.
Function setYet include:
1.Create DOM node
2.Insert DOM node
3.'click' event listen which uses callback 'del(func 5)', 'done(func 6)'
Func SetDone includes:
1. Create DOM node
2. Get value in localStorage, then parse JSON into js Obj
3. Render that value in done list
Func 5 includes:
1. Delete rendering data in yetList
2. Delete localStorage data in yetList
Delete data both render and localStorage.
Func 6 done includes:
1. get node event occured, then get id
2. delete render
3. delte yet in localStorage
4. add done in localStorage
5. render using setDone(func 4)
While QA, find bug:
When use refresh, setDone func doesn't operate clearly.
So fix them and add setDone2 to operate clearly.

SetDone originally contains all function in done value,
But now divide that function into two function, setDone and setDone2.
Add Todo number, done number
Build list with isDone status
Both rendering and localStorege
Complete delete button
Change eventListen form => input button click
This reverts commit 150285b.
@corinthionia corinthionia self-requested a review March 18, 2022 10:31
Copy link
Member

@corinthionia corinthionia left a comment

Choose a reason for hiding this comment

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

안녕하세요 시원 님 🙌🏻

우선 정성스러운 리드미와 커밋 메세지를 세세하게 작성해 주신 점이 인상깊었습니다 👍🏻 다만 변수나 함수의 이름을 조금 더 명확하게 지어 주시면 좋을 것 같다는 생각이 듭니다.

리드미 중간에 써 주신 질문에도 답을 해 드리자면, 둘 중 어떤 게 더 적절한 방식인지 정답은 없는 것 같습니다. 저는 개인 프로젝트를 진행할 때에는 한번에 몰아서 push를 하는 편이지만 협업 시에는 기능 구현이 끝난 후 바로 push하는 식으로 진행했었습니다. 제 개인적인 생각으로는 협업 시 다른 팀원분들도 코드를 최신으로 유지해야 할 필요가 있기 때문에 기능 구현 후 push하는 방식이 더 적절해 보입니다!

구현이 안 된 부분들은 스터디 시간 전까지 최대한 구현해 보시길 바랄게요! 과제하시느라 고생 많으셨고 스터디 시간 때 뵙겠습니다~

+) 그리고 PR 제목 수정 부탁드립니다~!

// 함수 6, delete data both render and localStorage
const done = (e) => {
const id = e.target.parentElement.id;
const text = e.target.parentElement.innerText.slice(4, -1);
Copy link
Member

Choose a reason for hiding this comment

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

text는 어디에 사용되는 변수인가요?

Copy link
Author

Choose a reason for hiding this comment

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

처음에 done (할일) delete , 이렇게 할일 생성목록을 만들었고 done을 클릭하면 완료 목록으로 내려가게 만들었는데요. text 에 할 일에 해당하는 텍스트만 추출하려고 했습니다.
나중에 보니까 할일 자체를 클릭하면 완료목록으로 이동하길래 done 이라는 버튼을 지웠습니당 ㅠ 고쳐야했는데 안됐네요 감사합니다

Comment on lines +10 to +12
const yetText = 'yetList';
const doneText = 'doneList';
const yetBtnText = 'yetBtn';
Copy link
Member

Choose a reason for hiding this comment

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

저는 이럴 경우 변수명과 문자열 값을 똑같이 설정하는 게 더 좋을 것 같습니다. 코드 리뷰하면서 이게 은근 헷갈리더라구요...!

Suggested change
const yetText = 'yetList';
const doneText = 'doneList';
const yetBtnText = 'yetBtn';
const yetList = 'yetList';
const doneList = 'doneList';
const yetBtn = 'yetBtn';

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 +88 to +90
const temp = JSON.parse(localStorage.getItem(yetText));
const yet = temp.filter((i) => i.id != id);
const done = temp.filter((i) => i.id == id);
Copy link
Member

Choose a reason for hiding this comment

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

local storage에 doneList도 저장해 두셨는데 yetList만 가지고 필터링한 이유가 있으신가요? 진행 중인 할일 목록(yetList)에 있는 항목들을 기준으로 yetdone을 나누기 때문에 완료한 할일 목록(doneList)의 개수가 제대로 카운팅되지 않는 것 같습니다.

또한 변수명이 list를 의미하는 건지, 그 안의 항목들을 의미하는 건지 약간 모호한 느낌도 있는 것 같아요. 아래처럼 수정하면 어떨까요? 또한 iterator의 이름도 명확히 작성하는 게 좋습니다!

Suggested change
const temp = JSON.parse(localStorage.getItem(yetText));
const yet = temp.filter((i) => i.id != id);
const done = temp.filter((i) => i.id == id);
const temp = JSON.parse(localStorage.getItem(yetText));
const yetList = temp.filter((todo) => todo.id != id);
const doneList = temp.filter((todo) => todo.id == id);

return JSON.parse(localStorage.getItem(doneText))?.length;
};

const setDone2 = () => {
Copy link
Member

Choose a reason for hiding this comment

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

함수의 이름이 모호한 감이 있습니다. renderDoneList 같은 이름은 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

네 맞아요 그게 더 좋아보여요. setDone 이라고 처음에 했다가 무슨 이유때문에 하나 더 만들었는데 함수명에 신경을 못 쓰고 아무렇게 지었네요 ㅠ

Comment on lines +107 to +113
const getTodoNum = () => {
return JSON.parse(localStorage.getItem(yetText))?.length;
};

const getDoneNum = () => {
return JSON.parse(localStorage.getItem(doneText))?.length;
};
Copy link
Member

Choose a reason for hiding this comment

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

개인적으로 이 함수들은 updateNum 함수와 분리할 필요가 없어 보입니다...!

Comment on lines +128 to +131
const a = getTodoNum();
const b = getDoneNum();
todoNum.innerText = `To Do (${a == undefined ? 0 : a})`;
doneNum.innerText = `DONE (${b == undefined ? 0 : b})`;
Copy link
Member

Choose a reason for hiding this comment

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

이 부분도 a, b 말고 직관적인 변수명으로 바꿔 주세요! 또한 아래처럼 작성하셔도 똑같이 동작합니다.

Suggested change
const a = getTodoNum();
const b = getDoneNum();
todoNum.innerText = `To Do (${a == undefined ? 0 : a})`;
doneNum.innerText = `DONE (${b == undefined ? 0 : b})`;
const a = getTodoNum();
const b = getDoneNum();
todoNum.innerText = `To Do (${a})`;
doneNum.innerText = `DONE (${b})`;

Copy link

@S-J-Kim S-J-Kim left a comment

Choose a reason for hiding this comment

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

안녕하세요 시원님

프론트엔드 멘토 김선종입니다.

코드를 구조적으로 잘 짜주셨네요. 보는 입장에서 잘 이해할 수 있었습니다. 다만 변수의 네이밍은 조금 더 명확하게 해주신다면 조금 더 보기 좋은 코드가 될 수 있을것이라 생각합니다. 그 외에는 크게 코멘트 드릴 사항이 없었고, 참고 하시면 좋을 내용들을 남겨보았습니다.

과제 하느라 고생하셨습니다

Comment on lines +21 to +27
const setYetLocal = (arr) => {
localStorage.setItem(yetText, JSON.stringify(arr));
};
// 함수2, setValue in localStorage
const setDoneLocal = (arr) => {
localStorage.setItem(doneText, JSON.stringify(arr));
};
Copy link

Choose a reason for hiding this comment

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

const setLocalStorage = (itemType, itemList) => {
  localStorage.setItem(itemType, JSON.stringify(itemList));
}

const setYetLocal = (arr) => setLocalStorage(yetText, arr)
const setDoneLocal = (arr) => setLocalStorage(doneText, arr)

이렇게 리팩토링 해보면 어떨까요? 유지보수성이 개선될 것 같습니다.

Copy link
Author

Choose a reason for hiding this comment

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

아아 훨씬 깔끔하네요 감사합니당 !!

};

// 함수 5, delete data both render and localStorage
const del = (e) => {
Copy link

Choose a reason for hiding this comment

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

Suggested change
const del = (e) => {
const deleteTodoItem = (e) => {

함수 이름이 너무 축약된 감이 있죠? 다른 사람이 코드를 볼 때 제목만으로도 기능을 얼추 유추할 수 있어야 합니다.

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 +127 to +132
const updateNum = () => {
const a = getTodoNum();
const b = getDoneNum();
todoNum.innerText = `To Do (${a == undefined ? 0 : a})`;
doneNum.innerText = `DONE (${b == undefined ? 0 : b})`;
};
Copy link

Choose a reason for hiding this comment

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

const getTodoNum = () => {
  return JSON.parse(localStorage.getItem(yetText))?.length ?? 0
};

getTodoNum()이라는 함수의 네이밍을 고려해볼때, 해당 함수는 항상 숫자만을 반환하는 것이 좋겠죠. 이런 경우에는 getTodoNum()을 nullish coalescing operator를 사용해 이렇게 리팩토링 하면 주현님의 코멘트 suggestion처럼 수정해 볼 수 있을 것 같습니다.

Copy link
Author

Choose a reason for hiding this comment

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

아하.. 처음에 ?.(optional chaining) 만 사용했는데 안돼서 저런 식으로 코드를 적었는데요.
?? 를 사용하면 해결이 되는군요 감사합니다!

Copy link

@chaaerim chaaerim left a comment

Choose a reason for hiding this comment

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

시원님 안녕하세요! 1주차 스터디 코드리뷰파트너를 맡게 된 김채림입니다! 😀
코드리뷰를 처음 해보기도 하고 아직 저도 부족한 부분이 많아서 조심스럽지만 작성해주신 코드 잘 봤습니다 !!
특히 로컬스토리지 적용하신 부분 보면서 반성의 시간을 가졌습니다.. 저도 빨리 적용해봐야겠어요 ㅎㅎ..
또 리드미에 작성해주신 것처럼 구조를 먼저 생각하고 구현하신 점도 인상깊었습니다!!
냅다 코드부터 작성하는 제 습관에 대해 고민해보게 되었습니다 🤣
다른 분들이 리뷰를 잘 달아주셔서 제가 크게 코멘트 드릴 점이 없었던 것 같네요! 꼼꼼하게 작성해주신 주석 덕분에 코드리뷰도 하기 좋았던 것 같습니다. 스터디 시간에 뵙겠습니다!

#yet{
border: 1px solid red;
}
#formDiv{

Choose a reason for hiding this comment

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

#yet#done 부분에 overflow도 같이 설정해주시면 범위 밖으로 목록이 넘어가는 걸 방지할 수 있을 것 같습니다.

Copy link
Author

Choose a reason for hiding this comment

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

채림님 안녕하세요 저도 채림님 코드 봤는데 너무 잘해두시고 다른 분들께서 글 많이 남기셔서
저는 많은 내용을 남겨드리지 못했네요 ㅠ 제 코드 정성스럽게 봐주셔서 감사합니당

<div id="yet">
<div id="formDiv">
<form action="" id="input-form">
<input id="input-box" type="text" required>

Choose a reason for hiding this comment

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

저도 required 로 입력값이 없을 경우를 처리해줘야겠네요..!!

Choose a reason for hiding this comment

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

저도 required attribute는 알지 못했었는데, 좋은 포인트인 것 같습니다.

Comment on lines +56 to +64
const setDone = (obj) => {
const li = document.createElement('li');
const span = document.createElement('span');
span.innerText = obj.contents;
li.id = obj.id;
li.append(span);
doneList.append(li);
updateNum();
};

Choose a reason for hiding this comment

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

yetArrdoneArr 를 구분해서 한번 더 클릭했을 때 다시 투두 목록으로 돌아갈 수 있도록 구현하면 좋을 것 같습니다! 그리고 여기서 delete 버튼이 같이 추가가 안되어 done에서 삭제가 불가능한 것 같은데 event를 받아서

const doneToDo=e.target.parentElement;
doneList.append(doneToDo);

이렇게 delete 버튼까지 다같이 가져와서 추가하는건 어떨까 하네요..!!

Comment on lines +64 to +67
.yetBtn{
border : none;
background : none
}

Choose a reason for hiding this comment

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

yetBtn 과 휴지통 img이 hover될 때 cursor: pointer;를 추가해주시면 더 직관적으로 투두를 클릭했을 때 done으로 넘어가는 것을 알 수 있을 것 같습니다 !!

Comment on lines +115 to +125
const setDone2 = () => {
const li = document.createElement('li');
const span = document.createElement('span');
const temp = JSON.parse(localStorage.getItem(doneText));
temp.map((i) => {
span.innerText = i.contents;
li.id = i.id;
li.append(span);
});
doneList.append(li);
};

Choose a reason for hiding this comment

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

setDonesetDone2를 따로 만드신 이유가 있으실까요?! 겹치는 부분이 많아 보이는데 코드리뷰가 처음이다보니 의도대로 제가 읽지 못하는 것일까봐 여쭤봅니다!!

Copy link

@jdaeheon jdaeheon left a comment

Choose a reason for hiding this comment

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

안녕하세요, 코드 리뷰 맡게된 15기 정대헌입니다!
시간이 없으셔서 코드를 정리하지 못하신 것 같은 흔적이 많이 있더라구요.
여유가 있으셨다면 조금 더 구조가 잘 보였을 것 같은데 아쉬움이 있는 것 같습니다.
코드에서 리엑트의 흔적도 조금 보이는데, 저도 많이 동감하는 바입니다.
수고하셨습니다.

<div id="yet">
<div id="formDiv">
<form action="" id="input-form">
<input id="input-box" type="text" required>

Choose a reason for hiding this comment

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

저도 required attribute는 알지 못했었는데, 좋은 포인트인 것 같습니다.

</div>
<div id="b">
<div id="todoNum">To Do (0)</div>
<ul id="yet-list">

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.

오 그렇게 해야하는 이유가 있나요?

Copy link

@S-J-Kim S-J-Kim Mar 23, 2022

Choose a reason for hiding this comment

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

대신 답변을 달아드리자면, 한 개의 HTML에서 id attribute는 한 개의 엘리먼트에만 부여해야 하는것이 원칙입니다. 말 그대로 identification을 위한 속성이기 때문이죠. 브라우저 parser의 예외처리에 의해 에러가 없지만, id 중복은 원칙적으로 오류 발생입니다.

// 함수3, render in yetList
const setYet = (obj) => {
// DOM 조작(생성)
const li = document.createElement('li');

Choose a reason for hiding this comment

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

이부분 함수로 정의해서 setYet(), setDone()에 모두 활용하는 것도 좋을 것 같습니다.

input:focus {outline:none;}
* {
box-sizing: border-box;
font-family: 'SpoqaHanSansNeo-Regular';

Choose a reason for hiding this comment

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

폰트를 로드하지 못했을 때 기본 폰트를 제시해주시는 것도 좋을 것 같습니다!

Suggested change
font-family: 'SpoqaHanSansNeo-Regular';
font-family: 'SpoqaHanSansNeo-Regular', sans-serif;

@siwonblue siwonblue changed the title Siwonblue [1주차 전시원 미션 제출합니다.] Mar 22, 2022
@siwonblue siwonblue changed the title [1주차 전시원 미션 제출합니다.] [1주차] 전시원 미션 제출합니다. Apr 9, 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.

5 participants