토이프로젝트) 간단한 Todo App 을 만들어보자.

나의 개발 일지·2022년 12월 14일
0

회고

목록 보기
1/1
post-thumbnail

(github repo)
Client : https://github.com/yeonhwan/Scribe_client
Backend : https://github.com/yeonhwan/Scribe_client

(app example)
https://www.flickr.com/photos/197135331@N07/albums/72177720304428463

로그인 화면

어플리케이션 내 화면


1) 시작

프로젝트의 목표는 Todo 리스트 어플리케이션을 만들어 보는 것.

이 토이 프로젝트를 시작하게 된 계기는 정말 단순하게도 섹션 3의 마지막 과제가 섹션 4에도 사용된다는 이유 하나였다.

매 섹션들 을 마무리 할 때마다 했던 해커톤 과제가 항상 시간도 너무 부족했고 어떠한 것을 실제로 만들어 본다는 성취감도 실제로 얻을 수 없었기 때문에 저 사실이 내가 프로젝트를 실제로 만들기 시작하게 된 가장 큰 동기가 될 수 있었다.

섹션 3 마무리 부터 섹션 4 마무리 까지 약 한 달여 간의 시간을 활용할 수 있었기 때문이다.

그동안 과정들을 수료해나가면서 스스로에 대한 매너리즘에 빠져가고 있었기 때문에 내 스스로 처음부터 무언가를 만들어 가는 것이 무언가 스스로를 환기하는 계기가 될 수도 있다는 점은 덤이었다.

2) 기획

사실 이 토이프로젝트를 해 나가면서 스스로 가장 부족했음을 절실하게 느꼈던 부분이 바로 기획단계였다.

앞서 언급했던 것처럼 프로젝트의 시작은 굉장히 사소한 이유에서였기 때문에 어떠한 거창한 계획을 마련해서 프로젝트를 진행하지 않았다.

기획 아닌 기획이 있다면 내가 지금까지 독학 및 코드스테이츠 과정에서 배운 것들을 모두 총체적으로 복습하고 실제적으로 사용해보는 시간을 마련해보는 것이었다.

기획이 이렇다보니 내가 학습한 내용들이 하나 하나 떠오를 때마다 그를 활용한 기능들을 추가해보는 식으로 개발을 진행했다.

하지만 이런 방식으로 어플리케이션을 기획하다보니 개발을 진행해 나갈 수록 많은 부분에서 개념적으로 복잡해지고 꼬이기 시작했다.

또한 기획을 통해 해야할 일들을 분명하게 만들지 않으니 코드를 실제로 타이핑 하려고 마음먹기까지 굉장히 힘들기도 했다.

그래서 결국 프로젝트 진행 도중 개괄적으로 내가 만들고자 하는 것을 리스트 형식으로 만들어보면서 뼈대를 잡았지만 충분하진 않았던 것 같다.

다음 부터 어떠한 작은 프로젝트라도 시작하기 전에 반드시 기획하고 생각하는 시간을 충분히 가져야겠다는 깨달음을 얻었다.

3-1 ) 개발 / 요약

내가 이번 토이프로젝트에서 구현하기 위해서 애썼던 목표들은 다음과 같다.


  1. 가장 기본적인 Todo 리스트의 CRUD 구현
  2. Todo 리스트가 클릭이벤트에 따라 완료/비완료 상태로 전환이 가능할 것
  3. Todo 리스트의 드래그 앤 드랍 구현
  4. Todo 리스트의 기능을 확장함으로써 필요한 Navbar 컴포넌트 구현
  5. Todo 리스트를 확장하여, Todo 리스트를 종류 별로 만들어 보관할 수 있는 리스트보드 형식의 데이터 구조 구현 (이 또한 역시 CRUD 가능)
  6. 리스트보드를 확장하여 구글 로그인 기능을 통해 유저 별로 리스트보드를 CRUD 할 수 있도록 구현
  7. Todo 리스트는 중요도와 날짜를 표기 또는 표기하지 않는 형태로 만들 수 있게할 것
  8. Taskboard 라는 컴포넌트를 통해 하나의 Todo 리스트 내에서 달성도와 통계를 시각적으로 확인할 수 있도록 할 것.
  9. Todo 리스트는 기본 /중요도 /날짜 순으로 선택하여 정렬해 볼 수 있도록 할 것
  10. 프로젝트에 맞는 CSS 테마와 어플리케이션에 적절한 반응형 에니메이션 구현

