(4~5주차) Notinon Cloning Project
2022년 10월 20일(목) ~ 2022년 10월 25일(화)
👶🏻프로젝트 시작👶🏻
👩🏻김민우
- editor 강의를 보고 파일 구상이 되어있다고 판단해서 설계없이 bottom-up방식으로 컴포넌트를 만들어 나갔는데 이때는 후에 불러올 참사🙀를 생각하지 못했습니다.
🐶 김민재
- 처음에는 구현해야하는 기능들 중심적으로 생각을 하였습니다. API 동작 방식을 먼저 생각하려고 하였고 이 후 컴포넌트를 붙이면 동작하지 않을까 하였고 이로 인해 설계에 대한 부분을 많이 놓치고 시작하게 되었습니다.
🙎🏻♂️김성현
- 처음에 구상을 했을 때는 크게 어렵지 않을 것으로 생각했습니다. 좌측 사이드바는 전에 트리구조를 구현한 경험을 바탕으로 구현하면 될 것으로 생각했고, 에디터 또한 앞의 강의에서 다루었기 때문입니다. 먼저 기본적인 틀을 잡고 컴포넌트를 추가해나가는 씩으로 생각하고 시작하였습니다.
👨🏻💻 변건오
- 사이드바 부분과 editor 부분만 컴포넌트로 나누어서 개발하면 된다 생각했고 기능도 많이 필요없다고 생각하였고 지금까지 강의에서 실습한 TodoList app과 editor를 잘 융합하면 쉽게 만들 수 있다고 생각했습니다.
👶안재관
- 강의 내용을 바탕으로 에디터와 state를 활용한 dataflow를 구성하려 했다. 프로젝트의 크기가 크지 않아서 데이터가 이동해야 할 depth가 깊지 않아, 머릿속으로 간략하게 구상하고 구현에 들어갔다. 자동 저장 에디터를 활용해서 내용을 저장하고 API 호출만 잘 이뤄지면 문제없이 생성할 수 있을 줄 알았다. 이때 까지는 쉬울줄 알았지……🤦♀️
👦🏻진행 및 어려웠던 점👦🏻
👩🏻김민우
- Rich editor 구현
- contentEditorable은 포커스가 될때 input과는 반대로 커서가 앞으로 가는것을 알게 되었다. selection.getRangeAt 같은 것을 사용해서 마우스 커서의 위치를 작성중인 글 맨 뒤로 변경하려 했으나 실패했다…… 😂
- 기능 구현을 추가할때마다 처음 구상과는 다르게 새로운 컴포넌트들이 생겨나기 시작했다.
- 처음부터 설계가 잘못되었다라는 것을 감지한 시점
- 새로운 컴포넌트가 만들어질때 마다 컴포넌트간의 의존성도 갖게 되었다 🤛
- 받아온 데이터의 id를 어떻게 정할지 고민했다.
- api 자체적으로 데이터가 생길때마다 자동으로 id가 주어지기 때문에 쉽게 해결 가능했다.
- 🐞Error를 찾는과정
- 본인의 코드는 본인이 가장 모른다(🤔) 팀원들 각자 중간중간 디스코드 화면공유를 통해서 구현사항을 브리핑했고 5명이 모이니 생각했던것 보다 버그가 많았다.
🐶김민재
- 설계
- 조금 늦기는 하였지만 구조에 대해 생각해보았고 크게 두 갈래 sidebar와 editpage로 구분하여 프로젝트를 진행했습니다.
- 초기 계획
- 화면 깜빡임을 방지하고 싶어서 리스트를 한번만 받아온 후 서버 통신에 오류가 없다면 문서들을 다 낙관적 업데이트로 구현해보고 싶었습니다.
- 트리 구조 구현
- 초기 재귀적인 방식으로 아래로 접근하는 방식을 생각하긴 하였으나 구현하는데 어려움을 겪었고 결국 해결하긴 하였습니다.
- Fold state
- 초기 계획으로 진행하다가 상위 문서가 삭제될 때 하위 문서들이 root로 가서 이를 처리하기 위해서는 상태값을 setState 해야 한다는 점을 발견하였고 뒤늦게 구현하려고 하였으나 실패하였습니다.
- 이후 계획으로는 객체로 localstorage에 저장하여 key = id, value = true or false로 정리해보려고 합니다.
- API
- API 동작 방식을 이해하고 프로젝트를 작성하는게 훨씬 시간을 단축할 것이라고 생각하여 여러가지 시도를 해보았습니다. 지울때 리턴되는 값을 이용해보기도 하였습니다.
- state
- APP에서 documents 리스트를 받고 sidebar에서는 route와 documents 리스트 상태만을 이용하고 editpage에서는 document의 id를 이용한 제목과 내용들만 다루도록 노력하였으나 쉽지 않았습니다.
- Eidtor
- 다른 분들과 같이 contenteditable을 이용해서 더 다양한 기능을 구현해보고 싶었으나 시간 분배 실패와 이해하기 어려운 개념으로 인해 실패하였습니다.
- 리팩토링을 진행하며 다시 구현해보고 싶습니다.
🤦🏻♂️김성현
- UL-li 태그 중첩으로 인한 Hover Event시의 문제
- 사이드바에서 li태그에 호버이벤트를 넣고 싶었으나, 제가 짠 코드의 구조가 li안에 li가 게속 중첩되는 형식이라 하위 li가 있는 경우 상위 li가 길게 늘어나 원하는 모양대로 되지않았습니다.
- 사이드바 구조를 바꾸기엔 늦었다고 생각하여 어쩔 수 없이 li 내부의 텍스트와 버튼에만 호버이벤트를 넣어주었고, 시작하기전 기획이나 생각을 더 많이 해야겠다고 생각했습니다.
- 에러를 찾아내는 과정
- 처음엔 예상하지 못했던 부분이나 기능에서 에러가 발생하여 코드를 손보거나 방어코드를 추가해야하는 경우가 많았습니다. 완성한 지금도 아마 발견하지 못한 부분이 있을 것이고, 이런 것을 찾아내면서 수정해나가는 것이 어려웠던 것 같습니다.
🤷🏻♂️ 변건오
- Sidebar
- 문서 목록을 불러오는 것은 쉬웠지만 자식 요소까지 tree 형태로 출력하려고 하니 어려웠습니다.
- 처음에는 자식이 있으면 보여주고 없으면 다음 문서를 보여주는 형태로 코드를 짰는데, 마지막 요소에 다다를 때, 자꾸 undefined를 마주하게 되었습니다.
- 또한, 위 방식을 사용했을 때, Toggle 버튼을 통해 문서를 열고 닫는데 Toggle 버튼 이벤트가 자식요소에 계속 남아있어 위로 끌어올리지 못하여 Toggle이 제대로 동작하지 않았습니다.
- 재귀 함수로 문서 Tree를 작성하였고 팀원들의 도움으로 Toggle의 상태를 LocalStorage에 담아 Toggle 상태에 따라 자식 문서를 보여주고 숨기는 형태로 구현했습니다.
- ul 태그를 재귀함수를 통해 다시 사용하다 보니 한 곳에만 일어나야하는 이벤트가 전체적으로 일어나는 버그가 발생
- Editor
- Editor에서 수정을 할 때, 수정할 때마다 focusout 되는 현상이 발생했습니다.
- 이 버그는 onEditing (수정 함수)에서 render함수를 넣어 수정이 일어날 때마다 렌더링이 다시 되어 발생하는 버그로 렌더링 함수를 빼고 setState를 넣어 버그를 방지했습니다.
- Editor 제목을 변경했을 때, Sidebar의 문서 제목도 바로 바뀌도록 구현해야했는데 최상단 컴포넌트인 App에서 데이터 관리를 안하다 보니 변경사항을 바로 적용할 수 있도록 코드를 짜지 못하였고(원했던 낙관적 업데이트를 하지 못하였다)
🪓🤬🥃안재관
- sidebar
- 문서목록을 tree 형태로 불러오는 것도 처음에 어려웠다. BFS || DFS를 사용해서 구현하려했는데 ul 태그 안에 li를 위치시키는 것이 생각보다 잘 떠오르지 않았다. 결국은 재귀형태로 구현했다. 처음에 li 태그 안에 들어갈 내용을 생각하지 않고 무작정 넣어서 나중에 p태그를 사용해서 다시 수정했다. 여기서 진행 상황을 2번정도 갈아 엎었기 때문에 생각보다 시간이 훨씬 더 많이 소요되었다.😢
- 선택된 문서, 현재 하위 문서를 보여줄지에 대한 여부를 localStorage를 사용해서 구현했다. 처음엔 set과 같은 자료구조를 사용하려고 했는데 그럴 경우 새로 고침 할 때마다 값이 매번 새로워지기 때문에 잘못된 방법이였다.
- 글이 생성 | 삭제 | 업데이트 될 때마다 리스트를 업데이트 해야했다. 전체적으로 sidebar를 다시 그리는 방법을 선택했다.
- Editor
- 새 글을 작성하는 상황에 따라 에디터의 내용이 달랐다.
- 루트 문서를 작성할 때, 새글을 연속해서 작성할 때 등등 다양한 상황이 있는데 각 상황마다 에디터가 적절하게 동작하지 않는 상황이 생겼다. 다양한 상황들을 너무 많은 조건 분기로 나누려고 했던 탓에 조건 분기를 간소화 했다.
- route
- 변경 사항이 즉시 반영 되지 않는 문제가 있었다.
- 경로에 따라서 페이지에 그리는 정보가 다르다. 그리고 그 때마다 컴포넌트들이 state를 갱신 하기 때문에 변경사항이 있으면 현재 페이지나 메인 페이지로 다시 routing 시켜서 화면이 갱신된 것처럼 보이게 만들었다.
👴마치며 (느낀점 또는 개선해야 할 점)👴
👩🏻김민우
- 진행하면서 가장 큰 느낀점은 설계의 중요성이다. 프로젝트 마감일이 다가올 수록 변경해야하는 부분이 많아지고 컴포넌트간의 의존성을 줄이기 위해서는 구조적으로 처음부터 수정하지 않는다면 불가능 했다.🛠️
- 팀원의 중요성을 느꼈다. 혼자 해결이 불가능할때 팀원들과 의견을 주고받으면서 더 나은 기능구현을 할 수 있었다. 다들 새벽까지 안주무셔서 언제든 질문이 가능했다.😄
- store를 사용할 수 없는 상황에서는 데이터를 최상단에서 뿌려주는 것이 좋은 방법이라고 생각하게 되었다.
🐶김민재
- 상태 값을 잘 관리하는 것만으로도 컴포넌트의 의존성을 줄일 수 있다.
- 진행한 방향에서 결국 실패하였지만 상태 값을 잘 다뤘다고 느끼지 못하여서 아쉬움이 많이 남습니다. 리팩토링과 다음 프로젝트에서는 더 깔끔한 상태관리를 구현해보고 싶습니다.
- 프로젝트를 진행할수록 아쉬움이 크다.(설계의 중요성)
- 초기에는 정말 이해가 잘 되지 않아서 진행 방식을 잘 못잡았지만 직접 구현해보며 잘못된 점을 느끼고 있으나 마감시간에 가까워져 너무 뒤로 돌아갈 수 없었습니다.
- 초기 설계의 중요성을 느끼게 되었습니다. 위부터 상태값을 내려주고 최 하위 컴포넌트가 가진 상태는 적어도 상위 컴포넌트가 조율해야한다는 개념도 알게되었습니다.
- 내가 한 고민은 팀원도 하고 있거나 이미 하였다.
- 질문을 통해 많은 점들을 배울 수 있었고 팀원들이 궁금한 내용은 제가 궁금해할 예정이거나 궁금했던 점들이기에 함께 성장하고 속도도 아주 빠르게 진행할 수 있었던 것 같습니다.
- 팀원들과 함께하여 힘도 많이 났고 마무리까지 잘 할 수 있었습니다.
🙇🏻♂️김성현
- 코드를 짜기 전의 기획의 중요성이나 코드를 짜는 순서를 알 수 있었습니다.
- 코딩을 진행하는 과정에서 예상치 못한 오류나 생각의 변화로 앞에서 짠 코드가 걸림돌이 되는 경우가 있었습니다. 결국엔 고민하고 코드를 다시 가다듬는 과정이 필요하게 되어서 시작하기전 기획이나 생각을 더 많이 해야겠다고 생각했습니다.
- state 관리에 대해 깊게 알 수 있었고, 효율적인 관리의 중요성을 알 수 있었습니다
- 실제 데이터와 state간의 차이가 일어나지 않도록 잘 관리해 주어야 자연스럽고 문제없는 뷰를 유지할 수 있고, 이에 따라 낙관적 업데이트를 하며 어려움도 많이 느꼈던 것 같습니다.
- 컴포넌트의 depth가 늘어남에 따라 state를 전달하고 관리하는 것에 복합해지는 것을 느꼈기에 이것을 잘 관리하는 것에 대한 중요성도 알 수 있었습니다.
🧟♂️ 변건오
- 데이터를 최상단에서 관리할 수 있도록 구조를 짜는 것이 좋은 방법이라고 느꼈습니다.
- 하위 컴포넌트들을 만들고 합치는 Bottom-Up 방식은 무엇을 구현하고 어떤 기능이 있는지 모두 파악한 후에 해야 효율이 좋다는 것을 깨달았습니다. 기능 하나하나 필요할 때마다 붙여서 개발하다 보니 잘되던 코드도 수정을 통해 오류가 발생할 수 있고 데이터 관리도 힘들게 느껴졌습니다.
- 처음 설계할 때, 필요한 데이터가 무엇이 있고 어디에서 쓰일지 잘 설계해야된다고 느꼈습니다.
- 한 가지 문제에 너무 몰두해 있으면 넣고 싶었던 기능도 못 넣게 된다. 시간 계획을 잘 세워야겠다고 생각이 들었습니다.
👴안재관
- 구현을 시작하기 전에 계획을 잘 세워야한다.
- 처음에 아무 생각없이 bottom-up 방식으로 구현했는데 나중에 보니 App 컴포넌트에서 data를 전달하는 방식이 더 좋았다. 최소한 data-flow 정도는 그리면서 생각해보자.
- 기능을 덧 붙일 때 조금 더 고민하자
- 하위 컴포넌트에서 데이터가 필요하거나 갱신이 이뤄져야 할 때 무분별 하게 fetch를 남발했다. 이러한 과정은 성능을 떨어 트릴 수 있다. 임기응변으로 구현 하다보니 나중에 로딩 속도가 느린 것처럼 보이는 상황이 발생했다….😂