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주차] 김동혁 미션 제출합니다. #2

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

Conversation

ddhelop
Copy link
Member

@ddhelop ddhelop commented Mar 14, 2024

🔗 링크

vanilla-todo-19th-dh.vercel.app/

📌 기능구현

  • 할 일 입력창(Form)에 텍스트를 입력하고 enter 혹은 버튼클릭으로 할 일 추가
  • 할 일 추가/삭제 시 애니메이션
  • 할 일 삭제
  • 할 일 완료 표시
  • localStorage에 할 일, 완료 상태 저장
  • 모바일 (768px 이하) 반응형 스타일

🤔 후기

이번 미션을 통해 프레임워크 및 라이브러리 이용없이 HTML, CSS, JS만으로 개발을 하는게 생각보다 쉽지 않았고, 디버깅 하는 것도 정말 어렵다고 느꼈습니다... DOM을 사용하여 html 구조를 조작하는것도 쉽지 않았고, react hook의 유용함과 편리함을 다시 알았습니다. 또 JS 코드를 한 파일에 몰아 넣다보니 코드 가독성도 떨어지고 나중에 유지보수할 때 찾기 힘들 것 같다는 생각을 했습니다.
자바스크립트 DOM조작에 대해 낯설었는데 이번 과제를 통해서 어느 정도 감을 잡은 것 같아 매우 유익했습니다.


📄 Key Questions

1. DOM은 무엇인가요?

Document Object Model, HTML 및 XML 문서의 프로그래밍 인터페이스 브라우저는 DOM을 사용하여 문서를 구조화된 데이터로 표현하며, 이를 통해 프로그래밍 언어가 문서 구조, 스타일, 내용 등을 읽고 변경할 수 있게 합니다.

JavaScript는 DOM을 사용하여 HTML 문서의 내용, 구조, 스타일을 동적으로 조작하는 방법 중 하나입니다. 예를 들어, JavaScript를 사용하여 DOM 요소를 찾아 그 내용을 변경하거나, 사용자의 액션에 반응하여 페이지에 새로운 HTML 요소를 추가할 수 있습니다.

다음은 DOM을 이용해 동적인 웹 페이지를 만드는데 자주 쓰이는 기능들 몇 가지입니다.
(getElementById, querySelector, querySelectorAll, createElement, removeChild, addEventListener).


2. HTML (tag) Element를 JavaScript로 생성하는 방법은 어떤 것이 있나요?

JS로 HTML Element를 생성하는 방법에는 여러가지가 있습니다.

  1. createElement를 사용해 요소 생성
  2. textContent, innerHTML 프로퍼티 사용
  3. setAttribute 이용 속성 추가
  4. appendChild, insertBefore 생성한 요소를 특정 부분에 삽입

2-1. 어떤 방법이 가장 적합할까요?

요소를 생성하고 DOM에 추가하는 방법은 상황에 따라 다를 수 있습니다. 그러나 대부분의 경우 createElementappendChild (또는 insertBefore) 메서드를 사용하는 방법이 가장 기본적이고 널리 사용되며, 대부분의 요구 사항을 충족시킬 수 있어 많이 사용합니다.


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

footer: 문서나 섹션의 바닥글을 정의할 때 사용합니다.
header: 문서나 섹션의 머리글을 정의할 때 사용합니다.
main: 문서의 주요 콘텐츠를 정의할 때 사용합니다. 문서당 하나의 main 요소만 있어야 합니다.
nav: 탐색 링크를 정의할 때 사용합니다.
section: 문서의 일반적인 섹션을 정의할 때 사용합니다. 각 section은 주제별 콘텐츠와 해당 헤더를 포함해야 합니다.
aside: 본문 내용과 간접적으로 관련된 부분을 정의할 때 사용합니다. 예를 들어, 사이드바나 콜아웃 박스 등이 있습니다.


Semantic 태그를 사용하는 이유

  1. Semantic 태그는 웹 페이지의 구조를 더 명확하게 표현하므로, 개발자들이 문서의 구조를 쉽게 이해할 수 있습니다.
  2. 검색 엔진 최적화(SEO): 검색 엔진은 semantic 태그를 사용하여 콘텐츠의 구조와 중요성을 파악합니다. 이는 검색 결과에서의 노출과 순위에 긍정적인 영향을 미칩니다.

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