구현하고자 했지만 게으름으로 시간이 부족해 더 구현하지 못했던 목표들은 유저가 리스트보드에 존재하는 모든 Todo 리스트를 중요도 별로 또는 날짜 별로 또는 완료되고 완료되지 않은 상태로 볼 수 있게 하는 페이지를 구현하는 것, 반응형 웹을 구현하는 것, 유저가 프로필을 방문해 수정하고 확인하는 것, 라이트모드 다크모드 전환 등 이었다.

아쉽지만 지금 작성해 둔 토이프로젝트를 나중에 좀 더 다듬을 수 있으니 그 때를 기약해야 할 것 같다.

또한 자잘한 버그들과 코드의 상황적 변수를 막을 수 있는 부분을 마련하지 못했고 최적화와 코드의 통일이 전혀되어있지 못한 부분들도 나중에 꼭 수정해서 완성하겠다는 다짐을 한다.

3-2 ) 개발 / 과정

목표 1 ~ 3 )

가장 먼저 Todo 리스트의 CRUD 구현과 간단한 드래그 앤 드랍 및 애니메이션 과정은 섹션 3의 해커톤 과정에서 끝마쳤다. 어쩌면 과정중에서 큰 고민 없이 가장 먼저 해결한 부분이 아닐까 싶다.

1 ) Todo CRUD

컴포넌트들의 계층 관계가 그렇게 깊지 않고 컴포넌트내의 로직이 그다지 복잡하지 않아 간단히 더미데이터를 만들고 그대로 리액트 자체 Hooks 들을 통해서 해결하려고 처음엔 생각했지만, Redux 와 같은 상태 관련 라이브러리에 대한 학습이 부족했다는 생각이 들었기 때문에 이를 최대한 활용해보기로 했다.

그러나 Redux를 그대로 사용하는 것은 워낙 사전에 준비해야하는 코드들이 양이 많아 배보다 배꼽이 더 커지는 상황에 부딪힐 것 같았다.

따라서 Redux 대신 Recoil, RTK, Zustand 세 가지 라이브러리를 놓고 고민한 후에 Redux와 비슷하지만 사용성이 훨씬 개선된 Zustand 라이브러리를 사용했다.

Zustand를 통해 Todo 더미데이터를 전역 상태로 구성한 후 이를 각 컴포넌트에서 렌더링하고 이 상태들을 변경할 수 있는 메서드들을 Zustand의 전역 상태에 작성한 후 필요할 때마다 호출해서 사용했다.

이를 통해서 Todo 리스트의 CRUD구현은 보다 손쉽게 작성할 수 있었다.

2 ) Todo 클릭 이벤트

Todo 클릭 이벤트를 통해서 Todo 컴포넌트를 클릭하면 해당 Todo가 완료됐음을 반영하여 사용자에게 표현해주고 싶었다.

이에 따라 선택한 에니메이션 과 표현은 다양한 Todo 리스트를 사용하면 볼 수 있는 가로줄로 선이 그어짐과 동시에 해당 컴포넌트의 색이 변하는 것이었다.

막상 간단할 것이라고 생각 했던 이 CSS 애니메이션이 생각보다 구현하기가 간단하지 않았다.

가로줄 (즉, 취소선)을 CSS로 에니메이트 할 수 없었기 때문이었다.

따라서 이러한 에니메이션을 어떻게 만들어야 할지 구글링을 통해서 발견해 적용함으로써 해결할 수 있었다.

구글링한 결과는 보더 버텀 라인만 보이도록 만들어진 빈 컴포넌트를 클릭할 때마다 크기를 늘렸다 줄였다 하면서 생성하는 것이었다.

예시로 작성된 CSS 코드를 살펴보면서 내 컴포넌트에 적절하게 반영될 수 있도록, 수정한 후 컴포넌트의 CSS에 반영해 주었다.

