🐰 엘리스 SW 6기 2차 프로젝트 Mingle 회고 (3) - 프로젝트 진행 3주차 (+ 발표)
이전 글
🐰 엘리스 SW 6기 2차 프로젝트 Mingle 회고 (2) - 프로젝트 진행 1주차, 2주차 (tistory.com)
🐰 엘리스 SW 6기 2차 프로젝트 Mingle 회고 (2) - 프로젝트 진행 1주차, 2주차
이전 글 🐰 엘리스 SW 6기 2차 프로젝트 Mingle 회고 (1) - 프로젝트 시작 전 (tistory.com) 🐰 엘리스 SW 6기 2차 프로젝트 Mingle 회고 (1) - 프로젝트 시작 전 1차 프로젝트에 이어서 2차 프로젝트의 모든
developingdiaryoflily.tistory.com
2차 프로젝트 진행 마지막 주인 3주차 회고를 해 보겠다!
1️⃣ DB에 곡과 플레이리스트 업로드해 놓기
사용자가 직접 곡과 플레이리스트를 업로드할 수 있는 서비스이지만, 초기에는 곡과 플레이리스트 정보가 하나도 없을 것이므로 미리 VM과 연결된 DB에 데이터를 넣어놓는 작업을 실시하였다.
곡은 저작권 문제가 발생하지 않도록 아래 사이트에서 다운받아 사용하였다.
(결제를 하지 않고 사용하면 노래에 시그니처 사운드처럼 회사 로고명 음성이 같이 나온다.🥲 but 무료 음원치고 퀄리티가 좋은 거 같아 선정하였다!)
Royalty-Free Music for Video Creators | Artlist
Royalty-Free Music for Video Creators | Artlist
Explore premium royalty-free music for video creators | Music licensing for YouTube videos, social media, commercials, podcasts and games | Your go-to stock music library
artlist.io
차트에 100개의 곡이 뜰 수 있도록 postman에서 좋아요 누르기 api 요청 send를 하여 통해 최소 100개의 곡에 좋아요를 누르는 작업을 하였고, 여러 명의 유저를 만들어 놓고 각 유저마다 모든 장르의 플레이리스트를 업로드 하게 하여 플레이리스트 추천 로직에 따라 무조건 4개 이상의 플레이리스트가 걸릴 수 있도록 세팅을 하였다.
처음부터 끝까지 자체적으로 만들다 보니 get 해와서 띄울 정보가 없어 postman을 이용해 수동으로 데이터를 만들어 놓아야 했다😂
2️⃣ 문서 작업 (기획서 작성, figma 다듬기)
처음에 기획을 진행하고, figma에 디자인도 어느 정도 해두고 시작하긴 했지만 기획은 문서화가 되어 있지 않았고 notion과 discord에 여기저기 흩어져 있는 상태였고, figma에도 주요 기능 정도가 디자인 되어 있었기 때문에 추가된 기능들 디자인도 추가시켜야 했다.
곡과 플레이리스트를 다 업로드하고 나니 백엔드가 할 작업들은 거의 마무리가 된 상태라서 문서와 디자인 완성 작업을 백엔드가 맡아 하기로 하였다.
기획서 | Built with Notion
목차
tinted-chair-ae5.notion.site
3️⃣ 프론트 코드 작성
문서 작성도 거의 다 마치고 나니 시간이 뜨게 되었다.
프론트 작업은 아직 남아 있는 상태라 몇개의 기능은 백엔드가 맡아 개발하기로 하였다.
원래 프론트 코드를 짜는 것을 원하고 있긴 했으나 막상 맡아서 개발하려 하니 두려움도 있었다.
1차 프로젝트때는 익숙한 Vanilla JS로만 개발을 하면 됐었기에 거리낌 없이 프론트 분들을 도와드릴 수 있었지만, 이번 프로젝트에서는 Vanilla JS만큼 익숙하지는 않은 React를 사용해야 했다.
사실 React를 사용하여 개발하는 것까지는 괜찮지만 처음 사용해보고 개념도 제대로 잡혀 있지 않은 Typescript, React-query, recoil을 사용하여 개발하려니 괜히 나섰다가 오히려 기능 구현을 제대로 하지 못해프로젝트를 완성하지 못하면 어쩌나 걱정이 많이 되었다. 마감일도 거의 3일정도밖에 남지 않은 상태였다.
그렇다고 아예 시도도 안하기에는 좋은 기회를 놓치는 거 같았고, 프론트 분들이 작업해온 양이 지금까지 너무 많았었기 때문에 다들 피로도가 많이 쌓인 상태인 거 같아서 한 번 해 보아야겠다고 다짐했다.
그렇게 하여 내가 구현을 담당한 기능은 다음과 같이 플레이리스트 관련 CRUD 기능이 되었다.
📍 플레이리스트 업로드 기능
새 플레이리스트 만들기 / 유저가 이미 만들어놓은 플레이리스트에 곡 추가하기 모두 가능하게
📍 현재 로그인한 유저가 업로드한 플레이리스트 수정 기능
플레이리스트에서 곡 삭제, 제목 수정, 커버 사진 수정, 내용 수정, 장르 수정 가능하게
📍 현재 로그인한 유저가 업로드한 플레이리스트 삭제 기능
처음 미션은 플레이리스트 업로드 기능을 구현하는 것이었다.
차트, 장르별, 최신 음악 사이트에 들어가면 오른쪽 위에서 볼 수 있는 +Playlist 버튼을 클릭하면 사용자가 해당 곡 페이지에서 선택된 음악들로 플레이리스트를 제작하는 모달창을 띄워야 했다.
다른 분이 곡 업로드 컴포넌트를 이미 완성해 두셔서 그 코드를 참고하여 제작하였다.
처음에 코드를 딱 보고 어떻게 돌아가는 코드인지 잘 이해가 가지 않아서 1~2시간 정도는 다른 분이 작성한 코드를 계속 들여다보면서 흐름이 어떻게 되는지를 파악하는 데 보낸 거 같다. 🥲
'플레이리스트에 담을 곡을 토글할 수 있어야 하고 ➡️ 클릭된 곡은 state에 담아 ➡️ playlist 업로드 컴포넌트에 props로 내려주어 ➡️ playlist 버튼을 클릭 시 저장할 곡을 띄우고, 필요한 정보를 입력받아 플레이리스트 업로드하기' 이 과정을 거쳐야 하여 곡 데이터를 가져오는 코드부터 살펴보았고, 통신 시 어떠한 흐름으로 코드를 작성해야 할지를 살펴보았다.
모든 코드의 역할을 세세하고 정확하게 이해하지는 못했지만
📍 song 데이터는 어디로부터 받아져 와서 어떤 컴포넌트로 전달되고,
📍 서버로는 어떻게 요청을 보내는지(utils에서 만들어 놓은 useAxios의 return값에서 axiosInstance나 axiosBase 가져와 HTTP 메서드와 함께 사용하기),
📍 성공과 에러 처리는 어떻게 하는지 (useMutation의 첫 번째 매개변수로 통신 수행 함수를 작성하고, 두 번째 매개변수로 onSuccess, onError 콜백 함수를 작성하여 각각 성공, 실패 시 처리하기)
등의 흐름을 중심으로 이해하려 노력했고, 이미 작성된 코드를 많이 참고하여 플레이리스트 업로드 기능을 구현하는 데에 성공했다.
이어서 플레이리스트 수정, 삭제를 구현해야 했는데 플레이리스트 업로드랑 비슷한 흐름으로 구현하면 됐었다. 다만, 마이페이지에서 플레이리스트 재생 페이지로 이동한 경우에만 삭제, 수정 버튼이 뜨도록 해야 했다.
마이페이지에서 플레이리스트 재생 페이지 이동 시 navigate 함수에 state로 isFromMyPage: true 이런 식으로 전달해 주고 플레이리스트 재생 페이지 파일에서는 isFromMyPage가 true인지 아닌지 확인하여 그에 따라 버튼을 보여주거나 보여주지 않는 식으로 구현을 하는 것이 핵심이었다.
마지막으로 추가 기능으로 플레이리스트 업로드 시 기존 플레이리스트에 추가하여 업로드할 것인지, 새 플레이리스트에 업로드할 것인지 선택할 수 있도록 제작하였다.
유저가 업로드한 플레이리스트 get api와 플레이리스트에 곡 추가 api만 잘 사용하면 됐어서 무난하게 구현이 가능하긴 하였지만 새 플레이리스트에 추가하기 버튼을 누를 경우 모달창을 2번 띄워야 했어서 그 부분이 살짝 까다로웠다. 중간에 X 표시나 모달창 바깥을 클릭하면 취소가 되게 만들어야 했는데 그때 state에 들어 있는 데이터들을 잘 초기화해야지 버그가 생기지 않았다.
프론트 기능은 정말 일부분의 기능만 개발을 하였지만 개발 과정 중에서 가장 느낀 것이 많았고, 걱정했던 것보다 구현이 잘 된 거 같아 뿌듯했다.😊
4️⃣ 빌드 에러와 버그 해결하기
어느새 개발 마지막 날이 되었고, 기능들도 모두 구현 완료하였다.
📍 빌드 에러
빌드 후 배포를 위하여 client 폴더에서 yarn build를 수행해 보았더니 정말 많은 Typscript 빌드 에러가 발생하였다.😂😂 기억상 108개 정도로 나도 어느 정도 기여를 했다...
Typescript 코드를 빠르게 무작정 작성하다 보니 놓친 부분이 많았었던 거 같다.
해결을 위해 디스코드에서 화면 공유를 하여 30개의 에러를 남기고 모두 해결을 하였고, 나머지는 오피스 아워 시간에 코치님께 해결을 부탁드렸다ㅎㅎ 정말 감사했다!!
빌드 결과 번들링 사이즈가 너무 크고, 빌드 시간도 오래 걸리는 문제가 있었는데 React.lazy 함수와 Suspense 컴포넌트를 이용해 코드 분할을 하여 번들의 일부를 나누고 필요한 시점에 로딩을 하여 해결할 수 있었다.
📍 버그
➡️ 로그인 후 새로고침을 하면 로그인이 해제되는 현상이 있었다. 이는 팀장님이 인증 헤더가 있는 axiosInstance의 Axios.create에서 withCredentials: true 옵션을 추가하여 브라우저가 요청에 대해 쿠키를 자동으로 포함시키도록 만들어 로그인 상태가 유지되도록 만들었다.
➡️ 곡 좋아요 토글 버그가 있었다. 좋아요를 누르는 것은 잘 되는데 취소가 반영되지 않는 문제였다. 이 부분도 팀장님이 해결해 주셨는데 좋아요를 누를 때와 취소할 때 실행될 콜백 함수를 분리시키고, 각 동작이 실행될 때마다 React query의 queryClient.invalidateQueries() 메서드를 사용하여 캐시된 데이터의 쿼리를 무효화시켜 다시 렌더링이 일어나도록 하여 해결하였다.
(이전 코드는 곡이 좋아요가 되어 있는지 아닌지의 상태를 바탕으로 콜백 함수를 실행해야 하는데 클릭이 이루어지는지 아닌지 여부를 바탕으로 Like와 deleteLike를 수행하려 해서 제대로 수행이 되지 않은 것으로 추정한다.)
이건 발표 몇십분 전에 해결이 된 오류였는데 해결이 되어서 정말 다행이었다!
// 기존 코드
const handleLikeClick = async () => {
if (!isClick) {
await Like(_id);
} else {
await deleteLike(_id);
}
// 수정한 코드
const handleLikeClick = () => {
Like(_id);
queryClient.invalidateQueries();
};
const handleDeleteLikeClick = () => {
deleteLike(_id);
queryClient.invalidateQueries();
};
5️⃣ 발표
드디어 개발이 끝나고 발표 날이 다가왔다.🎇🎇
발표는 내가 맡기로 하였고, 발표 날 아침에 디스코드에서 모여 리허설을 진행하였고, 트러블 슈팅 부분에서 내용을 그대로 읽기보다는 좀 더 청중이 흥미를 느낄 수 있도록 내용은 간추리고, 공감을 유발할 수 있는 멘트를 더하면 좋겠다는 피드백을 받고 오후에 발표에 들어갔다.
발표는 1차 때와 거의 비슷하게 프로젝트 기획, 기능 소개, 트러블 슈팅, 프로젝트 시연 순으로 진행하였다.
발표 순서는 3번째로 앞 순서라서 오히려 좋았다😊😊
역시 다른 코치님들로부터 피드백을 받았다. 내가 제작한 부분에서는 플레이리스트 업로드 시 사진을 필수로 해 놓은 것이 사용자 경험 측면에서 별로 좋지 않을 수 있어 사진을 올리지 않을 경우 자동으로 기본 이미지가 들어가도록 해놓는 것이 더 좋을 거 같다는 피드백을 받았다. 추후에 수정해볼 계획이다!
발표가 끝나고 사실 그냥 바로 쉬러 나갔다ㅋㅋㅋㅋ 전날에 새벽 4시까지 다같이 회의하고 나서 잠을 못자고 바로 발표 준비를 했기에 너무 피곤했었다🥲🥲
3주동안 거의 매일 개발에만 힘을 쏟았기 때문에 의미있었고, 1차 프로젝트보다 더 많은 기능을 구현하고, 더 많은 기술을 경험해볼 수 있어서 매우 뜻깊은 시간이었다.
🔜 추후 계획
이번 2차 프로젝트를 경험하고 나서 좀 더 배우거나 해보고 싶은 것들이 생겼다.
📍 배포와 클라우드 스토리지 이용
엘리스 과정 진행하면서 정말 많은 것을 배웠지만 아쉬운 점 중에 하나는 배포를 경험해보지 못했던 것이었다. 이미 엘리스 측에서 제공해 준 VM은 삭제가 되었기 때문에 어차피 재배포를 해야 해서 내 힘으로 한 번 해보고 싶다.
그리고 이번 프로젝트에서 이미지나 음원 파일 같은 것들을 클라우드 스토리지를 이용하지 않고 엘리스에서 제공해 준 VM 자체에 저장을 하는 방식을 택했다. 그래서 VM이 삭제됨이 따라 우리의 데이터도 날아가게 되었다.😂 그래서 클라우드 스토리지를 이용하여 좀 더 안정적으로 데이터를 보관하는 방법을 사용해 보고 싶다!
📍 코드 리팩토링
회고글을 쓰면서 살펴보니, 내가 작성한 백엔드, 프론트 코드에서 불필요한 코드나 억지스러운 로직이 있는 것을 발견할 수 있었다. 이 부분들을 리팩토링 해보고 싶다.
📍 다양한 상태 관리 라이브러리 사용해보고 비교하기
이번 프로젝트에서 recoil을 적용하기는 했지만 내가 제대로 사용을 하여 코드를 작성하지는 않은 거 같다.
redux, redux toolkit, recoil 등 다양한 상태 관리 라이브러리를 사용해 보고 각각 어떤 장점과 단점이 있고, 왜 상태 관리 라이브러리를 사용해야 하는지 몸소 느끼고 싶었다.
📍 React Query
이번 프로젝트에서 React Query가 굉장히 많고 편리한 기능을 제공한다는 것을 알게 되었다.
React Query를 더 공부하여 적재적소에 사용해 보고 싶다는 생각이 많이 들었다.
이렇게 2차 프로젝트의 전반적인 진행 과정 회고는 끝이다❗
앞으로도 프로젝트를 계속 살펴보며 배운 내용이나 리팩토링 한 내용, 구현 과정들 등을 기록해나갈 예정이다!