데브코스에서 진행한 첫 번째 프로젝트였습니다 !
바닐라 자바스크립트 강의를 수강 후 노션을 클론하는 프로젝트를 과제로 진행했습니다.
프로젝트도 회고도 처음이니 감안하고 봐주시면 감사하겠습니다 😊
바닐라 JS만을 이용해 노션을 클로닝합니다.
기본적인 레이아웃은 노션과 같으며, 스타일링, 컬러값 등은 원하는대로 커스텀합니다.
API로 서버에서 데이터를 가져와 폴더명을 트리 구조로 표현
추가 / 삭제 / 수정 기능 구현
별도의 저장 방법 없이 자동저장 구현
history API를 이용하여 SPA 구현
폴더 구조
컴포넌트 구조 및 기능
App.js : 컴포넌트를 불러오고 실행하는 프로젝트의 시작 화면입니다. history API의 라우팅 기능도 App.js에서 실행됩니다.
PostPage.js : PostList.js를 불러와 화면에 렌더링하고 추가/삭제 등의 이벤트를 처리합니다.
PostList.js : 서버에서 받아온 문서 목록을 트리구조로 만들어서 보여줍니다.
PostEditPage.js : post를 수정하고 저장하는 페이지 입니다. 자동 저장 기능은 디바운싱을 이용하여 localStorage에 수정한 내용을 저장하고, 저장된 후에는 localStorage를 비울 수 있게 구현하였습니다.
Editor.js : 문서를 작성하는 페이지 입니다. title과 content에 keyup 이벤트가 발생할 때 마다 setState와 onEditing 함수를 실행합니다.
// 수정 전 코드
$postList.innerHTML = `<ul>
${this.state
.map((post) => `
<li class="post-list" data-id="${post.id}">
${post.title}
<button class="add-button">+</button>
<button class="remove-button">-</button>
<ul>
${post.documents.map((document) =>`
<li class="post-list" data-id="${document.id}">${document.title}
<button class="remove-button">-</button></li>`
).join("")}
</ul>
</li>
`
처음에는 방법을 생각해내지 못해서 map안에 map을 또 사용하는 방식으로 코딩을 하였습니다. 하지만 이런식으로 하면 2층까지밖에 구현을 할 수가 없었죠 ...
// 수정 후 코드
const renderPosts = (posts) => {
return `<ul>
${posts.map((post) => {
return `<li class="post-list" data-id="${post.id}">
${post.title}
<span class="button-wrap">
<button class="add-button" style="border: none;">
<i class="fa-solid fa-plus"></i>
</button>
<button class="remove-button" style="border: none;">
<i class="fa-solid fa-trash-can"></i>
</button>
</span>
${post.documents.length > 0 ? renderPosts(post.documents) : ""}
</li> `;
})
포기하고 그냥 낼까 자신과 타협하다가 ...^^ 팀원분이 재귀라는 힌트를 주셔서 따로 renderPosts라는 함수를 만들어 documents의 길이가 0 이상일때 (하위 문서가 있을 때) 함수를 재귀로 호출하게 구현 했습니다 !
이 부분은 강의때 제대로 이해하고 넘어가지 못한 부분이라 코딩을 하면서도 의아한 부분이 굉장히 많았습니다. 데이터의 흐름을 잘 알지 못하니 어디서 렌더를 해야하고 언제 setState를 해야하는지 막막하게 느껴졌습니다. 좀 더 연습이 필요할듯 !
과제나 프로젝트에 CSS를 입혀본건 이번이 처음이었던 터라 사실 심미적인 부분은 크게 기대를 하지 않았습니다. 하지만 placeholder, hover등 사용자의 입장에서 사용성을 크게 높일수 있는 부분을 몰라서 사용하지 못했다는 점이 아쉬웠습니다.
CSS에 대해서 좀 더 공부해서 천천히 적용해 보려고 합니다!
위 사진은 처음 제가 목표했던 컴포넌트 구조입니다. 아무래도 강의에서 진행하셨던 코드를 기반으로 프로젝트를 해 나가다보니 그 코드에 맞춰서 코딩을 했습니다. 그래서 지금은 postList를 불필요하게 계속해서 렌더링 하는 문제가 있는데, 이 부분도 추후 변경할 예정입니다 !
디바운스 부분은 프로젝트 진행시 이해가 전혀 안되었던 부분이라 강사님 코드를 참고 하였습니다 😂 낙관적 업데이트는 아예 구현하지 못했습니다 ㅜㅜ
토글버튼 구현
지금은 트리가 다 펼쳐진 채로 폴더명 목록이 나오고 있습니다.
토글 기능을 추가해 좀 더 사용성을 높이고 싶습니다.
CSS
아직 CSS가 많이 미흡했는데 목요일 박영웅님의 CSS Flex특강을 듣고 CSS를 좀 더 공부해보고 싶다는 생각을 했습니다. 코스에 CSS심화 과정이 있기도 하니 그 전에 노션 프로젝트를 리팩토링 하면서 CSS 연습도 더 하고싶습니다!
postPage에서 postList + postEditPage 둘 다 렌더링 할 수 있게
오류 해결
제목을 입력하고 저장되면 제목의 마지막 글자가 지워지고 내용을 쓰거나 새로고침을 하면 다시 생기는 이상한(?)에러가 발생하고 있습니다.
보너스 요구사항 해결하기
contentEditable을 이용하여 좀 더 rich한 에디터를 만들어보고 싶습니다!
'완성이지만 미완성입니다 ~'
일주일에 걸친 프로젝트가 끝이 났네요 ㅎㅎ
사실 마지막 이틀정도는 정말 완성을 못할거라고 확신하고 우울감에 빠져서 컴퓨터 앞에서 한숨만 쉬었던것 같습니다 ㅋㅋ
그렇지만 실패는 성공의 어머니 라는 말이 있져? 그만큼 저는 성장했다구여 ㅡㅡ !!
무작정 뛰어들기 보다는 프로젝트를 진행하기 전에 요구사항을 꼼꼼히 작성하는 것이 중요하다는 것, 내 코드의 문제점을 정확하게 파악해야 남에게 도움을 받을 수 있다는것 ,, 정말 많은것을 배웠고 또 많은 아쉬움이 남는 프로젝트였습니다 ~,,,
프로젝트 끝 ,,, 하지만 쌓인 일은 37463개 ,,,,
그래서 ,,, 혹시 너 ,,,나 안지쳤어 !!! ㅜㅜㅜ 할수이써 !!!!!!
구조부터 깜빡임까지 왠지 익숙한 앱이네요...😂 동지를 찾은 느낌이에요 ㅋㅋㅋ
이번 과제 정말 고생 많으셨습니다! 앞으로도 수료까지 같이 열심히 달려봐요! 바위 ~ 🙋♂️