3 ) 드래그 앤 드랍

Todo 의 클릭 이벤트까지 구현하고 난 후 추가적으로 무엇을 구현하면 좋을까 하고 생각했을 때, 가장 먼저 생각난 것이 바로 드래그 앤 드랍 기능이었다.

상용되고 있는 대부분의 Todo 리스트 어플리케이션은 드래그 앤 드랍을 통해서 리스트 내용의 순서를 변경할 수 있기 때문이었다.

이를 구현하고자 마음 먹었을 때는 섹션 3 해커톤에서의 시간을 거의 다 쓰고 마무리 단계였기 때문에 스스로 생각해보는 시간을 충분히 가질 수 없어 급하게 구글링을 통해 방법을 찾았다.

해당 기능을 라이브러리를 통해 구현하게 될 경우 상황이 더 복잡해질 것 같았기 때문에 리액트와 바닐라 자바스크립트를 통해서 구현하는 방법을 찾았고, 이는 바로 Draggable 컴포넌트와 onDrag 이벤트 들을 사용해서 구현하는 것이었다.

먼저 Draggable 컴포넌트는 해당 컴포넌트의 자식 컴포넌트들에 대해 Drag 이벤트에 반응할 수 있도록 만들어준다.

이를 통해 컴포넌트가 Drag 이벤트에 반응하게 되면 onDrag 이벤트들을 통해 리스트내에서 그 컴포넌트가 위치하는 인덱스를 반환하게 만들어줄 수 있는데, 이 값을 가지고 전역 상태에 반영해주는 것으로 드래그 앤 드랍을 구현할 수 있었다.

추후 프로젝트를 더욱 진행하고 난 이후 프로젝트를 개발할 시간도 좀 더 있을 때 , 이전에 구현한 드래그 앤 드랍이 에니메이션을 통한 유저와의 상호작용이 부족함을 느꼈고 이를 개선할 수 있는 방안을 찾아 수정했다.

이를 통해 적용한 것이 드래그 앤 드랍 이벤트를 좀 더 시각적으로 보여줄 수 있는 기능을 제공하는 라이브러리인 React Beautiful DnD 라이브러리를 사용하는 것이었다.

기존에 적용 시켰던 방법과는 정말 다른 방법 (라이브러리가 정상적으로 동작하도록 라이브러리 개발자가 작성해둔 사용법) 을 사용했기 때문에 이를 반영하는 데에 많은 골치가 아팠던 기억이 난다.

또한 내가 이미 작성해두었던 컴포넌트 또한 더욱 복잡해진 상태였기 때문에 이를 적절하게 사용하기 위해서 쉴세 없이 구글링 했던 기억도 난다.

구현의 큰 골자는 라이브러리에 적힌 사용법과 크게 다르지 않으니 이를 참조하는 것이 좋겠다.

다만 상황에 따른 자잘한 버그가 많이 발생했기 때문에 이를 사용하면서 만난 버그들을 모아 추후 사용을 위해 에러노트를 작성해야할 것도 같다.

목표 4 ~ 9 )

목표 4 ~ 9 (수정된 드래그 앤 드랍 포함) 까지는 이후 스스로 남는 시간에 하나 하나 구현하려고 노력해본 부분들이다. 구현해 나가면서 시간적으로 심적으로 많이 부딪혔기 때문에 기능의 완성도 와 최적화 보다는 기능이 원하는 대로 동작한다는 사실을 위안 삼아가면서 기능 개발에만 집중했다. 언젠가 나중에는 완성도 있는 코드 구현을 할 수 있기를…

4) Navbar 구현

프로젝트를 확장해 감에 따라 페이지를 구분하고 이동해야 될 필요성을 느꼈고 navbar를 통해서 사용자가 이동하면서 사용하도록 만들어야겠다는 생각을 했다.

먼저 어플리케이션을 하나의 큰 컴포넌트로 두는 것이 아니라, 클라이언트 사이드 페이지 라우팅을 통해서 기능별로 분리해야했다.

이를 위해서 React Router Dom 을 사용해서 분리해서 라우팅 시켜주었다.

