![[우주윗미] 코드잇 스프린트 심화 프로젝트 회고](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe3vde%2FbtsJsx6VRtw%2Fd45RTqHeYv83Gqmbr8WR50%2Fimg.png)
- 시작하며...
- 프로젝트 선정
- 아쉬웠던 점
- 프로젝트 선정 이유
- 프로젝트 네이밍
- 프로젝트 초기 세팅
- 스타일 초기 세팅
- 스토리북 Chromatic 배포
- 기술스택
- Next.js - App Router
- App Router
- TypeScript
- Tailwind CSS
- TanStack query
- Jotai
- Storybook
- React Hook Form
- Zod
- 공통 컴포넌트 만들기
- 고려할 점
- Form 관련 공통 컴포넌트
- Input 컴포넌트
- FieldWrapper 컴포넌트
- DropDown 공통 컴포넌트
- Toast 공통 컴포넌트
- 페이지 구현
- 1. 팀 페이지
- 1-1. 데이터 패칭
- 1-2. 멤버 초대 / 추방(탈퇴) / 메일 보내기
- 1-3. 할 일 목록 리팩토링
- 2. 팀 생성 / 수정 / 참여
- 2-1. 팀 생성 / 수정
- 3. 모집 게시판 목록
- 3-1. 무한 캐러셀 컴포넌트 구현
- 3-2. 검색창
- 3-3. SSR + TanStack Query
- 3-4. search param 값에 따른 URL
- 3-5. 페이지네이션
- 4. 게시물 상세
- 4-1. SSR + TanStack Query
- 4-2. 토큰
- 4-3. 게시물 좋아요 옵티미스틱
- 4-4. 댓글 무한 스크롤
- 4-5. 댓글 작성 중
- 4-6. 세션 스토리지 사용하여 목록으로 가기
- 5. 게시물 작성 / 수정
- 베타 테스트
- 진행 이유?
- 피드백 방식
- 피드백 반영
- 게시물 조회수 기능
- 캐러셀이 슝 날라가는 현상
- KPT 회고
- 팀 회고
- K- Kepp
- P - Problem
- T - Try
- 개인 회고
- K - Keep
- P - Problem
- T - Try
- 피어리뷰
- 마치며...
시작하며...
드디어 코드잇 스프린트의 마지막 프로젝트인 "심화 프로젝트"를 마쳤다.
이번 프로젝트는 이전 프로젝트들과 달리 약 6주간 진행되었고, 지난 기간을 돌아보며 프로젝트를 구현하는 동안 나는 어떤 고민과 결정을 거쳐 프로젝트를 완성했는지 정리하기 위해 회고를 작성하게 되었다.
프로젝트 깃허브 링크 https://github.com/sprint6-part4-team3/WouldYouWithMe
GitHub - sprint6-part4-team3/WouldYouWithMe: 팀원을 모집하여 함께 스터디 투두리스트 관리하는 서비스
팀원을 모집하여 함께 스터디 투두리스트 관리하는 서비스. Contribute to sprint6-part4-team3/WouldYouWithMe development by creating an account on GitHub.
github.com
프로젝트 선정
아쉬웠던 점
처음부터 아쉬움을 이야기하긴 좀 그렇지만...^^
원래 심화 프로젝트는 백엔드와 디자이너와 함께 진행하는 방식이었으나, 5기부터 기초와 중급 프로젝트처럼 주어진 피그마 시안과 스웨거 문서를 기반으로 구현하는 형식으로 바뀌게 되었다.
하지만 프로젝트를 진행하면서 팀원들과 컨셉을 좁혀 나가, 같은 프로젝트라도 우리 팀만의 특색이 드러나는 결과를 만들면서 점점 만족스러워졌다.
프로젝트 선정 이유
이번 프로젝트는 총 4가지가 주어졌는데,
난이도가 있는 프로젝트를 하고 싶어 "Coworkers"와 "Global Nomad" 중 고민을 많이 했다.
그러나 "Global Nomad"는 이미 이전 기수에서 많이 다뤘던 프로젝트였기 때문에, 이번에 새로 추가된 "Coworkers"가 더 마음에 들었다.
중급 프로젝트 회고에서도 이야기했듯이, 적은 인원으로도 서비스가 활성화되어야 유지가 쉽다는 점을 고려했을 때,
"Coworkers"는 팀 단위뿐만 아니라 개인도 사용할 수 있는 "투두 리스트" 관리 서비스로 유지 가능성이 높고, 기술적으로도 도전할 부분이 많아 보이는 프로젝트로 팀원들과 회의 끝에 최종적으로 "Coworkers"를 선택했다.
프로젝트 네이밍
프로젝트의 네이밍을 정하는게 처음에 어려웠다. (내가 의견 몇 개 냈는데 기각 당함ㅋㅋㅋㅋㅋㅋㅋㅋ)
팀원들과 자유롭게 대화하다가 "우주 컨셉"을 떠올리게 되었고, 재혁님이 제안한 "우주윗미 (Would You With Me)" 가 팀원 모두 마음에 들어 동의했다.
또한 기존의 "투두 리스트" 서비스에서 "스터디 투두 리스트" 로 주제를 변경하며, 자유게시판도 "모집 게시판"으로 바꾸는 방향으로 기획을 구체화했다.
"우주윗미" 라는 이름 덕분에 프로젝트가 "우주 컨셉" 과 "스터디 투두 리스트" 라는 우리 팀만의 독특한 색깔을 갖게 되었고, 덕분에 프로젝트에 더 큰 애정을 가지고 열심히 임할 수 있었다.
그리고 중급 프로젝트와 마찬가지로 이번에도 내가 서비스의 로고와 썸네일을 제작하게 되었다.

