Skip to content

Conversation

@baekseungsun
Copy link

@baekseungsun baekseungsun commented Sep 12, 2025

배포 링크: https://vanilla-todo-22nd-ten.vercel.app/

-DOM은 무엇인가요?
DOM은 Document Object Model의 약자로 문서의 구조를 표현하는 트리 구조의 모델입니다. JS를 통하여 웹 페이지를 동적으로 조작할 수 있도록 합니다

-이벤트 흐름 제어(버블링, 캡쳐링)란 무엇인가요?
웹 DOM 트리에 이벤트가 전파되는 방식입니다. 버블링은 트리의 하위 (child)부터 상위 (parents)로 전파되는 방식이고 캡쳐링은 그 반대로 상위에서 하위로 전파되는 방식입니다.

-클로저와 스코프가 무엇인가요?
스코프란 코드에서 생성한 변수의 영향권입니다. local, global이 있으며 local은 블록 내에서만 유효한 범위, global은 프로그램 전체에서 유효한 범위입니다. 클로저란 스코프를 기억하고 스코프 밖에서도 변수를 사용 가능하게 합니다.

과제를 진행하며 느낀/배운 점:

  1. css를 코딩하는 것이 생각보다 어렵다는 것을 느꼈습니다. 요소가 많아질수록 고려해야 하는 부분이 늘어났고, margin, padding 등의 설정을 잘못하면 어디서 에러가 났는지 알아내고 디버깅하는 것이 까다로웠습니다. JS를 코딩하는 것보다 css에서 시간을 더 많이 쓴 것 같습니다.
  2. Storage를 사용하여 저장한 것을 다시 불러오는 과정이 까다로웠습니다. innerHTML로 불러올 시 버튼 등의 function을 불러올 수 없었고 이를 해결하기 위해선 event delegation이라는 방식을 사용해야 했습니다. 이 페이지에서 도움을 받았습니다.
  3. 과제 필수 조건은 아니었지만 event pin (상단 고정)을 구현하는 데에 시간을 많이 투자했습니다. 상단 고정까지는 수월했으나 고정을 풀고 원위치로 돌리기 위해선 이벤트의 원위치를 기억하고 불러올 방법이 필요했고, 스택, 큐, ArrayList등이 아닌 html의 ul 태그로 구현한 데이터 구조를 다뤄본 경험이 없어 Array.from()의 사용법에 익숙하지 않았습니다. 여기서 답을 찾았습니다.

Copy link
Member

@chaeyoungwon chaeyoungwon left a comment

Choose a reason for hiding this comment

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

과제하시느라 수고 많으셨습니다! 직접 문서를 찾아보며 이슈를 해결해 나간 점이 인상적이네요 🥹
또한 pin 기능까지 추가로 개발해 주신 점도 좋았습니다 👏

지금 vercel 배포 링크가 private 링크로 되어있는 것 같은데, public 링크로 변경 부탁드립니다!!
프로젝트 settings에서 private->public으로 변경해주시면 접근 권한없이 확인 가능해용

Comment on lines +160 to +164
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
addToList();
}
});
Copy link
Member

Choose a reason for hiding this comment

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

스크린샷 2025-09-14 오전 4 30 55

현재는 한글 입력 후 Enter를 누를 경우, 마지막 글자가 두 번 입력되는 현상이 있습니다!
이 문제는 IME 조합형 입력 중 keydown 이벤트가 조합이 완료되기 전에 먼저 실행되면서 발생하는 이슈인데요.

아래 참고 자료들에서 안내하는 것처럼 KeyboardEvent의 isComposing 속성을 활용하면
이런 상황을 방지할 수 있으니 참고해보시면 좋을 것 같아요 👍

https://developer.mozilla.org/ko/docs/Web/API/KeyboardEvent/isComposing
https://velog.io/@goldfrosch/is-composing

Comment on lines +27 to +29
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && menuTab.classList.contains('active')) closeDrawer();
});
Copy link
Member

Choose a reason for hiding this comment

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

esc 키로 메뉴를 닫는 UX까지 챙겨주신 부분이 인상 깊네요!