가장 먼저 사용자를 만나게 될 홈 페이지와 로그인 페이지 로그인 접속후 리스트 보드를 보여주는 리스트보드 페이지 이후 하나의 Todo 리스트에 들어가서 볼 수 있는 Todo 리스트 페이지까지 총 4가지를 추가해주어야 했다.

기능을 확장하면서 추가해주어야 할 것이 많았기 때문에 기존에 작성해두었던 Todo 리스트 대신 새로운 Todo 리스트를 만들게 되었다.

대신 기존에 만들어 두었던 Todo 리스트 컴포넌트는 사용자가 로그인하지 않아 유저 데이터가 존재하지 않아도 사용할 수 있도록 또 다른 페이지로 구분해 총 5가지 페이지로 어플리케이션을 구분했다.

Navbar 컴포넌트는 이 5가지 페이지로 자유롭게 이동할 수 있도록 도와주어야 했다.

따라서 Navbar에 필요한 RRD 링크 컴포넌트를 배치한후 어떠한 페이지에도 일괄적으로 존재하게 조치했다.

Navbar의 디자인 또한 고민이 많아 수정에 수정을 거친 부분이었다.

Navbar를 상단에 두어 헤더로 사용할 지 그렇지 않으면 좌측에 두어 사이드바로 활용할 지에 대해 어떠한 부분이 더 편리하고 보기에 좋을 지 생각해 보았을 때, 스크롤과 상관 없이 존재하는 것이 편의성을 올릴 수 있을 것 같아 좌측 사이드바로 구현하는 것으로 결정했다.

또한 PC를 기반으로 웹 어플리케이션을 기반으로 개발을 하고 있었기 때문에 넓은 랜드스케이프 화면을 채우기엔 Todo 기반 어플리케이션의 데이터 내용이 부족해 이를 적절하게 보충할 수 있는 사이드바가 더욱 적절해보였다.

처음에는 상호작용적인 부분의 욕심 때문에 Navbar를 마우스가 올라갈 때와 아닐 때를 구분해 접었다 폈다 할 수 있도록 구현했지만, 이는 필요 이상으로 이벤트에 반응하여 정신이 없게 만들었고 어플리케이션을 활용하는 부분에 있어서 페이지를 불안하게 만들었다.

디바운스를 통해 수정할 수 있었지만, 이것 저것 기능을 추가하여 더 복잡하게 하는 것 보다는 Navbar를 펼친 상태로 고정해두는 것이 비용을 절약할 수 있을 것 같아서 최종적으로 접히고 펼쳐지는 이벤트를 제거한 상태로 마무리했다.

5 ~ 6) Todo 리스트의 확장과 구글 로그인

드디어 이 토이프로젝트의 하이라이트에 도달했다.

이 부분이야 말로 이 토이프로젝트를 진행함에 있어서 가장 중요한 부분이었고, 중요한 만큼 정말 몸과 마음이 고생했던 부분이었다.

확장에 있어서 가장 중요한 키워드는 바로 풀스택 이라고 할 수 있을 것 같다.

즉, 클라이언트 - 서버 - DB 를 전부 개발해 Todo 리스트를 확장해 어플리케이션으로 작동할 수 있도록 만드는 것이었다.

(지금와서 생각해보면 정말 괜한짓을 한 게 아닐까 하는 생각이 들기도 하지만 원하는 대로 동작하는 모습을 보면서 조금 보람차기도 했고 복습을 한 번은 제대로 했구나 하는 생각이 든다.)

기존에 독학을 통해 Mongo DB(NoSql DB) - Mongoose(Object Document Modeling) - Express (Server) 를 통해 백엔드를 구성하는 방법을 스치듯 배운적이 있었는데 이 기억을 통해서 제대로 한 번 활용해보고 기억해두고 싶었다.

또한 DB를 활용해야만이 데이터를 의미있게 영구히 보관할 수 있었기 때문에 어플리케이션이라는 본질에 더욱 다가갈 수 있었기 때문이었다.

DB 작성하기

가장 먼저 해야했던 것은 DB를 작성하여 데이터를 보관할 저장소를 만드는 것이었다.