CSS의 한 레이아웃 모델, 복잡한 레이아웃을 간단하고 예측 가능한 방식으로 구현할 수 있게 해주며, 특히 항목의 크기가 미리 알려지지 않은 경우나 동적인 화면 크기에서의 반응형 디자인을 구현할 때 유용합니다.


Flex 컨테이너 속성

  • display: flex 또는 inline-flex 값을 사용하여 Flex 컨테이너를 정의합니다.
  • flex-direction: 아이템들의 주 축(main axis)을 설정합니다. 값으로는 row, row-reverse, column, column-reverse 등이 있습니다.
  • flex-wrap: 아이템들이 컨테이너를 벗어날 때 줄 바꿈 여부를 결정합니다. nowrap, wrap, wrap-reverse 등의 값을 사용할 수 있습니다.
  • justify-content: 주 축(main axis)을 따라 아이템들의 정렬 방법을 결정합니다. 예를 들어 flex-start, flex-end, center, space-between, space-around 등이 있습니다.
  • align-items: 교차 축(cross axis)을 따라 아이템들의 정렬 방법을 결정합니다. flex-start, flex-end, center, baseline, stretch 등의 값이 사용됩니다.
  • align-content: 여러 줄의 아이템들이 교차 축에 걸쳐 어떻게 정렬될지 결정합니다.

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

  1. 웹 브라우저만 있으면 바로 코드를 작성하고 결과를 확인할 수 있으며, 이는 학습 과정에서 큰 장점으로 작용한다고 생각합니다.
  2. Node.js나 nest.js를 통해 JavaScript는 서버 사이드 개발에도 사용되며, 이로 인해 개발자는 프론트엔드와 백엔드 모두 동일한 언어를 사용할 수 있는 장점이 있습니다.
  3. NPM(Node Package Manager)을 통해 사용할 수 있는 수십만 개의 라이브러리가 있어 개발에 용이합니다.
  4. React, Angular, Vue.js 등 다양한 프레임워크와 라이브러리 덕분에 UI 개발, 애플리케이션 개발, 실시간 어플리케이션 등 다양한 영역에서 JavaScript의 사용이 확대되었습니다.

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

저는 명확하고 최대한 간결한 주석을 다는 것이 바람직한 방법이라고 생각합니다.
저가 코드나 글을 작성할때 가장 중요하게 여기는것이 가독성인데, 이것은 코드에 주석을 명확하고 간결하게 작성하는 것이 가독성을 높이는 방법이라고 생각합니다. 다른사람이 본인의 코드를 봐도 쉽게 수정할 수 있고, 이해하는데 오랜시간이 안걸리게 주석을 다는 것이 바람직한 방법이라고 생각합니다.

<!-- input container -->
<div class="WriteForm">
<div class="writeTodoForm">
<img src="./icon/check.svg" class="check_icon" />
Copy link

@songess songess Mar 16, 2024

Choose a reason for hiding this comment

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

svg를 사용해 훨씬 깔끔한 거 같아요!

Copy link

Choose a reason for hiding this comment

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

맞아요 😆 여기서 alt 태그로 이미지 속성값을 넣어주면 더 좋아요 !

우리는 웹 접근성을 위해서 코드를 짤때 시각장애인을 위해 화면을 읽어주는 기능인 '스크린리더'를 고려해주어야 하는데요,

스크린 리더는 img 태그에 대해 이런 특징을 가진다고 해요!

  1. alt 태그를 명시해두지 않으면 src값을 읽어주고
  2. alt= "" 라고 명시하면 해당 이미지를 읽지 않고 넘어가고
  3. alt= "이미지를 나타내는 단어" 라고 명시하면 '이미지를 나타내는 단어' 를 읽어준답니다 > <

Comment on lines +2 to +8
const today = new Date();
const options = {
month: "long",
day: "numeric",
weekday: "long",
};
const dateString = today.toLocaleDateString("ko-KR", options);
Copy link

Choose a reason for hiding this comment

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

toLocalDateStringoptions를 사용해 날짜표시를 이렇게 할 수 있군요. 배워갑니다!

Copy link
Member

Choose a reason for hiding this comment

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

이 방법은 저도 배워갑니다...!!

@@ -8,7 +8,22 @@
</head>