프로젝트 초기 세팅
다른 프로젝트와 다르게 6주간 진행되는 프로젝트로 초기 세팅을 탄탄하게 했다.
팀원 모두 기초 및 중급 프로젝트에서 사용한 컨벤션이나 ESLint 설정을 공유하여, 가장 유용했던 것들만 가져와 프로젝트 환경을 구축했다.
특히 ESLint 와 Husky 를 잘 설정해 덕분에 프로젝트 진행 내내 코드 컨벤션을 준수하며 코딩할 수 있었다.
그동안 프로젝트와 비교했을 때, 이번 프로젝트의 다른 점은 "네이밍 컨벤션" 인 것 같다.
파일명을 "케밥 케이스" 로 작성하게 되어서 파일을 쉽게 찾고 구분할 수 있어 편했다.
스타일 초기 세팅
이번 프로젝트에서는 내가 스타일 초기 세팅을 담당하게 되었고 Tailwind CSS 를 사용하게 되었다.
피그마 시안에 맞게 "타이포그라피", "색상", "폰트" 를 적용하였다.
그런데 좀 다른 점이 있다면 바로... "pxr" 단위를 도입하게 되었다.
해당 단위는 멘토님이 추천해 주신 단어이고, 팀원분이 관련 아티클과 라이브러리 주소를 공유해 주셔서 "pxr" 을 적용하게 되었다.
"pxr" 적용 관련된 내용을 https://jjang-j.tistory.com/150 에서 확인할 수 있다.
[Tailwind] px 작성, 자동 rem 변환 (feat. pxr 단위)
시작하며...Tailwind CSS 를 사용하면 기본적으로 rem 단위로 동작한다. 만약 조금 더 섬세하게 px 단위로 크기를 조절하고 싶은 경우에는 아래 코드처럼 사용하게 된다. 그런데 개발자 도구에 들
jjang-j.tistory.com
스토리북 Chromatic 배포
이번에 프로젝트에서 공통 컴포넌트를 만든 후, 스토리북을 작성하기로 했다.
그런데 PR 을 올렸을 때, 바로 스토리북을 확인하지 못하면 굳이 스토리북을 사용할 이유가 없고 결과를 확인하기 위해 매우 번거로운 작업을 수행해야 된다.
그래서 이를 해결하기 위해 Github Action 을 사용하여 스토리북을 Chromatic 으로 PR 을 올릴 때마다 배포하였다.
Github Action 을 사용하는 작업은 여러 번 해봤지만, PR 에 계속 Push 를 할 때마다 커멘트가 달리는 현상이 있어 가독성 측면에서도 별로고 PR 이 조금 지저분해지는 기분이 들었다.
그래서 이번에는 "comment_tag" 를 사용하여 PR 한 개당 하나의 커멘트만 달리고 하였고, 추가적으로 배포된 시각을 추가하여 언제 업데이트되었는지 확인할 수 있게 하였다.
이게 진짜 자동화고 개발 효율을 향상됨을 몸소 느끼게 되었다.
나뿐만 아니라 팀원분들도 컴포넌트 개발할 때도 매우 유용하고 편리하다고 했다. (뿌듯 😊)
스토리북을 Chromatic 으로 배포한 내용은 https://jjang-j.tistory.com/138 여기서 확인할 수 있다.
[GitHub Action / Chromatic] 스토리북 PR 미리보기 배포 (feat. yarn)
시작하며...이번 프로젝트에서 Storybook 을 사용하게 되었다. 그런데 예를 들어 공통 컴포넌트를 만들고 Storybook 을 작성한 후 Pull Request 를 올렸을 때, 리뷰어들을 Storybook 에 반영된 것을 시각적으
jjang-j.tistory.com
기술스택
이번 프로젝트에서는 크게 Next.js - App Router, TypeScript, Tailwind CSS, TanStack Query, Jotai, Storybook, React Hook Form, Zod 등을 사용하였다.
Next.js - App Router