이전에 배우고 설치해두었던 Mongo DB 외에는 다른 선택지가 존재하지 않았기 때문에 이를 선택해 바로 진행했다. (또한 어플리케이션의 사용할 데이터 또한 JSON 형식으로 미리 기획해두었기 때문에 적절했다.)

실질적으로 DB를 구성하기 시작하면서도 굉장히 지식이 부족했고 사용법을 숙달하지 못했었기 때문에 고생길이 예약되어 있었다.

실제로 도큐멘트를 일일이 찾고 구글링하며 DB를 구현하기 위해서 몇 일간을 내리로 고생했던 기억이 떠오른다.

Mongo DB 만을 통해서 Node 내에서 Mongo 와 연결하여 사용할 수 있으나 이 방법보다 익숙했던 Object Document Modeling 라이브러리인 Mongoose 의 도움을 통해서 DB의 구조를 작성하고 데이터의 입출력을 진행했다.

Mongoose 내에 존재하는 다양한 메소드들을 통해서 그래도 비교적 쉽게(하지만 자료들을 일일이 찾아가면서 이해하고 테스트해보고 버그와 싸우는 과정은 마냥 쉽지는 않았던 것 같다…)개발할 수 있었다.

그렇게 DB에 저장해 사용할 데이터 구조는 다음과 같이 구성했다.

어플리케이션에 활용할 데이터 자체는 복잡하지 않았지만, 중첩된 자료형에 대해서 DB에서의 입출력을 효율적으로 하기 위해 다방면으로 깨지고 구르고를 정말 많이 했던 것 같다.

자료도 많지 않았고 있는 자료들 중에서도 어떠한 자료가 내게 적합한지를 판단하고 테스트하느라 고생했던 기억에 몸서리가 쳐진다..

결국, 이를 해결하기 위해서 중첩이 발생하는 각각의 데이터 마다 따로 Document Model을 만들어주었고 이를 저장하는 DB에서 Collection을 각각 마다 만든 후, 상위의 Collection의 해당하는 필드에 ID 값 만을 저장해둔 후 필요할 때마다 ID를 통해 데이터를 조회해 populate하는 방식으로 해결했다.

거치고 나서 생각하면 참 간단하고 직관적인 방식인데, 막혀있을 때는 왜 그렇게 생각이 나질 않았는지 모르겠다.

서버 작성하기

DB를 구성한 이후 그 다음 해야할 것은 DB에서 데이터를 받아 클라이언트에 전송해줄 역할을 맡을 서버를 작성하는 것이었다.

서버를 구성하기 위해서는 친숙한 express를 통해서 Node js 환경에서 구성해주었다.

서버의 구현에는 그래도 많은 어려움이 존재하지 않았어서 클라이언트의 연결과 API의 로직을 잘 구성하는 일들에 신경을 썼다.

그러나 서버의 구현에는 ‘이게 왜 안되고 오류를 뱉을까?’ 하는 상황들이 굉장히 많아서 HTTP 통신과 서버의 작동 네트워킹, CORS 등에 대해서 공부를 해야겠다는 필요성을 굉장히 많이 느꼈다.

이 중의 하나의 예로 로그인을 구현하는 과정에서 클라이언트를 리다이렉트 처리 해줘야할 부분이 존재했는데, 이 과정에서 CORS 설정을 분명히 해줬다고 생각했지만 클라이언트 상에서 계속해서 CORS 오류를 내뿜었다.

이 부분은 결국 로그인 로직을 다른 방법으로 작성하는 것으로 해결했으나 왜, 어째서 오류가 발생했는 지에 대해서 속 시원히 찾을 수 없어 아쉬움이 남는다.

또한 REST API에 대해서 공부를 하긴 했으나, 효율적으로 API의 틀을 미리 기획한 후 코드를 작성한 것이 아니기 때문에 구성이 엉망이라는 점이 또한 부족한 점이라고 할 수 있을 것 같다.

결국 서버와 백엔드를 구성 하면서는 아쉬움과 부족함이 절절히 남는 경험을 한 것 같다.

그래도 기능이 동작한다는 점에서 위로를 삼는다.

6 ) OAuth 2.0 과 구글로그인

