[1주차] 박유민 과제 제출합니다.#3
Conversation
Tutankhannun
left a comment
There was a problem hiding this comment.
코드 정말 잘봤습니다. 디자인 토큰 관리부터 유틸 함수 분리, isComposing 체크, 예외처리... 등등 너무 잘해주셔서 힘들게 코드 리뷰 달았습니다. 이번 주차 과제하시느라 수고 많으셨습니다~ 앞으로 과제도 잘부탁드립니다!!
| @@ -0,0 +1,250 @@ | |||
| // 상태 | |||
| const today = new Date() | |||
There was a problem hiding this comment.
이미 보셨을지는 모르지만 최근 Date를 대체하여 떠오르는 Temporal API에 대해서도 아시면 유용할 것 같습니다!
| const addTodoItem = (text) => { | ||
| const key = dateToKey(selectedDate) | ||
| if (!store[key]) store[key] = [] | ||
| store[key].push({ id: Date.now(), text: text.trim(), done: false }) |
There was a problem hiding this comment.
투두를 저장할 때, Date.now()를 id로 사용하는데 간편하고 좋지만 확장성을 고려하였을 때는 uuid를 활용하는 것이 유지보수 측면에서 더 좋다고 고려됩니다! (사실 이번 과제 정도에서는 이 방식도 직관적이고 좋지만 이후 볼륨이 커졌을 때 uuid 방식을 고려하시면 좋을 것 같아요~)
| padding: 6px 2px; | ||
| font-size: var(--text-sm); | ||
| } | ||
| #calendarSection { |
There was a problem hiding this comment.
#calendarSection 스타일이 중복 선언된 것 같습니다. 하나로 합쳐도 될 것 같아요.
| { | ||
| "semi": false, | ||
| "singleQuote": true, | ||
| "trailingComma": "es5", | ||
| "bracketSpacing": true, | ||
| "arrowParens": "always", | ||
| "useTabs": false, | ||
| "tabWidth": 2, | ||
| "printWidth": 80, | ||
| "endOfLine": "lf" | ||
| } |
There was a problem hiding this comment.
Prettier 를 이용해 개발 환경을 관리하셔서 코드가 전체적으로 깔끔하게 느껴졌습니다!
특히 "semi": false 설정 덕분에 JS 코드가 줄 끝이 시각적으로 깔끔하게 정리되어 있어 가독성이 좋았습니다.
개인적으로는 "singleQuote": true 설정 덕분에 HTML에서는 " " 를, JS에서는 ' ' 를 사용하여 파일별로 시각적으로 구분이 되어 코드 읽기가 훨씬 편했습니다!
| </div> | ||
| <script src="script.js"></script> | ||
| </body> | ||
| </html> |
There was a problem hiding this comment.
시맨틱 태그를 꼼꼼하게 달아주셔서 코드를 읽는 것만으로도 발표 때 보여주셨던 그림이 상상됩니다!