지난번과 동일하게 이번에도 Next.js 를 사용하게 되었다.
Next.js 를 사용하면 파일 기반 라우팅이라 React 처럼 React-Router-Dom 이런 라이브러리를 사용하지 않고 간편하게 라우팅을 할 수 있다. 그 밖에도 Server Sider Rendering 이 가능해 로딩 속도도 개선이 되고 SEO 에도 좋은 프로젝트를 만들 수 있다.
그런데 지난번과 다른 점이 있다면 이번에는 Page Router 대신 최신 버전인 App Router 를 사용하게 되었다.
App Router
프로젝트 기간이 거의 3배나 증가했고 규모도 전보다 커지며 프로젝트가 복잡하다.
그래서 대규모 프로젝트에 적합하며 많은 기능과 유연성을 제공하는 App Router 를 선택하게 되었다. (대규모까진 아니지만...)
사실... App Router 가 아직 안정화되지 않아 오류가 많다는 소문을 들어 조금 두려웠다. 하지만 실제로 사용해 보니깐 그렇게 오류가 많이 발생하지도 않고 App Router 의 유용한 기능을 사용하면서 수월하게 개발했던 것 같다.
아무튼 만족도는 높고 이번 기회에 App Router 를 사용해 볼 수 있어서 학습적인 측면에서 매우 만족스러웠다!
TypeScript

TypeScript 는 국룰이다.
중급 프로젝트 회고에서 TypeScript 좋았던 점을 작성했어서 자세한 내용은 패스하겠다.
아무튼 최고 ٩( ᐛ )و
Tailwind CSS

저는.. Tailwind CSS 에 사랑에 빠졌습니다..... 😍
그동안 module CSS, SCSS, Emotion, Styled Components 를 사용해 봤는데, 그중에서 Tailwind CSS 가 나한테 1위다 🥇
지난번에 이어 이번에도 Tailwind CSS 를 사용하게 되었는데 역시나 간편하고 빠르게 개발할 수 있었고 커스터마이징이 용이했다.
또한 이번에는 "스타일 초기 세팅" 에서 언급한 "pxr" 단위를 사용해서 지난번에 겪은 불편한 점을 해소하게 되었다. 아무튼 최고 🙌
TanStack query

코드잇 강의에서 배운 서버 상태 라이브러리인 TanStack Query 를 이번 프로젝트에 적용하게 되었다.
TanStack Query 에서 제공해 주는 다양한 hook 과 기능을 통해 데이터 요청을 간편하게 할 수 있고 서버 상태 라이브러리답게 서버의 상태를 관리할 수 있어 서버에서 가져온 데이터를 캐싱하고, 캐싱한 데이터를 가져올 수도 있는 유용한 라이브러리이다.
사실 난 TanStack Query 는 이번 프로젝트 포함해서 3번 사용해 보았지만 사용할 때마다 매번 새로운 hook 과 기능을 사용하게 되었다.
(그만큼 기능이 많고 유용하다는 뜻)
첫 번째 프로젝트에서는 단순하게 useQuery, useMutation 을 사용하였고,
두 번째 프로젝트에서는 useSuspenseQuery, 쿼리초기화, stale time 을 적극 사용하였고,
이번엔 useInfiniteQuery, 옵티미스틱 업데이트, prefectQuery, enabled, placeholdeerData 등을 사용하였다.
개발의 효율성도 높아주고 현업에서도 자주 사용되는 기술로 이를 활용하고 적용할 수 있어 만족스러웠다.
Jotai

이번엔 상태 관리 라이브러리 중에서 Jotai 를 사용하게 되었다.
지난 프로젝트에서는 러닝 커브가 낮고 다운로드 수가 많은 Zustand 와 Jotai 중에서 고민을 하여 결국 Zustand 를 선택하게 되었다.
그러나 Zustand 의 Persist 를 사용했을 때, hydration 에러가 발생하였고 구글링 하여 문제를 해결했던 경험이 있었다.
그래서 Next.js 에 좀 더 친화적인 라이브러리를 사용하고 싶다 생각했었고, 마침 Jotai 공식문서에 Next.js 탭이 따로 있는 것을 발견하였고 Zustand 보다는 문제없이 잘 사용할 수 있을 거 같았다.
예상대로 Persistance 를 사용했을 때 아무런 문제 없이 잘 사용하게 되었다.

Storybook

이전 프로젝트에서는 공통 컴포넌트를 만든 후 '/test/1' '/test/2' 이렇게 새로운 페이지를 일일이 만들어서 컴포넌트를 테스트하고 다른 사람이 확인할 수 있게 하였다.
하지만 이렇게 페이지를 만드는 과정은 번거로웠다. 🥲
그래서 코드잇 강의에서 잠깐 배운 Storybook 을 도입하게 되었다.
Storybook 을 통해 개별 컴포넌트의 테스트를 간편하게 할 수 있고 문서화하여 컴포넌트를 한눈에 확인할 수 있었다.
또한 위에 "스토리북 Chromatic 배포" 에서 나왔던 것처럼 PR 을 올릴 때 커맨트로 배포 주소를 바로 확인할 수 있어 이점을 극대화하였다.


