Skip to content

[1주차] 남기림 과제 제출합니다.#5

Open
GirimNam wants to merge 8 commits intoCEOS-Developers:masterfrom
GirimNam:main
Open

[1주차] 남기림 과제 제출합니다.#5
GirimNam wants to merge 8 commits intoCEOS-Developers:masterfrom
GirimNam:main

Conversation

@GirimNam
Copy link
Copy Markdown

배운 점 및 느낀 점

  • 기본적인 HTML, CSS, JS를 배운 후 바로 리액트로 프로젝트를 진행해왔어서, 단순하게 Vanilla JS만으로 프로젝트를 진행하는 것이 마냥 쉽지만은 않았습니다. 리액트를 사용하면서 시맨틱 태그를 크게 신경쓰지 않았던거 같은데 그 중요성도 알게 되었습니다.
  • 개인적으로 날짜별로 페이지를 넘길 수 있도록 하는 부분에서 시간을 많이 할애했습니다. 처음에는 단순하게 캘린더를 가져와서 구현해야하나 생각했지만, 구현하기 쉽지 않았는데, 단순하게 하루씩 이동하면 된다는 생각에 마지막에는 좀 수월했던 것 같습니다.
  • 개별적으로 넣으면 좋을 기능이 뭐가 있을까 생각하다 일주일의 7일을 각각 무지개색 배경으로 표현하여 배경색만으로 요일을 알 수 있게 해보았습니다.
  • localstorage를 사용해서 날짜를 이동해도 정보가 계속 남아있도록 했습니다. 처음에 어떤식으로 정보를 저장해야하는지 조금 혼란스러웠습니다.
  • 무엇보다 로컬에서 먼저 파일을 만든 후 깃허브에 올리는 식으로 진행하다 깃 명령어가 제대로 안 작동하고, 그래서인지 deploy도 안되는 일이 있었습니다. 다음부터는 fork해서 레포지토리를 먼저 만든 후 진행해야겠다고 다짐했습니다..

배포링크

https://vanilla-todo-23rd-ochre.vercel.app/

Review Questions

  1. DOM은 무엇인가요?
    DOM이란 문서객체모델로, 웹 페이지를 스크립트 또는 프로그래밍 언어와 연결하는 역할을 합니다. 웹 브라우저는 HTML 문서를 해석하는 과정에서 문서객체모델을 생성합니다. 이는 HTML과 같은 문서 구조를 메모리에 표현함으로써 이루어집니다. DOM은 문서를 논리적 트리로 표현하는데, 트리의 각 가지는 노드에서 끝나고, 각 노드는 객체를 포함합니다. DOM 메서드를 사용하면 프로그래밍 방식으로 트리에 접근할 수 있습니다. 이를 통해 문서의 구조, 스타일, 또는 내용을 변경할 수 있습니다. 노드에는 이벤트 핸들러도 첨부될 수 있는데, 이벤트가 트리거되면 이벤트 핸들러가 실행됩니다.
image
  1. 이벤트 흐름 제어(버블링 & 캡처링)이 무엇인가요?
  • 버블링(bubbling): 한 요소에 이벤트가 발생되면, 그 요소의 부모 요소의 이벤트도 같이 발생되는 이벤트 전파를 의미합니다. 브라우저의 이벤트는 기본적으로 버블링 방식으로 작동됩니다. 예를 들어, 자바스크립트 addEventListener() 함수로 요소의 이벤트를 등록하면 기본적으로 버블링 전파 방식으로 이벤트가 흐르게 되어, 만일 자식 요소에 이벤트가 발생하면 부모 요소도 버블링 통해 이벤트가 전파되어 리스너가 호출되게 됩니다.
  • 캡처링(capturing): 캡처링은 한 요소에 이벤트가 발생되면, 그 요소의 자손 요소의 이벤트도 같이 발생되는 이벤트 전파를 의미합니다. 한마디로 버블링 반대인데, 실무에서 자주 쓰이지는 않지만 가끔 유용한 경우가 있습니다. 브라우저의 이벤트 전파 방식은 버블링이 기본값이기 때문에 캡처링으로 설정하기 위해선 별도의 옵션을 함수에 주어야 합니다. 자바스크립트 addEventListener() 함수의 3번째 매개변수로 true 값을 주면 이 이벤트 타겟은 캡처링을 통해 이벤트를 전파받아 호출되게 됩니다.

  1. 클로저와 스코프가 무엇인가요?
  • 스코프: 스코프는 변수의 유효 범위를 정의하는 개념입니다. 자바스크립트에서는 전역 스코프와 지역 스코프가 있는데, 전역 스코프는 코드의 어디에서나 접근 가능한 반면, 지역 스코프는 특정 함수 내에서만 접근할 수 있습니다.
  • 클로저: 클로저는 함수가 선언될 당시의 스코프를 기억하는 함수입니다. 클로저는 내부 함수가 외부 함수의 변수에 접근할 수 있게 해줍니다. 클로저는 외부 함수의 실행이 끝났는데도 불구하고, 그 외부 함수 안에 있던 변수들을 여전히 사용할 수 있는 특별한 함수입니다. 클로저는 주로 데이터 은닉, 상태 유지 등의 용도로 사용됩니다. 함수 내부에 선언된 변수는 외부에서 접근할 수 없는데, return에서 새로운 함수를 정의하여 해당 변수를 사용한다면 접근 가능하게 됩니다. 해당 함수가 다르게 사용된다면, 함수의 변수는 각각 독립적으로 유지됩니다.