배포 링크
🔗Vanilla Todo
느낀 점 및 배운 점
React와 Next.js 기반 프로젝트를 진행하다가 오랜만에 HTML, CSS, JavaScript 중심으로 코딩을 하려니 생각보다 어렵게 느껴졌습니다. 무엇보다 TailwindCSS의 편리함이 정말 많이 그리웠습니다.. 최대한 간결하게 작성하려고 노력했지만, 기능이 하나씩 추가될수록 코드가 길어지면서 가독성이 조금 떨어진 점은 아쉽게 느껴졌습니다.
이번 과제를 진행하면서 기본기의 중요성을 다시 한 번 느꼈고, 특히 DOM에 대해서도 제가 제대로 이해하지 못하고 있던 부분이 많았다는 것을 깨달았습니다. 평소에는 프레임워크가 어느 정도 추상화해주는 부분에 익숙해져 있었는데, 이번에는 요소를 직접 만들고 붙이고 이벤트를 연결하면서 브라우저가 실제로 어떻게 동작하는지 조금 더 체감할 수 있었습니다.
이번 과제에서 제가 중점적으로 생각한 부분은 다음과 같습니다.
디자인 토큰 분리
#000000처럼 직접 하드코딩해서 작성해도 구현은 가능하지만, 모든 값을 그렇게 넣어버리면 유지보수 측면에서 조금 아쉽다고 생각했습니다. 그래서 이번 과제에서는 컬러뿐만 아니라 border radius, shadow, font, font size 같은 값들도 최대한:root에서 분리해서 관리하려고 했습니다. 작은 과제여도 이런 식으로 구조를 잡아두면 나중에 수정하거나 확장할 때 훨씬 편하다고 생각했습니다.눈에 피로하지 않은 색상 사용
투두리스트는 사용자가 자주 보게 되는 화면이라고 생각해서, 색상은 과하거나 피로하지 않게 잡는 것을 목표로 했습니다. 그래서 메인 컬러는 주로 흰색과 채도가 낮은 하늘빛 계열로 구성했습니다. 완료/삭제처럼 의미가 분명한 버튼만 초록색, 빨간색으로 구분해서 포인트를 주었고, Pretendard 폰트의 깔끔한 느낌도 전체적인 분위기와 잘 어울린다고 생각했습니다.
한 눈에 들어오도록 구성
저는 하루의 할 일만 보는 것보다 전체 달력과 함께 일정을 확인하는 방식을 더 선호해서, 이번 과제도 그런 흐름으로 구현했습니다. 사용자가 날짜를 선택하면서 바로 할 일을 확인할 수 있도록 달력과 리스트를 함께 배치했고, 오늘 진행도와 이번 달 진행도를 같이 보여주어 현재 상태를 한눈에 파악할 수 있도록 구성했습니다.
구조 설계

조금 적나라하긴 하지만.. 작업하면서 정리했던 스케치도 함께 첨부합니다! 저는 러프하게라도 먼저 구조를 잡고 개발하는 것이 습관인데, 이번에도 이 방식이 꽤 도움이 됐습니다. HTML 구조를 나누거나 CSS 레이아웃을 설계할 때 훨씬 덜 헤맸고, 복잡한 페이지일수록 이렇게 큰 틀을 먼저 잡아두는 게 중요하다고 다시 느꼈습니다.
Review Questions
1. DOM은 무엇인가요?
DOM
이번 과제에서 사용한 DOM API
document.getElementById— id 값을 기준으로 특정 요소를 선택할 때 사용document.querySelectorAll— CSS 선택자를 기준으로 여러 요소를 한 번에 선택할 때 사용createElement/appendChild— 새로운 요소를 동적으로 생성하고, 원하는 위치에 추가할 때 사용textContent— 요소 내부의 텍스트 내용을 변경할 때 사용classList— 클래스 추가/제거를 통해 요소의 상태나 스타일을 변경할 때 사용element.style— 진행률 바의 width처럼 필요한 스타일을 인라인으로 직접 변경할 때 사용2. 이벤트 흐름 제어(버블링 & 캡처링)이 무엇인가요?
브라우저에서 이벤트가 발생하면, 해당 요소에서만 끝나는 것이 아니라 문서 구조를 따라 전파되는데, 이벤트 전파는 아래와 같은 3단계로 이루어짐

캡처링(Capturing)
document에서 시작해, 실제 이벤트가 발생한 요소까지 내려오는 단계addEventListener의 세 번째 인자로true를 전달하면 캡처링 단계에서 이벤트를 감지할 수 있음타깃(Target)
버블링(Bubbling)
addEventListener는 기본적으로 버블링 단계에서 동작event.stopPropagation()을 사용하면 상위 요소로의 이벤트 전파를 막을 수 있음3. 클로저와 스코프가 무엇인가요?
date,otherMonth값을 기억하고, 클릭 시 올바른 날짜 정보를 참조할 수 있도록 하는 데 활용했음var: 함수 스코프를 가짐let,const: 블록 스코프를 가짐