이 토이프로젝트를 진행하면서 스스로 가장 구현해보고 싶었던 부분이 바로 구글 로그인 부분이었던 것 같다.

시작하기 전에는 이전에 과제로 주어진 Github 로그인을 경험해 본 터라 막연하게 쉽게 구현할 수 있을 것이라고 생각했는데, 막상 열어보니 정말 두 번째로 가장 고생한 부분이 아니었나 싶다.

우선 시작부터 갈피를 잡을 수 없어 굉장히 난감했다.

구글이 제공하는 API 들은 굉장히 다양하고 종류가 많았기 때문에 이를 적절히 찾는 것도 쉽지 않았다.

또한 이 API와 Authorization을 사용하기 위해서 계정을 등록하고 설정해주어야 하는 부분도 단계가 낯설고 복잡해 제대로 설정하기 까지 반복을 여러번 요구했다.

결국 구글의 Authorization 가이드 라인을 따라서 구글로그인을 위한 사전 과정을 마친 후 구글로그인 컴포넌트를 만들고 데이터를 주고받았다.

그러나 Auth Code 와 Access Token 을 주고 받는 데까지는 성공했으나 정작 중요한 로그인처리에 필요한 데이터들에 접근할 수 없었고 로그인 후 에 리다이렉트 과정을 실행할 수 없었다.

이는 OAuth 2.0 에 대해 개념을 잘못 잡고 로그인 과정을 잘못 구현한 것이 문제였다.

따라서 OAuth 2.0 에 대해 과정을 정리해보고 기억해보고자 한다.


  1. 개발자는 Client 에서 로그인 페이지(Auth code를 전달받을)를 미리 구성한 후, 로그인 버튼 등을 통해서 OAuth 2.0 시도를 보낼 서비스에 HTTP Post 요청을 서비스가 요구하는 Client Key 와 Secret 등을 포함해 요청을 보낸다.
  2. 서비스는 Client 에서 온 요청을 받아, Post 요청으로 온 데이터를 개발자가 사전에 등록해 놓은 정보와 비교하고 일치할 경우 Client를 자사의 로그인페이지로 Redirect 시킨다.
  3. 사용자가 로그인 시도 후 성공할 경우 서비스는 Auth Code를 URI parameter에 포함시켜 Client를 다시 개발자가 미리 서비스에 등록해놓은 Redirect URI로 이동시킨다.
  4. Client는 URI 에 포함된 Auth Code를 추출해 내어 자신의 서버에 Post요청으로 전달한다.
  5. 서버는 전달 받은 Auth Code를 통해 서비스가 요구하는 Token URI에 Access Token 요청을 보낸다.
  6. 서버가 Access Token 을 성공적으로 전달받으면 이제 서비스의 API를 통해서 데이터를 이용할 수 있는 권한을 얻는다.
  7. 개발자는 이 Access Token 을 활용해서 Login 과정을 구현한다.

이 과정을 성공적으로 구현하자, 거짓말 처럼 원하는 대로 데이터를 받아오고 동작하기 시작했다.

나는 Access token 을 이용해 Google의 People API 서비스를 통해 유저의 이름과 이메일 정보를 통해 커스텀 회원가입을 구현하고 이를 바탕으로 Login을 구현했다.

이 과정에서 email 정보는 중복되지 않는 다는 점을 사용해, DB 에서 유저를 조회할 수 있는 유저 ID로써 email을 사용했다.

그리고 Login 정보를 1~3) 에서 사용된 Zustand (이번에는 session storage를 활용한다.) 를 다시 활용해 전역상태에 저장해 필요할 때마다 모든 컴포넌트에서 접근할 수 있도록 했다.

추가적으로 Google에서는 Google Identity Service라는 서비스를 최근에 제공하기 시작하면서 이러한 Authorization 과정을 보다 손쉽게 활용할 수 있도록 Javascript / HTML API를 제공하고 있다.

이를 통해서 구글이 제공하는 편의적인 기능(로그인 기능을 담은 버튼을 생성 해주는 함수도 존재한다.)과 함께 로그인 서비스를 편하게 구현할 수 있다.