React Hook Form

폼의 상태 관리를 간편하게 하기 위해 React Hook Form 라이브러리를 사용했다.
이번 프로젝트에서 특히 입력 폼으로 받는 부분이 많아 React Hook Form 을 사용하여 폼 관리 하는데 유용했다.
특히 React Hook Form 의 FormProvider 를 사용하여 폼의 값을 상태 관리하여 prop drilling 을 해결할 수 있었고 복잡성을 개선할 수 있었다.
(웃긴 얘기지만 예전에 입력받을 폼의 내용이 많아서 이를 상태 관리하고 싶어 Recoil 을 사용했던 경험이 있었다.)
Zod

React Hook Form 을 사용하여 폼의 유효성 검사를 할 수 있지만 Zod 를 사용할 경우 타입 안정성과 정밀한 유효성 검사를 수행할 수 있었다.

공통 컴포넌트 만들기
이제 본격적으로 개발 얘기다...
고려할 점
팀 프로젝트를 하면서 가장 먼저 개발해야 되는 것이 바로 "공통 컴포넌트" 라고 생각이 든다.
"공통 컴포넌트" 를 만들었을 때, 다음과 같은 이점들이 있다.
- 재사용성 향상
- 유지보수성
- 일관성 있는 UI/UX
- 코드 관리 용이
- 팀 협업 효율성
이전 회고에서 언급했다시피 옛날에 "공통 컴포넌트" 를 만들어 두지 않고 작업한 결과, 코드의 길이도 길어지고 UI 수정하는 것도 하나하나씩 수정했었고, 같은 컴포넌트가 2개 이상 있었었다...ㅋㅋㅋㅋㅋㅋㅋ
직접 경험해 봄으로써 "공통 컴포넌트" 의 중요성을 제대로 깨닫게 되었다.
아무튼 나는 이번에 "공통 컴포넌트" 를 만들면서 다음 원칙을 고려하면서 개발하였다.
- 단일 책임의 원칙
- 재사용성
- 확장성
멘토님께서 "공통 컴포넌트" 를 최대한 도메인의 성격을 제외하여 "UI 라이브러리" 를 만드는 것처럼 하라고 조언을 받았다.
Form 관련 공통 컴포넌트

최대한 여러 곳에서 유용하게 사용하면 좋을 거 같아 단순히 Input 컴포넌트만 만든 것이 아니라, ErrorMessage, FieldWrapper, Textarea 컴포넌트도 만들었다.
피그마 시안에 label 이 없는 부분도 있어 최대한 컴포넌트를 분리하고 컴포넌트끼리 조합하여 사용할 수 있게 구현하였다.
Input 컴포넌트

input 태그의 기본 요소 속성을 상속받아 props 에 없는 input 의 속성을 사용할 수 있게 되어 재사용성과 확장성을 높였다.

React Hook Form 의 register 를 사용하여 폼 요소에 접근하게 해 주는데, register 가 폼 요소에 ref 를 할당하기 때문에 "forwardRef" 를 사용하여 ref 를 전달받아 사용할 수 있도록 했다.
FieldWrapper 컴포넌트

form 입력의 label 와 errorMessage 를 담은 컴포넌트이다.
이를 통해 각 폼 필드마다 동일한 스타일과 구조를 적용할 수 있어 일관성이 향상되고, 각 폼 필드를 감싸게 되어 가독성도 높아진다.
DropDown 공통 컴포넌트

"DropDown" 컴포넌트를 "컴파운드 패턴"을 사용하여 구현하였다.
"DropDown" 컴포넌트가 사용 사용되는 컴포넌트가 최대한 효율적으로 구현할 수 있는 방법이 없을까? 고민을 하다가 "컴파운드 패턴" 을 도입하게 되었다. (이번 프로젝트에서 무려 11개 파일에서 사용됨)
"컴파운드 패턴" 을 사용하게 되니깐 유연성, 가독성, 역할 분담, 유지보수성 등 다양한 장점이 있어 유용했다.
구현 과정에 대한 내용을 https://jjang-j.tistory.com/131 에서 확인할 수 있다.
DropDown 컴파운드 패턴으로 공통 컴포넌트 구현하기
시작하며...이전 프로젝트에서 Menu 와 DropDown 컴포넌트를 구현하였다. 그러나 공통 컴포넌트라는 성격과 거리가 멀었다. 그래서 이번 프로젝트에서 DropDown 공통 컴포넌트를 범용성이 좋게 만들
jjang-j.tistory.com
Toast 공통 컴포넌트