//calendar manipulation
const menuContent = document.getElementById('menuContent');
datePickerEl = document.createElement('input');
Copy link
Member

Choose a reason for hiding this comment

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

datePickerEl이 현재 암묵적으로 전역 변수로 선언되어 있는데요.
지금은 코드가 짧아서 큰 문제가 없어 보이지만, 전역 변수는 예기치 않은 참조나 값 변경의 위험이 있어 유지보수 측면에서는 지양되는 방식입니다!

따라서 const 등을 사용해 명시적으로 선언해주시면 더 안전할 것 같아요 😊
const datePickerEl = document.createElement('input');

Comment on lines +208 to +216
.clearAll{
color: #0f172a;
font-size: 20px;
border-radius: 20px;
width: 120px;
margin-top: 5px;
margin-left: 10px;
background: #e2e8f0;
}
Copy link
Member

Choose a reason for hiding this comment

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

add 버튼처럼 다른 버튼 요소들에도 cursor: pointer; 속성을 적용해주면 더 좋을 것 같아요!

Copy link

Choose a reason for hiding this comment

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

저도 동의하는 부분입니다! 덧붙여서 구체적으로 말씀드리자면, 날짜 앞뒤 버튼, last week, next week, 날짜 선택 부분에서 달력 아이콘, Clear all, done, pin, delete 버튼 정도일 것 같습니다

Comment on lines +82 to +94
.nWeek {
width: 120px;
height: 30px;
font-size: 16px;
border-radius: 10px;
}

.lWeek {
width: 120px;
height: 30px;
font-size: 16px;
border-radius: 10px;
}
Copy link
Member

Choose a reason for hiding this comment

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

동일한 스타일은 이렇게 묶어주거나, week 버튼 클래스로 통일해도 좋을 거 같습니다!

.nWeek,
.lWeek {
  width: 120px;
  height: 30px;
  font-size: 16px;
  border-radius: 10px;
}

Comment on lines +71 to +79
function saveList(date) {
sessionStorage.setItem(storageKey(date), event.innerHTML);
}

//loads the events for a date
function loadList(date) {
event.innerHTML = sessionStorage.getItem(storageKey(date) || '');
getNumEvent();
}
Copy link
Member

Choose a reason for hiding this comment

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

sessionStorage를 사용하셨는데, 의도적으로 세션 단위에서만 데이터를 유지하려고 하신 건지 궁금합니다!-!

localStorage를 사용하면 브라우저를 껐다 켜도 데이터가 남아서, todoList 특성상 더 적합할 수도 있겠다는 생각도 들었습니다!

Comment on lines +50 to +62
nWeek.addEventListener('click', e => {
saveList(current);
current.setDate(current.getDate() + 7);
render();
loadList(current);
})

lWeek.addEventListener('click', e => {
saveList(current);
current.setDate(current.getDate() - 7);
render();
loadList(current);
})
Copy link
Member

Choose a reason for hiding this comment

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

반복되는 코드들은 유틸 함수로 분리해도 가독성이 좋아질 거 같아요 🙂
예를 들어 -7, +7 같은 숫자만 인자로 넘겨줘도 동일하게 동작하도록 만들 수 있을 것 같습니다!

Comment on lines +4 to +14
const menuTab = document.getElementById('menuTab');
const openBtn = document.querySelector('.menu');
const closeBtn = document.getElementById('closeMenu');

//open and close menu drawer
const openDrawer = () => {
menuTab.classList.add('active');
};
const closeDrawer = () => {
menuTab.classList.remove('active');
};
Copy link
Member

Choose a reason for hiding this comment

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

코드에서 = 앞뒤 띄어쓰기가 일정하지 않은 부분이 있는데,
앞으로는 Prettier 같은 포매터를 적용해서 코드 스타일을 자동으로 맞춰주면 더 깔끔하게 관리할 수 있을 것 같습니다!!

Comment on lines +96 to +104
.menuDatePicker{
margin-top: 80px;
margin-left: 88px;
font-size: 16px;
width: 120px;
height: 30px;
border-radius: 10px;

}
Copy link
Member

Choose a reason for hiding this comment

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

스크린샷 2025-09-14 오전 5 29 40