하지만 GIS에서 제공하는 로그인 버튼이 Iframe으로 구현되어 기존에 작성해두었던 디자인적인 부분에서 충돌을 일으켜, 다른 라이브러리를 사용해 커스텀 버튼으로 구글 로그인을 구현했다.

7 ~ 9 ) Todo 리스트에서 다양한 정보표시와 상호작용하기

AJAX 와 Tanstack Query

이제 다른 부분들이 준비가 되었으니, 본격적으로 데이터를 전달 받아 클라이언트에서 목적에 맞게 구현하는 부분이 남았다.

많은 부분은 1~3) 과정에서 작성해둔 로직들을 바탕으로 서버로부터 전달받은 데이터를 활용하는 형식에 맞게 수정하고 적절하게 CSS를 추가하면 되었다.

관건인 부분은 이제부터 서버로 렌더링에 필요한 데이터를 그때 그때 받아오기 때문에, 비동기통신을 적절하게 활용해야하는 점이었다.

이를 위해서 클라이언트에서 CRUD에 사용되던 로직을 떼내어 분리하고 이 로직을 서버로 옮겨 DB와 수행하게 만든 후, 클라이언트에서는 유저의 상호작용에 적절하게 HTTP 요청을 보내도록 수정해야 했다.

Ajax 통신을 보다 효율적으로 사용하기 위해서는 반복되는 로직을 분리해 커스텀 훅을 작성하거나 하는 방법이 존재하겠지만, 나는 이러한 부분에서 굉장히 편리하다는 평이 자자한 React Query (현 Tanstack Query)를 공부하고 사용해보며 익숙해져보기로 했다.

그리고 사용해보면서 왜 다들 그렇게 호평하며 사용하는지 이해하게 되었다.

Tanstack Query는 직관적인 기능과 사용법으로 클라이언트에서 Ajax 요청을 수행할 수 있도록 보조해준다.

Tanstack Query는 Tanstack Query내에서 효율적으로 Ajax에 활용할 수 있도록 미리 작성해둔 커스텀 훅을 제공하는데, 사용자는 이를 이용해서 HTTP 통신에 사용하면 되는 것이다. (직접적인 HTTP 통신에는 Axios 라이브러리를 사용했다.)

이 커스텀 훅을 통해서 서버로부터 필요한 데이터를 그때 그때 받아오거나 전달하거나 하면서 서버와 상호작용하며 CRUD를 재구현할 수 있었다.

...

서버에서 DB에 저장되어있는 데이터에 대해 CRUD를 위해서는 mongoose의 메소드들을 최대한 활용할 필요가 있었다.

mongoose에는 create, findById, findByIdAndUpdate, findByIdAndRemove 등 CRUD를 위한 기본적인 메소드들이 마련되어 있는데 이를 최대한 활용했다.

기본적인 데이터의 query는 mongo DB가 도큐먼트(collection에 저장되는 데이터 단위)에 자동적으로 부여하는 유니크한 Object Id를 통해서 조회하는 방식을 사용했다.

도큐먼트가 중복되는 사항을 데이터에 가질 수 있었기 때문이다.

신경써주어야 했던 점은, DB관련 메소드들을 사용할 때는 서버도 DB와 ajax 통신을 통해 명령을 주고받기 때문에 모두 async 처리를 해주어야 했다는 점이다.

또 하나 신경써야 했던 점은 삭제 부분이었는데, 사용하는 데이터의 구조가 중첩된 형태를 가지고 있었기 때문에 (상위 계층에는 하위 계층의 직접적인 데이터 대신 관련된 Object Id를 저장했다.) 하위 계층의 데이터가 삭제된다면 상위 계층에 존재하는 참조 데이터를 모두 삭제해야 했다는 점이었다.

이는 filter 메소드를 사용해 Object Id가 일치하는 부분만 삭제하고 새로 만든 배열을 할당하는 방식으로 구현했다. (다만, Object Id가 String 형태가 아닌 Object 형식을 가지고 있었기 때문에 이를 String으로 변환하기 위해서 toHexString 메소드를 사용해야 했다.)

Taskboard 구현과 Chart JS

