Skip to content

[1주차] 안혜연 미션 제출합니다. #8

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

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

noeyeyh
Copy link

@noeyeyh noeyeyh commented Mar 15, 2024

1주차 미션: Vanilla-Todo

배포 링크

배포 링크

기능 구현

  • 입력창을 통해 할 일 추가
  • 삭제 버튼 클릭으로 할 일 삭제
  • 체크 버튼 클릭으로 완료 표시, 밑줄 그어 완료 표시
  • 날짜 출력
  • 총 할 일 개수와 완료한 일 개수 출력
  • 로컬 스토리지 저장

느낀점

안녕하세요, 19기 프론트 안혜연입니다!

리액트 없이 순수 자바스크립트로만 구현하며 부족함을 많이 느꼈습니다. 바닐라 js를 많이 경험해보지 않아서 헷갈리는 부분이 많았는데, 작성하고 보니 깔끔하게 코드를 작성하지 못한 것 같습니다..

그리고 커밋 컨벤션에 맞춰 기능 단위로 커밋을 날리려고 노력했으나 명확하게 기능별로 나누지 못한 것 같아 아쉽습니다. 다음 과제 때는 더 신경써서 깔끔하게 작성하겠습니다.

Key Questions

1. DOM은 무엇인가요?

DOM은 Document Object Model의 약자로, 웹 문서의 구조를 나타내는 방식입니다.

  • DOM을 이용하여 HTML 요소로 구성된 웹 페이지를 동적으로 움직이게 만들 수 있습니다.

  • DOM은 트리 구조로 구성되어, 트리의 각 브랜치는 노드에서 끝나며 각 노드는 객체를 갖습니다.

2. HTML (tag) Element를 JavaScript로 생성하는 방법은 어떤 것이 있고, 어떤 방법이 가장 적합할까요?

document.createElement() 함수를 사용하는 것이 가장 직관적이라하여 이번 과제에서 많이 사용했습니다. 이는 새로운 HTML 요소를 생성하여 이에 새로운 속성을 추가합니다. 그리고 문서 내 다른 요소에 append, appendChild를 통해 이를 추가할 수 있습니다. document.createElement() 함수 외에도 innerHTML속성을 사용하여 내부 HTML을 직접 변경하는 방법도 있습니다.

3. Semantic tag에는 어떤 것이 있으며, 이를 사용하는 이유는 무엇일까요?

semantic tag는 의미론적 태그로 HTML에서 사용되는 의미를 명확하게 전달하여 웹 페이지의 구조를 더 명확하게 해줍니다. 이를 통해 코드의 가독성과 유지 보수성을 높일 수 있습니다. 실제로 semantic tag를 사용하면 <div><span>과 같은 태그만 사용하는 것보다 코드가 눈에 쉽게 읽히는 것 같아 이번 과제에서도 최대한 semantic tag를 사용하려고 했습니다.

또한 검색 엔진은 웹 페이지의 구조와 콘텐츠를 이해하기 위해 semantic 태그를 활용하여 웹 페이지의 주요 콘텐츠와 구조를 더 쉽게 파악할 수 있습니다.

  • <header>: 웹 페이지의 헤더 부분을 나타냄

  • <nav>: 네비게이션 링크의 집합을 나타냄

  • <section>: 주제별로 문서를 나누는 데 사용됨

  • <footer>: 웹 페이지의 하단 푸터 부분을 나타냄

  • <main>: 문서의 주요 콘텐츠를 나타내며 한번씩만 사용됨

4. Flexbox Layout은 무엇이며, 어떻게 사용하나요?

Flexbox는 css의 레이아웃 모델로 행과 열로 아이템을 정렬합니다.

  • flex-direction: 주 축의 방향을 행과 열로 설정함

  • flex-wrap: 아이템들이 컨테이너 밖으로 넘어갔을 때 줄바꿈 여부를 설정함

  • justify-content: 주 축을 중심으로 어떠한 방식으로 아이템을 정렬할 건지 설정함

  • align-items: 교차 축을 중심으로 어떠한 방식으로 아이템을 정렬할 건지 설정함

5. JavaScript가 다른 언어들에 비해 주목할 만한 점에는 어떤 것들이 있나요?

  • 자바스크립트는 인터프리터 언어로 다른 언어에 비해 시간이 적게 소요되어 프로그램 실행 속도를 높일 수 있습니다.

  • 다양한 라이브러리와 프레임워크를 제공하여 효율적이고 빠르게 개발할 수 있습니다.

  • 대부분의 웹 브라우저에서 지원되어 다양한 플랫폼에서 사용할 수 있습니다.

  • Node.js와 같은 기술을 사용하면 프론트엔드와 백엔드 모두에서 동일한 언어를 사용할 수 있게 하여 개발 과정을 간소화하고 개발 시간을 단축할 수 있습니다.

6. 코드에서 주석을 다는 바람직한 방법은 무엇일까요?

무작정 주석을 많이 다는 것은 오히려 가독성을 낮추는 것 같아 간결하고 명확하게 작성하는 것이 바람직하다고 생각합니다. 그리고 주석의 스타일 또한 일관되게 작성해야 합니다.