menuDatePicker에서 텍스트가 조금 잘려보이는 거 같은데 (일이 안보임), 넓이를 조금 더 키워줬어도 좋을 거 같아용

<button class="clearAll">Clear all</button>
<div class="numEvent">To-do: 0</div>
</div>
<ul class="event">
Copy link
Member

Choose a reason for hiding this comment

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

event는 전역 객체와 혼동될 수 있으니, 클래스명은 가급적 의미를 드러내면서도 예약어와 겹치지 않도록 네이밍 해주면 더 안전할 것 같습니다!

@baekseungsun
Copy link
Author

과제하시느라 수고 많으셨습니다! 직접 문서를 찾아보며 이슈를 해결해 나간 점이 인상적이네요 🥹 또한 pin 기능까지 추가로 개발해 주신 점도 좋았습니다 👏

지금 vercel 배포 링크가 private 링크로 되어있는 것 같은데, public 링크로 변경 부탁드립니다!! 프로젝트 settings에서 private->public으로 변경해주시면 접근 권한없이 확인 가능해용

배포링크 수정 했습니다! 알려주셔서 감사합니다, vercel 처음 사용해봐서 실수했네요

Copy link

@Jy000n Jy000n left a comment

Choose a reason for hiding this comment

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

작성하신 코드와 사이트 잘 봤습니다!!
개인적으로 구성하신 색상들이 제 취향이어서 좋았습니다아😄 그리고 Clear all 버튼, Pin 기능을 추가하신 것이 인상깊었습니다!!

<meta charset="UTF-8">
<title>vanilla-todo 백승선</title>
<link rel="stylesheet" href="style.css">
<script defer src="todolist.js"></script>
Copy link

Choose a reason for hiding this comment

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

defer 속성에 대해 새롭게 알게 되었습니다! 저도 다음에 사용해봐야겠습니다:)

flex-direction: column;
gap: 6px;
height: 425px;
width: 600px;
Copy link

Choose a reason for hiding this comment

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

.list 에서 width를 600px로 고정해서 그런지, 화면 너비를 줄이면 레이아웃이 잘리는 현상이 발생합니다! %나 rem 단위를 사용하면 조금 더 유동적으로 처리할 수 있을 것 같습니다

Comment on lines +208 to +216
.clearAll{
color: #0f172a;
font-size: 20px;
border-radius: 20px;
width: 120px;
margin-top: 5px;
margin-left: 10px;
background: #e2e8f0;
}
Copy link

Choose a reason for hiding this comment

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

저도 동의하는 부분입니다! 덧붙여서 구체적으로 말씀드리자면, 날짜 앞뒤 버튼, last week, next week, 날짜 선택 부분에서 달력 아이콘, Clear all, done, pin, delete 버튼 정도일 것 같습니다

Comment on lines +64 to +66
const dateKey = (d) => new Date(d).toLocaleDateString('en-CA');
// "YYYY-MM-DD" in local time
const storageKey = (d) => `${dateKey(d)}`;
Copy link

Choose a reason for hiding this comment

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

찾아보니, .toLocaleDateString('en-CA') 자체가 "yyyy-mm-dd" 형식으로 문자열을 반환하는 것 같아서 굳이 템플릿 리터럴(${})로 감싸주지 않아도 될 것 같습니다. 성능에는 영향 없는 것 같지만 참고하셔도 좋을 것 같습니다:)

Comment on lines +110 to +113
const input = document.querySelector('.input');
const add = document.querySelector('.register');
const event = document.querySelector('.event');
const clearAll = document.querySelector('.clearAll');
Copy link

Choose a reason for hiding this comment

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

DOM 요소는 가독성과 중복 방지를 위해 한 번에 상단에서 정의하는 게 좋을 것 같습니더 !!

Comment on lines +214 to +216
function getNumEvent() {
numEvent.textContent = "To-do: " + event.children.length;
}
Copy link

Choose a reason for hiding this comment

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

Todo 개수를 불러올 때, todo 리스트를 체크해서 done 상태로 바꿔도 Todo 개수는 줄어들지 않던데 의도하신걸까욥

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.

3 participants