태스크보드라는 간단한 통계와 진행 상황을 그래프와 함께 사용자에게 전달할 수 있는 부분이 존재했으면 좋겠다는 생각에서 진행했다.

이를 구현하기 위해서는 Todo 데이터가 변화함에 따라서 동적으로 변화하는 그래프를 구현할 필요가 있었는데 이는 Chart js 라이브러리를 활용함으로 구현할 수 있었다.

Chart js 의 사용방법은 그렇게 복잡하지 않은, 라이브러리에 존재하는 준비 된 차트를 생성하는 클래스 함수에 데이터를 전달하는 방법으로 사용할 수 있었다.

다만, React에 적절한 방식으로 사용하기 위해서 추가적으로 react-chartjs-2 라이브러리를 사용해 도움을 받았다.

todo 데이터의 선택적 정렬

가장 마지막으로 구현을 시도한 부분이 동적으로 정렬기준을 변경해 사용자에게 데이터를 보여주는 부분이었다.

문제가 되었던 부분은 바로 서버로부터 그때 그때 fetching 해오는 데이터를 컴포넌트의 상태에 저장해놓고 정렬 기준에 맞게 재정렬 시켜주어야 한다는 점이었는데, 이 부분에서 항상 일정한 형태를 갖고 DB로 부터 전송되어지는 데이터를 어떠한 방식으로 재가공할 것인가의 문제였다.

당시 시간의 부족해 많은 방식을 고민 해보는 시간이 부족해 단순히 컴포넌트가 재 렌더링 될 때마다 데이터를 fetching 해오지만 기준이 default가 일 경우에만 상태에 업데이트 되도록 하고 그렇지 않을 경우, 이미 저장되어 있는 데이터를 활용해 재가공해 업데이트 하는 비효율적인 방식으로 구현했다.

회고하면서 떠오르는 생각은 이를 데이터에서 DB에서 데이터를 query하는 동안 해결하면 어땠을까 혹은 data fetching의 체이닝 함수 단에서 데이터를 재 가공하면 어땠을까 하는 생각이 든다.

10 ) 어플리케이션의 디자인과 CSS

이 부분에서 굉장히 많은 고민과 시행착오가 존재했던 것 같다.

CSS는 어플리케이션의 개발을 진행해나가면서 계속해서 신경써주어야 하는 부분이었는데, 이를 만족스러운 방식으로 해결하지 못했던 것 같기 때문이다.

나는 이 토이프로젝트에 utility first 방식을 사용하는 Tailwind 라이브러리로 CSS를 적용했다.

프로젝트가 가볍기도 했고, CSS를 즉각적으로 손쉽게 작성하고 결과물을 확인할 수 있다는 점이 효율적으로 다가왔기 때문이었다.

그러나 프로젝트가 진행되어 가는 동안 이것이 올바른 방식이 맞을까 하는 생각이 계속해서 들었다.

컴포넌트가 커지고 적용되어지는 CSS가 다양해질 수록 컴포넌트의 HTML은 점차 알아보기 힘든 상태로 변하기 시작했고, 특별한 컨벤션을 정해놓고 코드를 작성한 것이 아니었기 때문에 컴포넌트들마다 그때 그때 마다 필요한 방식대로 클래스 네임이 적용되어 어떠한 CSS가 적용되었는지 파악하는데 시간이 필요했다.

또한 CSS의 재활용에 있어서도 계속해서 긴 클래스 네임 리스트들을 전부 작성해주어야 했기 때문에 굉장히 떨어지는 듯한 느낌을 받았다.

이 부분에 있어서는 Tailwind에 대한 공부가 충분히 되지 않았기 때문에 효율성을 최대한 뽑아내지 못했기 때문이라는 생각이 들기도 한다.

다음 번에 있어서는 비록 조금 코드를 무겁게 만든다고 하더라도 Styled Component를 활용하여 CSS를 최대한 효율적으로 작성해보고 싶다는 생각을 했다.

4 ) 느낀 점 / 개선할 점

profile
반갑습니다! 오늘도 좋은 하루 입니다🙋🏻‍♂️. 프론트엔드 개발을 공부하고 있습니다!

0개의 댓글