링크 및 참고자료

Copy link

@westofsky westofsky 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 +134 to +143
const date =
today.getFullYear() +
'-' +
(today.getMonth() + 1).toString().padStart(2, '0') +
'-' +
today.getDate().toString().padStart(2, '0');

const day = days[today.getDay()];

document.getElementById('date').innerText = `${date} ${day}`;

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.

앗 그럼 date를 더 간단하게 작성할 수 있을 것 같아요..! 감사합니다!!

Comment on lines +61 to +64
.todo-text {
margin-left: 5px;
font-size: 15px;
}

Choose a reason for hiding this comment

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

사진처럼 길어지면 버튼이 세로로 정렬돼서
image
버튼을 감싸는 divdisplay:flex;를 주거나 .todo-text에 고정 width값을 주어도 좋을 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

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

이번주 과제에서는 width값을 지정해서 고쳐보겠습니다!

function updateCount() {
const toDoCount = toDoArr.length;
const doneToDoCount = doneToDoArr.length;
document.getElementById('count').innerText = `${doneToDoCount}/${toDoCount}`;

Choose a reason for hiding this comment

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

updateCount() 할 때마다 dom에 접근하게 될 것 같아서 상단에 한번에 선언해두고 innerText만 설정해도 좋을 것 같아요

Comment on lines +53 to +69
checkButton.addEventListener('click', () => {
const isCompleted = span.classList.contains('text-decoration-line-through');
span.classList.toggle('text-decoration-line-through', !isCompleted); // CSS 클래스를 통해 스타일 변경

checkButton.classList.toggle('checked', !isCompleted);

if (!isCompleted) {
doneToDoArr.push(newToDo);
} else {
const doneIndex = doneToDoArr.indexOf(newToDo);
if (doneIndex !== -1) {
doneToDoArr.splice(doneIndex, 1); // 체크 해제되면 doneToDoArr에서 제거
}
}
saveToDo();
updateCount();
});

Choose a reason for hiding this comment

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

콜백함수가 길어질 때 따로 빼놔도 가독성 측면에서 좋을 것 같습니다!

Comment on lines +95 to +112
function loadFromLocalStorage() {
const savedDoneToDo = localStorage.getItem('doneToDoArr');
const savedToDo = localStorage.getItem('toDoArr');

if (savedDoneToDo !== null) {
const parsedDoneToDo = JSON.parse(savedDoneToDo);
doneToDoArr = parsedDoneToDo;
}

if (savedToDo !== null) {
const parsedToDo = JSON.parse(savedToDo);
toDoArr = parsedToDo;
parsedToDo.forEach((toDoItem) => {
const isChecked = doneToDoArr.includes(toDoItem); // doneToDoArr에 포함되어 있으면 true
showToDo(toDoItem, isChecked); // 체크 상태 정보를 showToDo 함수로 전달
});
}
}

Choose a reason for hiding this comment

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

큰 차이는 없지만 이 부분은 한번 이렇게도 간소화 할 수 있을 것 같아요!

Suggested change
function loadFromLocalStorage() {
const savedDoneToDo = localStorage.getItem('doneToDoArr');
const savedToDo = localStorage.getItem('toDoArr');
if (savedDoneToDo !== null) {
const parsedDoneToDo = JSON.parse(savedDoneToDo);
doneToDoArr = parsedDoneToDo;
}
if (savedToDo !== null) {
const parsedToDo = JSON.parse(savedToDo);
toDoArr = parsedToDo;
parsedToDo.forEach((toDoItem) => {
const isChecked = doneToDoArr.includes(toDoItem); // doneToDoArr에 포함되어 있으면 true
showToDo(toDoItem, isChecked); // 체크 상태 정보를 showToDo 함수로 전달
});
}
}
function loadFromLocalStorage() {
const doneToDoArr = JSON.parse(localStorage.getItem('doneToDoArr') || '[]');
const toDoArr = JSON.parse(localStorage.getItem('toDoArr') || '[]');
toDoArr.forEach(toDoItem => {
const isChecked = doneToDoArr.includes(toDoItem);
showToDo(toDoItem, isChecked);
});
}

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 +5 to +6
let toDoArr = [];
let doneToDoArr = [];

Choose a reason for hiding this comment

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

doneToDoArr에 toDoArr의 일부가 들어가는 구조인데 다음에는 두 배열을 아예 분리해서 다뤄보는 건 어떨까요 ???

Copy link
Member

Choose a reason for hiding this comment

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

배열을 통해 할 일을 관리하셨는데,
나중에 더 세부적인 기능을 추가하시려고 할 때
할일을 객체를 통해 관리하시면, 할 일 텍스트말고도, 특정 할일에 대한 중요도나 완료 여부 등등을 같이 관리할 수 있어서 더 효율적일 것 같아서 객체를 통해 관리하시는 것도 추천드려봐요!!
아예 객체 하나에 할 일, 해당 할일의 완료 여부를 같이 관리해서
let toDoArr = [];
let doneToDoArr = [];
배열을 두 개로 나누지 않고, 하나의 객체해서 관리할 수 있어서요!

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

@CSE-pebble CSE-pebble left a comment

Choose a reason for hiding this comment

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

코드가 너무 깔끔하고 UI도 너무 예뻐요~!! 수고하셨습니다!

</head>

<body>
<div class="container"></div>
<div class="container">
<h1 class="title">To-Do List</h1>

Choose a reason for hiding this comment

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

시맨틱 태그를 사용해주셔서 넘 보기 편하네요!! <h1> 태그도 좋지만, 제목이니까 <header> 태그를 써줘도 좋을 것 같아요!!

Comment on lines +99 to +111
if (savedDoneToDo !== null) {
const parsedDoneToDo = JSON.parse(savedDoneToDo);
doneToDoArr = parsedDoneToDo;
}

if (savedToDo !== null) {
const parsedToDo = JSON.parse(savedToDo);
toDoArr = parsedToDo;
parsedToDo.forEach((toDoItem) => {
const isChecked = doneToDoArr.includes(toDoItem); // doneToDoArr에 포함되어 있으면 true
showToDo(toDoItem, isChecked); // 체크 상태 정보를 showToDo 함수로 전달
});
}

Choose a reason for hiding this comment

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

localStorage에서 getItem을 한 결과를 변수에 저장해주고, parse 하기 전에 먼저 null 체크 해주는거 너무 좋네요! 불필요한 parse 작업을 없애줄 수 있을 것 같아요!

}

