Conversation
corinthionia
left a comment
There was a problem hiding this comment.
안녕하세요 주희 님!
거의 모든 줄에 상세하게 주석을 달아 주셔서 어떠한 과정으로 코드를 작성하셨는지 그 흐름을 엿볼 수 있었던 것 같습니다 👍🏻 몇 가지 코멘트 남겨 두어서 확인해 보시면 좋을 것 같아요 🙂 과제 고생하셨습니다!!
script.js
Outdated
| @@ -1 +1,92 @@ | |||
| // 다들 화이팅!! ٩( *˙0˙*)۶ No newline at end of file | |||
| function handleAddTodo() { | |||
| let inputValue = document.getElementById("todo-input").value; // 입력한 todo 집중 | |||
There was a problem hiding this comment.
또한 document.getElementById("todo-input").value 가 자주 사용되므로, 최상단에 미리 변수에 할당하고 해당 변수를 사용하면 가독성이 더욱 좋아질 것 같아요 👀
There was a problem hiding this comment.
최상단이라고 하면 전역 변수로 할당하는 것 맞을까요 ?!
script.js
Outdated
| if (!inputValue) return; // 입력된 todo가 존재하지 않는다면 아무것도 하지 않기 위함 | ||
|
|
||
| let todos = JSON.parse(localStorage.getItem("todos")) || []; // localstorage에 저장해둔 todo를 가져와서 객체로 (아직 아무것도 없다면 빈 배열로 초기화) | ||
| todos.unshift(inputValue); // 입력된 todo를 추가 |
There was a problem hiding this comment.
unshift()를 사용하신 이유가 최신순으로 정렬하기 위함일까요?!
다른 분들 코드에도 코멘트 달았던 내용이긴 한데 unshift()는 원본 배열을 직접 변경하기 때문에, JavaScript로 배열을 조작할 때에는 새로운 배열을 만들고, 그 배열을 할당하는 방식으로 진행하는 것이 좋습니다!
그 이유가 궁금하시다면,,,
JS의 immutability(불변성) 관련된 문제인데 이 글에 자세히 나와 있어서 참고하시면 좋을 것 같아요!
간단히 설명드리자면, 배열의 값을 직접 변경할 경우 디버깅이 어렵고 의도치 않은 결과를 불러올 수 있기 때문에 배열의 값을 직접 변경하는 방식이 아닌 새로운 배열을 만들어 할당하는 방식을 추천합니다. 따라서 값을 직접 변경하는 push() , unshift(), splice() 등의 메서드보다 새로운 배열을 반환하는 map(), filter() 혹은 spread 연산자를 사용하는 방식을 권장합니다 👀 또한 나중에 React를 사용하실 때에도 배열 불변성을 지켜 주셔야 상태 변화 감지와 성능 최적화 부분에서 용이하답니다!
There was a problem hiding this comment.
맞습니다! 최신순을 위해 push에서 unshift로 수정했었습니다! 아직 성능 최적화를 위한 코드작성 방법은 잘 모르는 상황인데 자세한 조언 감사합니다 ㅎㅎ
script.js
Outdated
| let todos = JSON.parse(localStorage.getItem("todos")) || []; // localstorage에 저장해둔 todo를 가져와서 객체로 (아직 아무것도 없다면 빈 배열로 초기화) | ||
| todos.unshift(inputValue); // 입력된 todo를 추가 | ||
|
|
||
| localStorage.setItem("todos", JSON.stringify(todos)); // update 된 객체를 localStorage 에도 update |
script.js
Outdated
| document.getElementById("todo-input").addEventListener("keydown", function (event) { | ||
| if (event.isComposing && event.key === "Enter") { | ||
| handleAddTodo(); // Enter 키가 눌리면 todo 추가 함수 호출 | ||
| } | ||
| }); |
There was a problem hiding this comment.
엔터키로 할일을 추가하는 부분이 제대로 동작하지 않는 것 같아요!
There was a problem hiding this comment.
한글로 input 작성 후 엔터키로 todo를 추가하면 한글이 두 번씩 나오는 현상이 있어서 isComposing으로 해결해보려고 추가한 코드인데, 이렇게 하게 되면 영어로 입력 시에는 엔터키가 안 먹더라구요.. 조금 더 해결해 보도록 하겠습니다!
| todoList.innerHTML = ""; // 새로운 목록을 업데이트하기 위해 기존 목록 초기화 | ||
| // 초기화하지 않고도 배열에 추가된 항목을 화면에 표시할 수 있지만 -> 중복 문제, 성능 문제 생길 수 있음 | ||
|
|
||
| todos.forEach((todo, index) => { |
There was a problem hiding this comment.
forEach() 사용 좋습니다!! 👍🏻
script.js
Outdated
|
|
||
| todos.forEach((todo, index) => { | ||
| let li = document.createElement("li"); // todo 목록에 들어있는 각각의 값 마다 li 태그 붙이기 | ||
| li.innerHTML = `<span onclick="handleAddDone(${index})">${todo}</span> <i class="delete-btn" onclick="handleDeleteTodoItem(${index})"></i>`; // handleAddDone 함수와 handleDeleteTodoItem의 인자로 index를 넘겨주는 기능을 한 번에 처리하기 위함 |
There was a problem hiding this comment.
innerHTML은 주희 님이 사용하신 것처럼 스크립트를 문자열로 삽입할 수 있기 때문에 보안상 취약한 방법이라 여겨지고 있습니다! 따라서 createElement와 append/appendChild를 사용하여 <script> 요소를 생성하고 삽입하는 방법이 더 안전한 방법이라고 합니다 👀
There was a problem hiding this comment.
코드 관리 면에서 중요한 부분들을 많이 알아가는 것 같습니다! 이 부분도 참고하여 리팩토링 후 추가 커밋 하도록 하겠습니다 ㅎㅎ
script.js
Outdated
| let todos = JSON.parse(localStorage.getItem("todos")) || []; // localstorage에 저장해둔 todo를 가져와서 객체로 (아직 아무것도 없다면 빈 배열로 초기화) | ||
|
|
||
| todos.splice(index, 1); // todos 배열 내의 index에 해당하는 값을 1개 삭제할 것 |
There was a problem hiding this comment.
위에 언급한 배열 불변성을 고려하여 splice() 대신 filter() 메서드를 사용해 보면 좋을 것 같습니다!
| document.addEventListener("DOMContentLoaded", () => { | ||
| // 초기 렌더링 설정을 위한 코드 | ||
| // DOM이 완전히 로드된 후에 초기화되도록 설정! | ||
| // 로컬 저장소에서 가져온 데이터로 초기 상태 보여질 수 있도록 함 | ||
| // 이 코드가 없다면 페이지 로드 시 초기 목록을 로드하는 데 실패할 수 있음 | ||
| renderTodos(); | ||
| renderDone(); | ||
| }); |
| /* 스크롤바의 폭 너비 */ | ||
| .scrollbar::-webkit-scrollbar { | ||
| width: 10px; | ||
| } | ||
|
|
||
| .scrollbar::-webkit-scrollbar-thumb { | ||
| background: rgba(220, 20, 60); /* 스크롤바 색상 */ | ||
| border-radius: 10px; /* 스크롤바 둥근 테두리 */ | ||
| } | ||
|
|
||
| .scrollbar::-webkit-scrollbar-track { | ||
| background: rgba(220, 20, 60, 0.1); /*스크롤바 뒷 배경 색상*/ | ||
| } |
There was a problem hiding this comment.
스크롤바 디자인까지 신경쓰시다니 멋져요 👏🏻
jaee55555
left a comment
There was a problem hiding this comment.
localStorage부터 스크롤바 디자인까지, 세세한 부분을 다 챙기신 것같아서 주희님의 세심함을 알 수 있었습니다. 특히나 자세한 주석으로 설명해주셔서 코드를 쉽게 이해할 수 있었습니다.
주희님의 코드를 보면서 저 또한 많이 공부할 수 있었네요🤩
한 주동안 고생하셨습니다!
| <!-- 할 일 추가될 곳 --> | ||
| </ul> | ||
| </section> | ||
| <hr /> | ||
| <section class="done-list-box"> | ||
| <h4 id="done-list-title">💿 DONE (0)</h4> | ||
| <ul class="done-list"> | ||
| <!-- 완료된 일 추가될 곳 --> |
There was a problem hiding this comment.
HTML 안에서 목록들이 추가될 곳에 주석으로 정리 해주셔서
DOM 조작할 때 항목들이 어디에 들어갈지 바로 알아볼 수 있어서 너무 좋습니다!
| * { | ||
| font-family: "Binggrae-Two"; | ||
| } |
There was a problem hiding this comment.
*을 사용하여 폰트를 전체적으로 적용해주셨네요!
저는 *을 생각하지 못해서 모든 font-family에 폰트명을 작성했는데 주희님 코드 덕에 쉽고 간단한 방법 배워갑니다!
ongheong
left a comment
There was a problem hiding this comment.
안녕하세요 주희님! 1주차 미션에서 주희님의 코드 리뷰를 하게 되어 기쁩니다!
자바스크립트의 코드 스타일을 잘 적용해주셔서 많이 배워갈 수 있는 리뷰였습니다🙇🏻♀️ 함수마다 이름과 맡은 역할이 명확하게 정의되어 있고, 코드별로 주석을 꼼꼼하게 달아주셔서 이해하기 쉬웠습니다.
앞으로도 꾸준히 반복적으로 JS를 공부하는 모습 기대하겠습니다! (같이 공부해봐요!) 😀😀
| // localStorage에서 값을 가져오는 함수 | ||
| function getLocalStorageItem(key) { | ||
| return JSON.parse(localStorage.getItem(key)) || []; | ||
| } | ||
|
|
||
| // localStorage에 값을 새로 저장하는 함수 | ||
| function setLocalStorageItem(key, data) { | ||
| localStorage.setItem(key, JSON.stringify(data)); | ||
| } |
There was a problem hiding this comment.
localStorage에서 값을 가져오고 저장하는 일이 빈번한데, 이를 getter와 setter 메서드로 정리해서 코드 안전성/유지보수성을 높인 부분이 좋습니다!
There was a problem hiding this comment.
처음 코드 작성 할 때부터 꼭 수정해봐야겠다고 생각했던 부분이라, 리팩토링 시 가장 우선순위로 두었던 것인데 드러난 것 같아 뿌듯합니다 🤩
|
|
||
| function handleAddTodo() { | ||
| let inputValue = todoInput.value; // 입력한 todo 집중 | ||
| if (!inputValue) return alert("내용을 입력해주세요!"); // 입력된 todo가 존재하지 않는다면 아무것도 하지 않기 위함 |
|
|
||
| addTodoBtn.addEventListener("click", handleAddTodo); // +버튼에 todo 추가하는 함수 연결 | ||
|
|
||
| function renderTodos() { |
There was a problem hiding this comment.
renderTodos라는 직관적인 함수명을 통해 해당 함수가 가진 역할(html 요소가 화면에 표시되는 것)을 바로 파악할 수 있어 좋습니다!🙌
| @font-face { | ||
| font-family: "KyoboHand"; | ||
| src: url("https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_20-04@1.0/KyoboHand.woff") format("woff"); | ||
| font-weight: normal; | ||
| font-style: normal; | ||
| } | ||
| * { | ||
| font-family: "KyoboHand"; | ||
| } |
| html, | ||
| body { | ||
| width: 100vw; | ||
| height: 100vh; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| background: radial-gradient(circle at 50% 0, rgba(255, 38, 38, 0.5), rgba(255, 0, 0, 0) 70.71%), | ||
| radial-gradient(circle at 6.7% 75%, rgba(30, 30, 255, 0.5), rgba(0, 0, 255, 0) 70.71%), | ||
| radial-gradient(circle at 93.3% 75%, rgba(63, 255, 63, 0.287), rgba(6, 26, 6, 0) 70.71%) beige; | ||
| } |
| /* 스크롤바의 폭 너비 */ | ||
| .scrollbar::-webkit-scrollbar { | ||
| width: 10px; | ||
| } | ||
|
|
||
| .scrollbar::-webkit-scrollbar-thumb { | ||
| background: rgba(220, 20, 60); /* 스크롤바 색상 */ | ||
| border-radius: 10px; /* 스크롤바 둥근 테두리 */ | ||
| } | ||
|
|
||
| .scrollbar::-webkit-scrollbar-track { | ||
| background: rgba(220, 20, 60, 0.1); /*스크롤바 뒷 배경 색상*/ | ||
| } |
There was a problem hiding this comment.
스크롤바 구현 자체는 여러번 해보았지만 커스텀 디자인을 해본 경험은 적어서 이번 기회를 통해 많은 글들을 찾아보았는데 그 중 가장 상세한 설명이 있는 글인 것 같아 공유합니다! 같이 공부해요 🙌
| <div class="container"> | ||
| <!-- <header>📚 투두리스트</header> --> | ||
| <header> | ||
| <img id="emoji" src="/images/emoji.png" alt="이모지" /> |
안녕하세요, LG U+ URECA 프론트엔드 대면반 1기 고주희입니다.
노마드코더 JS 강의 수강, Core Javascript 책 스터디, 유레카 수업에서 다룬 JS, 며칠 전 완강한 드림코딩의 JS 기초 강의 수강 경험 등을 바탕으로 어쩌면 금방 할 수 있지 않을까 싶었으나 .. 역시나 DOM으로 태그 하나하나에 접근하고 업데이트해줘야하는 작업이 무척 번거롭고 어렵다는 생각이 들었습니다. 항상 react에 의존해서 구현해왔었다는 것을 다시 한 번 깨닫는 시간이었습니다. 🥲
알고 있다고 생각했는데 생각보다 훨씬 더 빈틈이 많았고, 꾸준히 반복적으로 JS를 공부해야겠다고 다짐했습니다. (믿어주십쇼)
알게 된 부분
앞으로 개선하고자 하는 부분
KEY QUESTION
배포
https://zuitopia-todo.vercel.app/