Jotai + Tailwind CSS 를 사용하여 "Toast" 컴포넌트를 구현하였다.
사실 편하게 라이브러리를 사용해도 되지만 한 번 구현해보고 싶어서 구현했다. 물론 나 스스로 구현한 게 아니라 구글링 해서 이것저것 참고해서 만든 것이다.
원래 Framer Motion 을 사용해서 구현했는데 모바일에서는 "Toast" 가 깜박거리는 이슈가 있었다. 아마 성능 문제였던 것 같아서 Tailwind CSS 로 애니메이션을 구현하여 문제를 해결하였다.
또한 Lottie 를 사용하여 동적인 Icon 으로 사용자 경험성도 향상시켰다.
페이지 구현
나는 이번 프로젝트에서
"팀 페이지", "팀 생성 / 수정 / 참여", "모집 게시판 목록", "게시물 상세", "게시물 작성 / 수정" 페이지를 맡게 되었다.
칸반보드 형식으로 진행되었는데 내가 작업 속도가 빨라 이것저것 맡게 되었다.
그러다 보니 해당 페이지를 잘 이해하고 있어 이를 가지고 추가적인 기능과 효율적인 유저 플로우를 구상할 수 있었던 거 같다.
1. 팀 페이지

내가 구현한 기능 중 설명할 내용은 다음과 같다.
- 데이터 패칭: SSR + TanStack Query + loading.tsx
- 멤버 초대 / 추방(탈퇴) / 메일 보내기
- 할 일 목록 리팩토링
1-1. 데이터 패칭
다른 팀원분이 데이터 패칭을 CSR 을 사용해서, 내가 SSR + TanStack Query 사용해서 패칭 하도록 리팩토링 하였다.
SSR 을 사용하여 초기 로딩 속도를 개선했고, TanStack Query 를 사용하여 stale time 을 60초로 설정했기 때문에 캐싱된 데이터를 사용하여 사용자 경험성을 향상시킬 수 있었다.
그리고 "할 일 목록" "멤버" 이런 내용으로 인해 팀 페이지 데이터가 바뀌는 경우가 생기는데 이때 데이터를 다시 서버에서 받아와야 하므로 TanStack Query 의 쿼리 초기화를 이용하였다.
또한 Next.js App Router 에서 제공하는 loading.tsx 를 사용하여 SSR 를 통해 서버에서 패칭 하는 동안 로딩 화면을 보여줘 이 또한 사용자 경험성을 향상시킬 수 있었다.
1-2. 멤버 초대 / 추방(탈퇴) / 메일 보내기



멤버 초대 토큰을 복사한 후, 바로 모집 게시판에서 토큰을 가지고 게시물을 작성할 수 있도록 하였다.
본인이 관리자면 나를 제외한 다른 멤버를 추방할 수 있고, 본인이 일반 멤버이면 본인만 탈퇴할 수 있도록 했다.
그리고 추방(탈퇴) 하기 전에 닉네임을 한 번 더 입력받아 실수를 방지하였다.
원래 이메일 복사 기능이었는데, 딱히 사용되는 곳이 없어 이메일 보내기로 수정했다.
1-3. 할 일 목록 리팩토링
팀원분이 CSR 로 구현하셔서 TanStack Query 로 사용하고, 쿼리 초기화를 하여 새로 업데이트된 데이터를 받아오게 하였다.
그리고 드래그앤드랍 기능에서 즉각적으로 데이터가 반영돼야 하기 때문에 TanStack Query 의 setQueryData 를 사용하여 리팩토링 하였다.
2. 팀 생성 / 수정 / 참여
폼에 관련된 내용이라 대단한 기능은 딱히 없다.
- React Hook Form 으로 폼 관리
- Zod 로 유효성 검사
2-1. 팀 생성 / 수정

React Hook Form 의 FormProvider 를 사용했기 때문에 컴포넌트를 입력마다 분리하여 간편하게 폼을 관리할 수 있도록 하였다.
특히 팀을 생성하고 수정하는 컴포넌트를 같이 사용하기 위해 React Hook Form 의 "watch" 를 사용하여 컴포넌트를 재사용하였다.

무분별한 버튼 클릭을 막기 위해 로딩 중일 땐 버튼을 disbaled 하고 로딩스피너를 사용하여 사용자의 경험성을 향상시켰다.

3. 모집 게시판 목록

피그마 시안과는 완전 다르게 만들었고, 구현한 기능은 다음과 같다.
- 무한 캐러셀 컴포넌트 구현
- 검색창
- SSR + TanStack Query
- param 값에 따른 url
- 페이지네이션 구현
3-1. 무한 캐러셀 컴포넌트 구현
중급 프로젝트 회고에 아래와 같은 내용을 작성했었다.

