Skip to content

Conversation

@Jy000n
Copy link

@Jy000n Jy000n commented Sep 13, 2025

결과 화면

image

느낀점 및 배운점

  • 리액트를 사용하지 않고 순수 자바스크립트로만 활용하여 코드를 짜려니 생각보다 쉽지 않아 DOM 조작 방법 등의 개념들을 더 찾아 보았고 이 과정에서 여러 메소드와 기능들을 익힐 수 있었다
  • 디자인 부분을 보기와는 다르게 생각보다 고민을 했었으나.. 0의 상태로 무언가를 짜려니 어렵게 느껴졌는데 그러다보니 디자인이 좀 많이 심플해져서 이제부터라도 여러 디자인들을 눈에 익혀 놓아야겠다
  • Vercel 배포에서 생각보다 막혔다. 하도 막혀서 다음에는 에러 없이 잘 할 수 있을 것 같다.

Review Questions

DOM (Document Object Model)

  • 문서 객체 모델
  • JS가 HTML/XML 문서를 웹 브라우저에서 조작할 수 있도록 트리 구조로 표현한 객체 모델
  • DOM을 통해
    • 콘텐츠 변경 : 텍스트, 이미지, 링크 등 수정
    • 구조 변경 : 요소 추가, 삭제, 이동
    • 스타일 변경 : CSS 조작
    • 이벤트 처리 : 클릭, 입력, 마우스 이동 등

이벤트 흐름 제어 (버블링 <-> 캡쳐링)

  • 이벤트는 DOM 트리를 따라 전파됨
  • 버블링 (Bubbling)
    addEventListener(event, handler)
    • 이벤트가 발생한 요소에서 DOM 트리의 최상위 요소까지 부모 요소를 따라 이벤트 핸들러가 순차적으로 진행되는 방식
    • 이벤트 타겟 -> 최상위 요소까지 올라감
  • 캡쳐링 (Capturing)
    addEventListener(event, handler, {capture:true})
    addEventListener(event, handler, true)
    • 이벤트가 발생했을 때 DOM 트리의 최상위 요소에서부터 시작하여 아래로 내려가면서 이벤트가 발생한 요소까지 이벤트 핸들러가 순차적으로 실행되는 방식
    • 최상위 요소 -> 이벤트 타겟까지 내려감
  • 이벤트 전파 순서 : 캡처링 -> 타겟 -> 버블링
  • 이벤트 제어 가능
    event.stopPropagation() // 더 이상 전파되지 않음
    event.preventDefault() // 브라우저 기본 동작 막기

클로저와 스코프

  • 클로저 (Closure)
    • 외부 함수의 변수(프리변수)와 그 변수가 선언된 스코프(렉시컬 스코프)를 함께 기억하는 내부 함수의 집합
    • 외부 함수가 종료되어 그 스코프가 사라져도, 내부 함수는 해당 스코프의 변수들을 계속 참조 가능
    • 활용) private 변수 구현, 콜백, 이벤트 핸들러, 모듈 패턴
  • 스코프 (Scope)
    • 변수/함수가 접근 가능한 범위
    • 전역 스코프 : 어디서든 접근 가능
    • 지역 스코프 : 함수 내부, 블록 내부에서만 접근 가능

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