function createBankAccount(initialBalance) {
  let balance = initialBalance; // 클로저에 의해 보호되는 변수

  return {
    getBalance: function () {
      ...생략
    },
    deposit: function (amount) {
      ...생략
    },
    withdraw: function (amount) {
      ...생략
    },
  };
}

const account1 = createBankAccount(10000); // 초기 잔액 10000원
const account2 = createBankAccount(15000); // 초기 잔액 15000원
//account1, account2는 독립적으로 작동함.

account.getBalance(); // 현재 잔액: 10000원
account.deposit(5000); // 5000원 입금. 새로운 잔액: 15000원
account.withdraw(3000); // 3000원 출금. 새로운 잔액: 12000원

코드 참고 및 출처: https://dsuumb.tistory.com/14

Copy link
Copy Markdown

@waldls waldls left a comment

Choose a reason for hiding this comment

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

기림님 1주차 과제하시느라 수고 많으셨습니다! 코드 보고 많이 배우고 갑니다 ㅎㅎ👍🏻👍🏻
현재 본문에 남겨주신 배포 링크의 텍스트와 실제 연결된 하이퍼주소 링크가 다른 것 같아요! 이 부분 더블체크 해주시면 좋을 것 같습니다 :)

Comment thread package.json
Comment on lines +1 to +14
{
"name": "todo",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"vite": "^8.0.0"
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Vite를 사용해서 세팅을 해주신 것으로 보입니다!
1주차 미션이 순수 Vanilla JS를 다루는 것이 목표인 만큼, package.json이나 vite.config.js 설정을 걷어내고 순수 환경을 깊게 다뤄보는 것도 좋은 경험이 될 것 같아요!

Comment thread index.html
Comment on lines +10 to +37
<header>
<h1>TO DO LIST</h1>

<div class="date-btns">
<button id="prev">◀</button>
<h2 id="date"></h2>
<button id="next">▶</button>
</div>
</header>

<main>
<section class="inputlist">
<form>
<input
type="text"
id="todo-input"
placeholder="할 일을 입력하세요."
/>
<button id="add">추가</button>
</form>

<div>남은 TO DO의 개수: <span class="count">0</span>개</div>
</section>

<section>
<ul id="todo-list"></ul>
</section>
</main>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

header, main, section 같은 시맨틱 태그를 적절히 활용해 주셔서 문서 구조가 한눈에 들어오네요! 특히 form 태그를 사용해 입력부를 구성하신 점이 인상 깊습니다ㅎㅎ

Comment thread src/main.js Outdated
Comment on lines +20 to +31
const dayIndex = now.getDay();
const shiftIndex = (dayIndex + 6) % 7;

const rainbowColors = [
"#f9d6d6",
"#FFD6A5",
"#f8f9ca",
"#e7ffe2",
"#c7f4f8",
"#A0C4FF",
"#d1cafd",
];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

요일별 배경색을 정하는 로직이 너무 센스있어요!! 👍🏻
다만 rainbowColors 배열은 유지보수를 위해 상수로 분리하는 것이 더 좋을 것 같습니다!
추후 색상을 수정하고 싶을 때 로직 내부를 뒤질 필요 없이 최상단의 상수값만 변경하면 되어 훨씬 편리할 것 같아요!
잘 알고 계시겠지만 제가 참고한 문서 링크 하나 남깁니다 ㅎㅎ

const RAINBOW_COLORS = ["#f9d6d6", "#FFD6A5", ...]; // 함수 밖 상단에 위치

const updateDisplay = () => {
  const shiftIndex = (now.getDay() + 6) % 7;
  const todayColor = RAINBOW_COLORS[shiftIndex];
  // ...
};

Comment thread src/main.js Outdated
Comment on lines +77 to +85
const createTodoItem = (value, isDone = false) => {
const li = document.createElement("li");
li.innerHTML = `
<div class="output">
<input class="check" type="checkbox" ${isDone ? "checked" : ""} />
<span style="${isDone ? "text-decoration: line-through; color: gray;" : ""}">${value}</span>
<button class="delete"> - </button>
</div>
`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

현재 createTodoItem에서 innerHTML 과 템플릿 리터럴을 이용해 요소를 생성하고 계신데, 이 방식을 textContext으로 변경해보시는 건 어떨까요? 사용자 입력값이 HTML로 해석되는 걸 막아줘서 보안상으로도 훨씬 안전하다고 합니다!
자세한 차이점과 보안 이슈에 대해서는 기림님이 참고하시면 좋을 포스팅 링크도 함께 남겨드려요!

@a-00-a
Copy link
Copy Markdown

a-00-a commented Mar 16, 2026

기림님 1주차 과제하시느라 고생 많으셨습니당!

comment에 남겨주신 배포 링크가 제 컴퓨터에서는 오류가 떠서 확인이 어려워, 기림님 깃허브에 있는 배포 링크를 참고해서 코드 리뷰를 진행했습니다!

https://vanilla-todo-23rd-ochre.vercel.app/

Comment thread src/main.js Outdated
};

const loadTodos = () => {
const savedTodos = JSON.parse(localStorage.getItem("myTodoList")) || [];
Copy link
Copy Markdown

@a-00-a a-00-a Mar 16, 2026

Choose a reason for hiding this comment

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

먼저 요일별로 지정된 배경 색상이 있어서 날짜를 넘길 때마다 시각적인 재미가 있고, 앱을 사용할 때 요일별로 배경이 바뀌는 것처럼 하루하루를 새로운 마음으로 지낼 수 있을 것 같아서 좋았습니당!

그리구 현재 localStorage.getItem("myTodoList")에서 key가 "myTodoList" 로 고정되어 있어서 날짜가 변경되더라도 동일한 todo 데이터가 로드됩니다.

_._.mp4

날짜별로 다른 todo 목록을 관리하려면localStorage.getItem(currentDate)처럼 key에 날짜 정보를 포함하는 방식도 참고하시면 좋을 것 같습니다!

Copy link
Copy Markdown

@Tutankhannun Tutankhannun left a comment

Choose a reason for hiding this comment

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

이번 주차 과제 수고하셨습니다~~ 위트있는 기능도 추가해주시고 Pretendard 폰트 적용도 잘하셨네요. 다른 분들도 좋은 코드 리뷰들 남겨주셔서 잘 참고해주시고 담주 과제도 화이팅입니다!!

Comment thread src/main.js Outdated
li.querySelector(".check").onchange = (e) => {
const span = li.querySelector("span");
if (e.target.checked) {
span.style.textDecoration = "line-through";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

완료 스타일에 인라인 js를 사용해주셨네요. 나중에 디자인을 수정하는 등의 유지 보수를 위해서는 css에서 클래스로 관리하는 게 깔끔할 것 같습니다!

Comment thread src/main.js Outdated
import "./style.css";

const input = document.querySelector("#todo-input");
//const addBtn = document.querySelector("#add");
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

더 깔끔한 코드를 위해서 사용하지 않는 코드는 제거하는 것이 좋습니다!

Comment thread src/style.css Outdated
gap: 10px;
width: 100%;
max-width: 500px;
gap: 10px;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

중복 선언된 gap도 정리해주시면 좋을 것 같습니다~

Comment thread src/main.js Outdated
const countElement = document.querySelector(".count");
const todoForm = document.querySelector("form");

const now = new Date();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

최근 Date의 대채제로 이슈 중인 Temporal Api에 대해서도 한 번 읽어 보시면 좋을 것 같습니다~
Date는 사라지고 Temporal이 온다

Comment thread index.html
<body>
<div id="app">
<header>
<h1>TO DO LIST</h1>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

UI 상에서 다른 요소와 같이 해당 텍스트도 중앙 정렬해주셔도 좋을 것 같습니다.

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