그래서 이번엔 라이브러리 없이 캐러셀을 직접 구현하게 되었고 자세한 내용은 https://jjang-j.tistory.com/157에서 확인할 수 있다.
[Next.js] 무한 캐러셀 컴포넌트 직접 구현하기 (feat. Tailwind CSS)
시작하며...지난 기초, 중급 프로젝트에서 캐러셀을 라이브러리를 사용하여 구현하였다. 그때 회고를 보면 나중에는 라이브러리가 아닌 직접 구현해보고 싶다고 글을 적었었다.그런데 마침 이
jjang-j.tistory.com
3-2. 검색창
특별한 기능은 아니지만, HTML 의 특징을 사용하여 구현하였다.

3-3. SSR + TanStack Query
초기 백엔드 응답 속도가 느린 이슈가 있었다.
그래서 사용자 경험성 향상을 위해 TanStack Query 로 구현하고(CSR) 스켈레톤을 보여줬다.
그러나 그 이후에 백엔드 서버가 개선되어서 응답 속도가 빠른데 스켈레톤 UI 를 보여주는 것이 어색하여 placeholderData 를 사용하여 데이터가 새로 요청되기 전에 이전 데이터를 보여주어 사용자 경험성을 향상시켰다.

프로젝트를 마치고 Lighthouse 로 성능 측정을 하였는데 69점이라는 낮은 점수가 나왔다.
결과를 보니 LCP 가 낮았고, 즉 렌더링이 되는 속도가 느리다는 뜻이었다.

그래서 이를 개선하기 위해 SSR + TanStack Query 를 도입하여 초기 렌더링 속도를 향상 시켰다.
(추가적으로 접근성도 일부 향상시킴)

3-4. search param 값에 따른 URL
지난 프로젝트에서도 게시판 목록을 구현하였는데 이때는 그냥 URL 이 "/boards" 로 여기서 페이지네이션, 정렬, 검색 다 했었다.
그러나 게시물 하나를 클릭하고 뒤로 가기를 누르면 "/boards" 로 가기 때문에 페이지네이션, 정렬, 검색이 유지되지 않았다.
그래서 이번에는 search param 값에 따라 URL 이 바뀌도록 구현했다.

사용자가 선택한 페이지네이션, 정렬, 키워드에 따라 URL 이 명확하게 정해지기 때문에 페이지 공유와 북마크에 유리해진다.
또한 새로고침을 해도 상태가 유지되기 때문에 UX 측면에서 좋다.
3-5. 페이지네이션

1칸, 5칸 움직이는 페이지네이션을 구현하였다.
사실 지금껏 페이지네이션을 구현해 본 적이 없었는데 이번에 드디어 구현을 하였다.
4. 게시물 상세

기존과 다르게 토큰, 조회수 기능을 추가하였고, 구현한 기능은 다음과 같다.
- SSR + TanStack Query
- 토큰
- 게시물 좋아요 옵티미스틱
- 댓글 무한 스크롤
- 댓글 작성 중
- 세션 스토리지 사용하여 목록으로 가기
4-1. SSR + TanStack Query
게시물 목록에서 게시물에 들어갈 때, 빠른 초기 렌더링 속도를 위해 SSR 을 사용하였다.
또한 캐싱을 하여 데이터를 재사용하고, 쿼리 초기화를 위해 TanStack Query 를 사용하였다.
그래서 게시물 목록 페이지에서 상세 게시물이 미리 렌더링이 되는 것을 확인할 수 있다.

해당 내용에 관한 설명은 https://jjang-j.tistory.com/153 에서 자세히 확인할 수 있다.
[Next.js / TanStack Query] Server Side Rendering 하기 (feat. app router)
시작하며...이번 프로젝트에서 Next.js App Router 를 사용하면서 TanStack Query 를 사용하기로 했다. 그런데 Next.js 에서는 데이터 패칭을 할 땐 Server Sider Rendering 을 사용하는데 이걸 TanStack query 와 함께
jjang-j.tistory.com
4-2. 토큰

기존 API 에는 게시물의 내용만 담는 content 만 있었는데 token 까지 내가 임의로 추가하여 게시물 내용을 포함해서 만든 객체를 JSON 형식의 string 문자열로 만든 것을 parse 하여 다시 객체로 만들어 사용하였다.

토큰이기 때문에 만료기간이 있었다.
그래서 유틸 함수를 만들어 만료가 되면 만료되었다고 화면에 표시하였고, 만료되지 않았을 경우 토큰을 클릭하여 바로 팀에 참여할 수 있도록 구현하여 UX 를 향상시켰다.
4-3. 게시물 좋아요 옵티미스틱

게시물의 좋아요 기능은 TanStack Query 의 옵티미스틱 업데이트를 활용해서 만들었다.
코드잇 강의로 옵티미스틱 업데이트를 하는 부분이 있었는데 보면서 실제로 구현해보고 싶다! 생각했었는데 실제로 구현하게 되었다.
그리고 좋아요, 좋아요 취소하는 부분을 사용자에게 역동적으로 예쁘게 보여주고 싶어 Framer Motion 이랑 Lottie 를 사용하였다.
(이 부분은 나중에 게시물로 자세히 작성할 예정이다.)
4-4. 댓글 무한 스크롤