+ 깃 명령 관련해서 문제 생겨서 다시 하다가 레포지토리 다 날려먹은 관계로 커밋 기록이 거의 없습니다.. :(

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.

과제하시느라 고생 많으셨습니다!! 커밋 기록이 다 날아갔다니 정말 아쉽네요.. 🥲
앞으로 과제를 Vercel로 배포하신다면, 배포 과정에서 다양한 오류를 접하실 수 있을 텐데요.
코드 품질을 사전에 관리하기 위해 .husky를 활용해 커밋 단계에서 린트나 테스트를 자동으로 실행해 두는 것도 도움이 될 것 같습니다! 🙌

<!-- 입력 목록 -->
<div class="inputContainer">
<input placeholder="할 일을 입력해주세요" id="todoInput" required />
<span class="appendTodo">+</span>
Copy link
Member

Choose a reason for hiding this comment

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

button 태그를 사용해도 좋을 거 같아용

Comment on lines +95 to +99
todoInput.addEventListener("keydown", (event) => {
if (event.key === "Enter") {
appendTodo.click();
}
});
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 오후 2 20 06

승선님 리뷰에도 남겨놨었는데, 한글 입력 후 엔터로 등록을 할 경우 마지막 글자가 두 번 입력되는 현상이 있습니다!

이 문제는 IME 조합형 입력 중 keydown 이벤트가 조합이 완료되기 전에 먼저 실행되면서 발생하는 이슈인데요.

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

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

Comment on lines +110 to +116
div.innerHTML = `
<input type="checkbox" class="checkboxButton" id="checkbox-${index}" ${
todo.checked ? "checked" : ""
} />
<span class="todoContent">${todo.text}</span>
<button class="deleteButton">x</button>
`;
Copy link
Member

Choose a reason for hiding this comment

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

현재 renderTodos 함수에서 innerHTML을 통해 사용자 입력값(todo.text)을 그대로 삽입하고 있는데요,
innerHTML은 입력값을 HTML로 파싱하기 때문에 악성 스크립트가 실행될 수 있는 XSS 보안 취약점을 초래할 수 있습니다!
따라서 createElement, appendChild, textContent를 활용해 해당 코드를 재구현하는 방법도 고려해 보시면 좋겠습니다 🙂

참고자료: https://greathyeon.tistory.com/49

`;

const checkbox = div.querySelector(`#checkbox-${index}`);
const todoContent = div.querySelector(".todoContent");
Copy link
Member

Choose a reason for hiding this comment

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

const todoContent = div.querySelector(".todoContent");

현재 코드에서 선언만 되고 실제로는 사용되지 않고 있는데요, 불필요한 코드는 제거해 주시면 더 좋을 거 같습니다!

@@ -0,0 +1,161 @@
* {
text-align: center;
font-family: Pretendard;
Copy link
Member

Choose a reason for hiding this comment

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

Pretendard는 기본 제공 폰트가 아니기 때문에 CDN, @import, @font-face 등의 방식으로 폰트를 불러와야 실제로 적용됩니다!
다음 과제에서 적용해보시면 좋겠네요 :)

Copy link
Member

Choose a reason for hiding this comment

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

전반적으로 rem단위를 사용하신 것이 인상깊네요!

// 버튼 클릭 시 날짜 변경
prevButton.addEventListener("click", () => {
changeDate(-1);
console.log("날짜:", currentDate.value);
Copy link
Member

Choose a reason for hiding this comment

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

console.log는 개발 과정에서 디버깅 용도로 사용되지만, 실제 배포 시에는 불필요하므로 제거해 주시는 것이 좋습니다!
앞으로 프로젝트를 진행하실 때도 참고해 주시면 좋겠습니다 :)

Comment on lines +12 to +14
<button class="dateButton" id="prevButton"><</button>
<input type="date" id="currentDate" />
<button class="dateButton" id="nextButton">></button>
Copy link
Member

Choose a reason for hiding this comment

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

현재 렌더링에는 문제가 없지만, 부등호는 잠재적으로 태그 시작/종료 기호이므로, 상황에 따라 오동작할 수 있습니다!
따라서 안전하게 표시하려면 < → &lt;, > → &gt;와 같이 HTML 엔티티로 대체해줘도 좋을 거 같아용


const defaultDate = `${yyyy}-${mm}-${dd}`;
currentDate.value = defaultDate;
localStorage.setItem("lastSelectedDate", defaultDate);
Copy link
Member

Choose a reason for hiding this comment

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

페이지 새로고침 시 마지막으로 선택했던 날짜가 유지되도록 구현해 주신 점이 인상 깊었습니다!
다만, 페이지를 닫고 다시 열었을 때는 오늘 날짜가 기본값으로 보이는 편이 더 자연스러울 수도 있을 것 같습니다. 이 경우 localStorage 대신 sessionStorage를 활용해 보시는 것도 좋겠습니다!!

<main>
<!-- 입력 목록 -->
<div class="inputContainer">
<input placeholder="할 일을 입력해주세요" id="todoInput" required />
Copy link
Member

Choose a reason for hiding this comment

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

required 속성을 넣어주신 점이 인상깊네용 😲

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.

2 participants