// 오늘 날짜와 요일
function todayDate() {

Choose a reason for hiding this comment

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

JS 함수명은 동사로 시작하는게 좋다고 합니다! 요 링크 함수 네이밍 부분 참고하시면 좋을 것 같아요! 네이밍은 매번 할 때마다 어려운 것 같습니당..

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 +134 to +139
const date =
today.getFullYear() +
'-' +
(today.getMonth() + 1).toString().padStart(2, '0') +
'-' +
today.getDate().toString().padStart(2, '0');

Choose a reason for hiding this comment

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

오 padStart() 메서드 배워갑니다!!

Comment on lines +134 to +139
const date =
today.getFullYear() +
'-' +
(today.getMonth() + 1).toString().padStart(2, '0') +
'-' +
today.getDate().toString().padStart(2, '0');

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.

오오 템플릿 리터럴 방식 쓰면 훨씬 간단하게 작성할 수 있을 것 같아요..!! 이번 과제에서는 그렇게 수정해보겠습니다!

deleteButton.className = 'delete-btn';
checkButton.className = 'check-btn';

span.innerText = newToDo;

Choose a reason for hiding this comment

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

innerText 대신 textContext를 사용해줄 수도 있어요! 이 블로그 참고해보세요!!

Copy link
Author

Choose a reason for hiding this comment

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

innerText 대신에 textContext로 쓸 수 있군요..! 블로그 링크 감사해요 참고해볼게요!!

@jinnyleeis
Copy link
Member

안녕하세요 혜연님!
우선 구현해주신 UI가 가 메모지 느낌이 나고 너무 깔끔하고 귀엽네요! !
그리고 form 태그를 통해 할 일을 추가를 구현하셨는데, 저는 input 태그로만 구현해서 이것도 인상깊었습니다!
form 태그를 잘 사용해 본적이 없는데, 활용해봐야겠어요!

저는 appendChild()를 써서 요소를 하나씩 추가했는데, 특정 요소에 추가해야하는 요소가 여러개일 때 append()를 통해 추가하신게 정말 효율적인 것 같다는 생각이 듭니다! 저도 리팩토링할 때, append()를 사용해야 겠네요!

css 코드를 보니, px를 통해 요소들의 크기를 지정하신 것 같은데, 그럼 화면이 반응형으로 작동하는게 불가능해서
다음엔 절대 단위 px말고 flex랑 상대 단위를 적절히 활용해서 반응형으로 개선해보시는 것도 추천드려봐요!!
잘 봤습니다!

@@ -3,7 +3,7 @@ body {
padding: 10px;
}

.canvas {
.container {
width: 375px;
Copy link
Member

Choose a reason for hiding this comment

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

px말고 %나, vh/vw등,
상대 단위를 써보는 것도 좋을 것 같아요!

Comment on lines +5 to +6
let toDoArr = [];
let doneToDoArr = [];
Copy link
Member

Choose a reason for hiding this comment

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

배열을 통해 할 일을 관리하셨는데,
나중에 더 세부적인 기능을 추가하시려고 할 때
할일을 객체를 통해 관리하시면, 할 일 텍스트말고도, 특정 할일에 대한 중요도나 완료 여부 등등을 같이 관리할 수 있어서 더 효율적일 것 같아서 객체를 통해 관리하시는 것도 추천드려봐요!!
아예 객체 하나에 할 일, 해당 할일의 완료 여부를 같이 관리해서
let toDoArr = [];
let doneToDoArr = [];
배열을 두 개로 나누지 않고, 하나의 객체해서 관리할 수 있어서요!

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.

4 participants