무한 스크롤 또한 한 번도 구현해 본 적이 없었고 구현해보고 싶었는데 마침 이번 기회에 구현하게 되었다.
(이번에 이것저것 도전하는 게 많았던 거 같음)
TanStack Query 를 사용하여 구현하였고 설명할 부분이 많아서 이것도 나중에 게시물로 자세히 작성할 예정이다.
4-5. 댓글 작성 중

초반에 백엔드 문제로 인해 API 응답이 지연되었다.
그래서 댓글을 단 후, 쿼리 초기화를 하여도 응답이 지연되었기 때문에 화면에 새로 추가된 댓글이 늦게 달리게 되었다.
팀원들과 회의를 통해 해결 방안을 찾다가, 디스코드 채팅처럼 응답이 오기 전까지는 흐릿하게 댓글을 보여줬다가 응답이 완료되면 댓글을 진하게 보여주자는 의견이 나왔다.
내가 구현한 코드가 좋은 방법은 아닌 거 같지만.. 샘플 댓글을 화면에 보여주고 TanStack Query 에서 isFetching 값을 사용해서 false 가 되면 샘플 댓글 값을 null 로 하였다.
4-6. 세션 스토리지 사용하여 목록으로 가기
기존에 "목록으로" 를 "router.back()" 을 사용하였는데
만약 주소창에 URL 을 직접 입력하여 상세 게시물 페이지로 가게 되는 경우, 의도하지 않은 방향으로 작동하게 된다.
그래서 이를 해결하기 위해 세션 스토리지를 사용하여 이전에 접근했던 페이지를 저장해서 "목록으로" 를 구현했다.
자세한 내용은 https://jjang-j.tistory.com/155 에서 확인할 수 있다.
[Next.js] 세션 스토리지, 이전 페이지 저장해서 뒤로 가기 구현 (feat. app router)
시작하며...이번 프로젝트에서 자유게시판(모집게시판)을 구현하게 되었다. 게시물 상세페이지에 "목록으로" 버튼이 있는데이를 눌렀을 때, 주소의 param 값이 유지되기 위해 router.back() 을 사용
jjang-j.tistory.com
5. 게시물 작성 / 수정



게시물 작성 / 수정 페이지도 구현하였다.
팀 생성 / 수정과 비슷하게 각각 요소마다 컴포넌트를 공유하여 코드의 길이를 줄였다.
베타 테스트
이번 프로젝트는 지난번과 다르게 베타 테스트라는 것을 진행하였다.
진행 이유?
베타 테스트를 진행하게 된 이유는 멘토님의 조언 덕분이었다.
서비스를 만들어도 돈을 쓰는 건 사용자로, 사용자의 피드백이 가장 중요하다고 했다.
그래서 우리 팀은 최종 발표 약 일주일 전에 모든 기능을 최대한 다 구현을 하여 베타 테스트를 진행하게 되었다.
(250명 이상의 활성 사용자 수를 기록했다!)
피드백 방식
피드백을 받은 방식에는 3가지가 있었다.
구글폼, 채널톡, 디스코드
채널톡 같은 경우는 내가 적용하였고 이에 관한 내용은 https://jjang-j.tistory.com/160 에서 확인할 수 있다.
[Next.js] 채널톡 연동하기 구현 (feat. app router, typescript)
시작하며...이번 프로젝트에서 직접 사용자들의 피드백을 받는 베타 테스트를 진행하기로 했다. 유저들의 피드백을 구글폼이나 디스코드로 받으려고 했는데 일단 접근성이 낮고 유저 입장에서
jjang-j.tistory.com
구글폼에는 긴 내용의 피드백을 받을 수 있었고, 채널톡에서는 간단한 오류나 서비스에 대한 칭찬을 받았다.
구글폼, 채널톡 각각 특징이 달라 다양한 방법으로 피드백을 효율적으로 받을 수 있었다.


피드백 반영
피드백을 통해 사소한 것부터 신기능까지 추가하였다. 그중에서 좀 굵직한 내용을 소개하려고 한다.
게시물 조회수 기능
상세 게시물 페이지에 조회수 기능이 있으면 좋겠다는 피드백이 있었다.
피드백을 받기 전에도 해당 기능을 구현하며 좋을 것 같다는 생각을 하게 되었는데 마침 피드백을 받아, 익숙한 Firebase 를 사용하여 게시물 조회수 기능을 구현하였다.
자세한 내용은 https://jjang-j.tistory.com/161 에서 확인할 수 있다.
[Next.js] firebase 게시물 조회수 기능 구현 (생성, 조회, 갱신)
(제목에는 Next.js 붙였지만 딱히 Next.js 에 관한 내용없음) 시작하며...이번 프로젝트에서 베타 테스트를 진행하면서 사용자들의 의견을 받았다. 그중에서 게시판 페이지에 조회수 기능이 있었으
jjang-j.tistory.com
캐러셀이 슝 날라가는 현상

