-
Notifications
You must be signed in to change notification settings - Fork 11
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주차] 김철흥 미션 제출합니다. #8
base: main
Are you sure you want to change the base?
Conversation
app.js
Outdated
const taskItem = document.createElement('div'); | ||
taskItem.classList.add('task-item', 'to-do-item'); | ||
|
||
const checkboxContainer = document.createElement('label'); | ||
checkboxContainer.classList.add('checkbox-container'); | ||
|
||
const checkbox = document.createElement('input'); | ||
checkbox.type = 'checkbox'; | ||
checkbox.classList.add('task-checkbox'); | ||
|
||
checkboxContainer.appendChild(checkbox); | ||
|
||
const taskText = document.createElement('span'); | ||
taskText.classList.add('task-text'); | ||
taskText.textContent = taskValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
label 태그를 input과 함께 사용하면 for로 지정된 요소 또는 함께 label로 묶인 요소의 click 이벤트로 label의 click 이벤트를 제어할 수 있습니다. 그래서 checkbox와 같은 경우 텍스트를 클릭해도 checkbox를 클릭할 수 있도록 하기 위해 label 태그를 많이 사용합니다. 만약 그런 의도로 label 태그를 사용하셨다면, span 태그 또한 label의 자식 요소로 추가하거나, label의 for 속성을 사용해서 span의 id와 엮어줘야 할 것 같습니다!
app.js
Outdated
const formatSelectedDate = (selectedDate) => { | ||
const year = selectedDate.getFullYear(); | ||
const month = String(selectedDate.getMonth() + 1).padStart(2, '0'); // 월은 0부터 시작하므로 +1 | ||
const day = String(selectedDate.getDate()).padStart(2, '0'); | ||
|
||
const weekdays = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']; | ||
const weekday = weekdays[selectedDate.getDay()]; | ||
|
||
return `${year}.${month}.${day} (${weekday})`; | ||
}; | ||
|
||
// 초기 날짜 설정 (현재 날짜) | ||
const today = new Date(); | ||
|
||
document.querySelector('.today-date').textContent = formatSelectedDate(today); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
날짜를 포매팅한 후 항상 document.querySelector('.today-date').textContent
을 포매팅된 날짜로 설정한다면, 그 로직을 formatSelectedDate
함수 내부에 작성해도 될 것 같습니다. 그러면 handleDateSelect
내부에서도 document.querySelector('.today-date').textContent = formatSelectedDate(dateObject);
라고 작성하는 대신 formatSelectedDate(dateObject)
만 호출하면 되니까요!
app.js
Outdated
datePicker.addEventListener('change', () => { | ||
handleDateSelect(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
함수에 별도의 인자를 넘겨주지 않는 경우에는 아래와 같이 두 번째 인자로 함수만 넘겨줄 수도 있습니다!
datePicker.addEventListener('change', handleDateSelect)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
리액트에서 기능에 따라 컴포넌트를 분리하듯 바닐라에서도 역할에 따라 함수를 분리하고 파일을 분리하면 가독성 측면으로도, 유지보수 측면으로도 더 개선된 코드를 작성할 수 있을 것 같습니다. 코멘트를 남기는 중에도 계속해서 리팩토링이 이루어지고 있는데요 ㅎㅎ 꾸준히 과제를 디벨롭하는 모습 멋있습니다. . . 고생 많으셨어요!
추가로 개별 코멘트로 과도한 알림을 보낸 점 사과드립니다. . .
헉. 코멘트를 보낸다는 걸 request changes를 눌러버렸어요 request changes는 무시해 주셔도 괜찮습니다!!! 💦💦💦
styles.css
Outdated
|
||
background: transparent; | ||
|
||
overflow-x: scroll; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
task-item
과 아래 task-text
에 설정한 overflow-x
때문에 화면에 스크롤바가 나타나고 있습니닷. 줄바꿈이 되고 있는 것 같은데 가로 스크롤을 설정하신 이유가 있으실까요?
image.png
const addTaskForm = document.getElementById('add-task-form'); | ||
const addTaskInput = document.querySelector('.add-task-input'); | ||
const toDoList = document.getElementById('to-do-list'); | ||
const doneList = document.getElementById('done-list'); | ||
const noTasksToDo = document.getElementById('no-tasks-to-do'); | ||
const noTasksDone = document.getElementById('no-tasks-done'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저는 리액트에서 전체 코드 순서를 변수 -> 함수 -> useEffect -> 렌더링
과 같이 작성해 왔는데요, 바닐라에서도 마찬가지로 변수 -> 함수
순서로 작성하게 되더라고요. 그런 점에서 변수 -> 함수 -> 변수 -> 함수
같은 흐름은 관심사를 분리할 때라는 좋은 신호인 것 같습니다.
이 위로는 date 관련 코드이니 date.js에, 아래는 task와 관련된 코드이니 task.js로 분리해서, app.js에서는 그 함수들을 import하여 document에 이벤트 리스너를 등록하는 형식은 어떨까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저도 코드를 작성하면서 모듈화의 필요성을 느꼈는데, 이 부분 반영해서 리팩토링해보겠습니다 :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋은 코드라고 생각합니다! 특히 UI 같은 경우 저도 굉장히 난항을 겪었는데, 피그마로 디자인 후 svg 파일 추가 등 해서 진행하신 게 너무 좋았습니다! 저도 다음 번에 기회가 되면 해당 방식으로 시도해보고자 합니다.
text: taskValue, | ||
completed: false, | ||
date: selectedDateStr, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이렇게 task 객체 unique ID로 관리하게 되면 장점이 많다고 생각합니다. 다만 Date.now()로 값을 할당하게 되면 date와 겹치는 부분이 있다고 생각해 hash 등을 사용해 암호화하는 방식은 어떨까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
현재 시간을 고유한 ID로 사용한 후에, 날짜 선택 기능을 추가하면서 id의 값이 중복된 의미의 필드가 된 것 같네요!
고유 ID로 사용할 수 있는 더 좋은 방식을 채택해서 리팩토링해보겠습니다 :)
|
||
const filteredTasks = tasks.filter((task) => task.date === selectedDateStr); | ||
filteredTasks.forEach((task) => renderTask(task)); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 과제에서 그럴 일은 없겠지만, date 값을 객체 속성으로 두면 O(N)이 걸릴 것 같습니다. {id, date, text, completed} -> date: {id, text, completed} 이렇게 2차원으로 만드시는 건 어떠실까요? (보통 N >> k 이기 때문에0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
위에서 date 필드와 id 필드를 리팩토링할 소요가 있었는데, date 필드 안에 task 객체 배열을 두는 방식으로 리팩토링하면 코드가 더 깔끔해질 것 같네요!
좋은 피드백 감사합니다 :)
🔗 배포 링크
To Do List
🫥 느낀 점
이번 1주차 미션을 진행하면서 느낀 점(어려움)은 크게 2가지였던 것 같습니다.
여전히 public에 있는 정적 파일이 로드되지 않는 에러가 발생하는데, 이 부분도 해결하면서 정적 프로젝트의 배포까지의 과정에 대한 이해를 할 수 있을 것 같습니다.
이번 미션을 진행하면서 피그마로 직접 디자인을 하면서 미션을 수행했는데 이 부분도 굉장히 재밌었습니다!
Key Question
1. DOM이란?
DOM(Document Object Model, 문서 객체 모델)은 웹 문서(HTML, XML)를 구조화하여 프로그램이 문서의 구조, 스타일, 내용 등을 동적으로 변경할 수 있도록 하는 인터페이스
웹 브라우저가 HTML 문서를 로드할 때, 이를 계층적인 트리 구조로 변환
➡️ 이 트리가 DOM!
2. 이벤트 흐름 제어(버블링 & 캡처링)이 무엇인가요?
웹에서 이벤트가 발생하면 브라우저는 캡처링 → 타겟 → 버블링 순서로 이벤트 전파를 진행함
즉, 부모 → 자식 방향으로 이벤트가 전달됨
즉, 자식 → 부모 방향으로 이벤트가 전달됨
3. 스코프(Scope)와 클로저(Closure)
스코프는 변수에 접근할 수 있는 범위를 의미
a. 전역 스코프(Global Scope)
b-1. 지역 스코프(Local Scope)
b-2. 블록 스코프(Block Scope)와 함수 스코프(Function Scope)
클로저는 외부 함수의 변수를 내부 함수에서 참조할 수 있는 개념
즉, 외부 함수가 실행된 후에도 내부 함수가 외부 함수의 변수에 접근할 수 있는 현상을 클로저라고 함
ex.)
위 코드에서 innerFunction은 outerFunction 내부에서 선언되었지만, outerVar를 기억하고 유지함
➡️함수가 생성될 당시의 외부 변수 환경을 기억하는 것이 클로저의 핵심!