<body>
<div class="container"></div>
<div class="wrapper">
<div class="header">✓ To Do</div>
Copy link

Choose a reason for hiding this comment

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

semantic 태그가 사용되었으면 더 좋았을 것 같아요!

Copy link
Member Author

Choose a reason for hiding this comment

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

semantic 태그를 사용해서 리팩토링 해볼게요 감사합니다.!!

@@ -8,3 +8,97 @@ const options = {
const dateString = today.toLocaleDateString("ko-KR", options);

document.getElementById("todayDate").innerText = dateString;

document.addEventListener("DOMContentLoaded", function () {
Copy link

Choose a reason for hiding this comment

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

DOMContentLoaded을 사용하신 이유가 궁금해요!

Copy link

Choose a reason for hiding this comment

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

저도 이번에 파싱이후의 초기화작업을 위해 DOMContentLoaded를 처음 써봤는데요, 아직 정확하게 이해하지는 못하고 공부중이라서 이번 토론시간에 같이 얘기해보면 좋을 것 같아요 > <

Copy link
Member Author

Choose a reason for hiding this comment

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

저도 이번에 과제를 하면서 새롭게 안 기능이라 한번 활용해보았어요!

DOMContentLoaded 이벤트 리스너를 통해 HTML 문서가 완전히 로드되고 파싱된 후에 코드를 실행해요. 이는 할 일 목록 관련 스크립트가 문서의 나머지 부분이 로드되기를 기다리지 않고 실행될 수 있도록 하려고 한번 활용해보았어요.

style.css Outdated
Comment on lines 18 to 31
@keyframes slideDownFadeIn {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

.animate-slide-down {
animation: slideDownFadeIn 0.2s ease-out forwards;
}
Copy link

Choose a reason for hiding this comment

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

애니메이션까지! 좋아요!

// 애니메이션 클래스 추가
todoItem.classList.add("animate-fade-out");

todoItem.addEventListener("animationend", () => {
Copy link

Choose a reason for hiding this comment

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

animationend를 사용해 애니메이션이 끝날 때 함수들이 실행돼서 좋은거 같아요.

Comment on lines +98 to +99
if (index !== -1) {
toDos[index] = todoObj; // 기존 항목 업데이트
Copy link

@songess songess Mar 16, 2024

Choose a reason for hiding this comment

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

value가 중복되는 것까지 체크하는 것 까지 구현한게 멋져요!
다만 83번 문에서 todoList에 insert하는 과정은 중복체크와 관계없이 항상 실행되어서 페이지를 새로고침하기 전까지는 화면에 중복되는 value가 포함된 div카드가 보이는 것 같아요.

script.js Outdated
Comment on lines 117 to 120
if (todoText !== "") {
addTodoItem(todoText);
const todoObj = { text: todoText, checked: false };
addTodoItem(todoObj);
inputField.value = "";
Copy link

Choose a reason for hiding this comment

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

유효성 검사까지 해서 좋아요!
else문까지 작성해서 빈 문자열이 들어오면 다시 입력하라는 알림창도 있으면 좋을거 같아요.

Copy link
Member Author

Choose a reason for hiding this comment

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

빈 문자열일때는 투두추가 함수 작동이 안되도록 설정했어요!

@@ -99,7 +115,8 @@ document.addEventListener("DOMContentLoaded", function () {
e.preventDefault();
const todoText = inputField.value.trim();
if (todoText !== "") {
addTodoItem(todoText);
const todoObj = { text: todoText, checked: false };
Copy link

Choose a reason for hiding this comment

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

localstorage에 저장되는 todo값을 객체배열형태로 저장해 하나의 키 값만을 활용해 완료/미완료 todo를 관리할 수 있어서 좋은거 같아요!

@@ -188,3 +188,41 @@ h1 {
.todoList li button:hover {
background-color: #3c3a39;
}

/* 모바일 반응형 */
@media (max-width: 768px) {
Copy link

Choose a reason for hiding this comment

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

모바일 반응형까지! 좋아요!

@@ -77,7 +77,7 @@ h1 {
}

#todayDate {
font-size: 10px;
font-size: 0.625rem;
Copy link

Choose a reason for hiding this comment

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

모든 단위를 rem형식 혹은 px단위로 통일했었는데 font-sizerem형식으로 바꿔주신 걸 보고 이렇게 사용할 수도 있구나 배웠어요!

@songess
Copy link

songess commented Mar 16, 2024

반응형 및 애니메이션이 멋져요! 고생하셨습니다.

Copy link

@Rose-my Rose-my left a comment

Choose a reason for hiding this comment

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

처음에 디자인이랑 애니메이션을 보고 진짜 대단하다고 생각했어요 > < 그리고 많이 배울 수 있었던 코드였습니다👍

과제 너무 수고많으셨고 KEY QUESTIONS도 열심히 하셨네요 멋져요😆

<form id="todoForm" class="writeTodoForm">
<img src="./icon/check.svg" class="check_icon" />
<input type="text" class="TodoInput" placeholder="할 일 추가" />
<button class="submitBtn">추가</button>
Copy link

Choose a reason for hiding this comment

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

button 태그를 사용할 때는 type="button"을 명시하면 좋아요! 😁

button의 기본 타입은 "button"이 아닌 "submit"이기 때문인데요! submit의 경우 폼을 제출하는 이벤트를 발생시켜서 따로 설정을 하지 않는 이상 새로고침에 따라 사용자가 입력한 값을 저장하지 않고 날려버린다고 하네요..🥹

그래서 type="button"을 명시해주어 이 버튼은 그자체로 아무런 이벤트가 없음을 알리고 자바스크립트 click이벤트 등과 연결을 하면 돼요! > <

Copy link
Member Author

Choose a reason for hiding this comment

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

엔터를 누를 시 폼 제출이 되려고 form 태그, 그리고 submit타입을 이용한 것 이였는데, 이런 문제가 있을 수 있군요. 감사합니다!

Comment on lines +11 to +12
<div class="wrapper">
<div class="header">✓ To Do</div>
Copy link

Choose a reason for hiding this comment

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

Suggested change
<div class="wrapper">
<div class="header">✓ To Do</div>
<body>
<header>
<h1>To Do</h1>
</header>

Copy link

Choose a reason for hiding this comment

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

div 태그 대신 해당 페이지에서 가장 중요한 제목인만큼 header태그로 감싸는건 어떨까요?

그리고 내부의 내용은 좀더 중요도를 줘서 h1으로 다시 감싸보았어요 ㅎㅎ

Copy link
Member Author

Choose a reason for hiding this comment

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

시멘틱 태그 활용, 그리고 h1태그 이용 습관화 해야겠어요. 감사합니다.

Comment on lines +13 to +15
<div class="todoContainer">
<h1 class="title">오늘 할 일</h1>
<p id="todayDate"></p>
Copy link

Choose a reason for hiding this comment

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

div 태그를 많이 쓰셨더라구요!

KEY QUESTIONS로 알아본 웹 접근성을 위해서 시맨틱 태그를 적극적으로 활용해보시면 어떨까요?
여기서는 <section>태그를 사용해보세요! 이 태그는 독립적으로 배포 및 재사용할 수 있는 독립형 콘텐츠에 사용된답니당!😊

참고할 수 있는 시맨틱 태그 공식문서 달아둘게요 > <

Comment on lines +49 to +52
const completeCheck = document.createElement("img");
completeCheck.src = todoObj.checked
? "./icon/checkComplete.svg"
: "./icon/NotCheck.svg";
Copy link

Choose a reason for hiding this comment

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

삼항연산자로 코드가 훨씬 깔끔해졌네요 ㅎㅎ

Comment on lines +18 to +19
<div class="WriteForm">
<form id="todoForm" class="writeTodoForm">
Copy link

Choose a reason for hiding this comment

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

네이밍이 너무 좋아요 😆 의미를 가지는 이름으로 네이밍해줌으로써 가독성과 추후에는 유지보수성까지 좋아지겠네요 > <

Comment on lines +40 to +46
if (todoObj.checked) {
todoTextContent.style.textDecoration = "line-through";
todoItem.style.color = "#808080";
} else {
todoTextContent.style.textDecoration = "none";
todoItem.style.color = "white";
}
Copy link

Choose a reason for hiding this comment

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

className을 가지고 스타일 변경은 css로 빼서 쓰면 더 가독성이 좋을 것 같아요! ☺️

@@ -8,3 +8,97 @@ const options = {
const dateString = today.toLocaleDateString("ko-KR", options);

document.getElementById("todayDate").innerText = dateString;

document.addEventListener("DOMContentLoaded", function () {
Copy link

Choose a reason for hiding this comment

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

저도 이번에 파싱이후의 초기화작업을 위해 DOMContentLoaded를 처음 써봤는데요, 아직 정확하게 이해하지는 못하고 공부중이라서 이번 토론시간에 같이 얘기해보면 좋을 것 같아요 > <

/* */

/* 할일 삭제 애니메이션 */
@keyframes fadeOutScaleDown {
Copy link

Choose a reason for hiding this comment

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

애니메이션보고 감탄했는데 keyframes로 하신거네요..! 멋져요 👍

// 로컬 스토리지에서 할 일 목록을 불러와서 페이지에 추가
const toDos = JSON.parse(localStorage.getItem("toDos")) || [];
toDos.forEach((todoObj) => {
addTodoItem(todoObj, false); // 이미 저장된 항목을 불러오므로, 여기서는 save 파라미터를 false로 설정
Copy link

Choose a reason for hiding this comment

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

저는 새로 추가된 리스트는 클래스 이름을 별개로 주는 방식으로 기존의 리스트와 구분을 했는데요, 그래서 코드가 복잡했던 것 같아요 🥹
그런데 요렇게 함수의 받아오는 인자를 여러 개 두는 것으로 구분하니까 훨씬 간결하고 좋네요 > <

리팩토링할 때 도움이 될 것 같아요 ㅎㅎ 많이 배웁니당

completeCheck.style.cursor = "pointer";

completeCheck.onclick = function () {
todoObj.checked = !todoObj.checked;
Copy link

Choose a reason for hiding this comment

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

이것도 저는 클래스를 두어 할일과 끝낸일을 구분했는데 todoObj를 객체로 저장해서 체크 여부를 구분하는 아이디어가 너무 좋은 것 같아요 👍

Copy link
Member

@leejin-rho leejin-rho 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 +2 to +8
const today = new Date();
const options = {
month: "long",
day: "numeric",
weekday: "long",
};
const dateString = today.toLocaleDateString("ko-KR", options);
Copy link
Member

Choose a reason for hiding this comment

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

이 방법은 저도 배워갑니다...!!

// 체크 상태 변경
const completeCheck = document.createElement("img");
completeCheck.src = todoObj.checked
? "./icon/checkComplete.svg"
Copy link
Member

Choose a reason for hiding this comment

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

완료한 일에 따라 다른 아이콘으로 표시해준 것은 좋지만, 완료된 일은 위치를 아래쪽으로 변경해주는 등 위치변경이 있었으면 더 좋았을 것 같습니다~!

height: 52px;
border-radius: 10px;
font-size: 0.81rem;

Copy link
Member

Choose a reason for hiding this comment

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

스크린샷 2024-03-17 오전 4 42 11

이렇게 쓸 일은 잘 없겠지만 ㅎㅎ 혹시 모를 경우를 방지하기 위해
word-break : break-all;
추가해주셔도 좋을 것 같습니다~!

Copy link
Member Author

Choose a reason for hiding this comment

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

오.. 이런 오류가 있었군요. 리팩토링하면서 수정해볼게요. 감사합니다~!

deleteButton.textContent = "삭제";
deleteButton.onclick = function () {
// 애니메이션 클래스 추가
todoItem.classList.add("animate-fade-out");
Copy link
Member

Choose a reason for hiding this comment

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

애니메이션 넣어주니까 사용할 때 훨씬 보기 좋아요~! 좋습니다!!

// 폼 제출 이벤트 처리
todoForm.addEventListener("submit", function (e) {
e.preventDefault();
const todoText = inputField.value.trim();
Copy link
Member

Choose a reason for hiding this comment

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

trim()을 사용해 아무것도 입력되지 않을 때 리스트가 추가되지 않도록 꼼꼼하게 신경써주신 것 좋습니다~!

Copy link
Member

Choose a reason for hiding this comment

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

alert()를 함께 띄워줘도 좋을 것 같아요ㅎㅎ

}

// 로컬 스토리지에서 할 일 목록을 불러와서 페이지에 추가
const toDos = JSON.parse(localStorage.getItem("toDos")) || [];
Copy link
Member

Choose a reason for hiding this comment

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

로컬 스토리지까지 정말 짱입니다~!

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