이런 오류가 있는 줄도 몰랐는데 발견해 주신 분 정말 감사합니다!
문제를 해결한 방법은 https://jjang-j.tistory.com/157#슬라이드가-숑-날라가는-현상 에서 확인할 수 있다.
[Next.js] 무한 캐러셀 컴포넌트 직접 구현하기 (feat. Tailwind CSS)
시작하며...지난 기초, 중급 프로젝트에서 캐러셀을 라이브러리를 사용하여 구현하였다. 그때 회고를 보면 나중에는 라이브러리가 아닌 직접 구현해보고 싶다고 글을 적었었다.그런데 마침 이
jjang-j.tistory.com
KPT 회고
팀 회고
K- Kepp
- 마감 기한을 잘 지킨다.
- 데일리 스크럼을 적극 활용한다.
- 서로의 의견을 잘 수용한다.
- UI / UX 측면도 잘 고려한다.
- 코드 리뷰가 활발하다.
- 적극적으로 문제를 해결한다.
P - Problem
- 팀원마다 작업 속도가 달라 부담을 느끼는 팀원도 있었다.
- 코드 관심사의 분리가 잘 안 된다.
- PR 리뷰 속도가 느리다.
- API 문제로 인해 작업 속도가 늦어진다.
T - Try
- 휴일을 정해 그날은 작업을 쉬는 날로 정했습니다.
- 같은 관심사끼리 묶어 이슈를 생성하여 PR 을 쪼갰습니다.
- 팀 회의 끝나고 2~3시는 코드 리뷰하는 시간으로 정했습니다.
- API 문제는 유연하게 넘어갔습니다.
개인 회고
K - Keep
- 맡은 역할을 마감 기한 내에 잘 완수했습니다.
- 적극적으로 의견을 제시하였습니다.
- 툴팁과 설명을 추가하는 등 UI / UX 측면도 고려했습니다.
- 팀원의 PR 을 최대한 다 확인하여 잘한 점과 개선 사항을 리뷰로 남겼습니다.
P - Problem
- 후반으로 갈수록 건강을 잘 챙기지 못했습니다.
- 프로젝트 마감 기한이 다가올 수록 리뷰의 속도와 퀄리티가 떨어졌습니다.
- 일정 관리 도구를 적극 활용하지 못했습니다.
T - Try
- 쉬는 날에는 푹 쉬고 건강을 잘 챙기겠습니다.
- 주어진 리뷰 시간에 최대한 꼼꼼하게 리뷰를 남겨주겠습니다.
- Height APP 이라는 일정 관리 도구를 사용하였고 이틀에 한 번은 들어갈 정도로 일정을 관리할 수 있도록 노력했습니다.
피어리뷰
프로젝트가 마무리된 후에는 익명으로 피드백을 주고받는 "피어리뷰" 시간이 있었다.
팀원들이 나에게 남겨준 피드백을 확인해 보니, 모두 따뜻하고 긍정적인 말씀을 해주셔서 정말 감동받고 감사한 마음이 들었다. 🥲
나는 평소 의견을 적극적으로 내는 편이라, 혹시나 내 의견만을 너무 강조하는 건 아닐까 걱정도 했었는데, 팀원들이 긍정적으로 바라봐 줘서 고마웠다.

마치며...
이번 프로젝트에서는 그동안 내가 구현하고 싶었던 기능을 직접 구현할 수 있었고, TanStack Query 등 다양한 기술을 적극적으로 활용한 덕분에 개발 역량이 크게 향상되었다.
또한, 프로젝트의 차별성을 두기 위해 팀원들과 활발히 소통하며 개선 사항을 도출하고, UX 측면에서도 사용자의 편의를 고려한 기획 또한 진행하였다. 덕분에 협업 과정에서 갈등 없이 원활한 소통을 이어가, 협업 능력 또한 크게 발전할 수 있었다.
비록 코드잇에서 진행한 모든 프로젝트가 마무리되었고, 스프린트도 끝이 났지만, 프론트엔드 개발자가 되기 위한 한 단계 걸어갈 수 있었던 중요한 발판이 되었다.

'💜 후기 및 활동 > 프로젝트' 카테고리의 다른 글
[Codeit Resources] 코드잇 인턴 프로젝트 회고 (0) | 2024.11.20 |
---|---|
[wiki-viki] 코드잇 스프린트 중급 프로젝트 회고 (7) | 2024.07.15 |
[내 마음 속 바다] 개발 동아리 DND 10기 프로젝트 회고 (0) | 2024.06.11 |
[Fandom-K] 코드잇 스프린트 기초 프로젝트 회고 (1) | 2024.06.10 |
FE 개발자가 되고 싶은 짱잼이
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!