Elice 2차 프로젝트, Cocktailer 회고
2022년 12월 16일 ~ 2022년 12월 30일, 약 3주간 진행된 Cocktailer 프로젝트에 대한 회고
Cocktailer
www.cocktailer.p-e.kr
https://github.com/Cocktailer-Elice/cocktailer
GitHub - Cocktailer-Elice/cocktailer: 🍹 칵테일에 대한 모든 것
🍹 칵테일에 대한 모든 것. Contribute to Cocktailer-Elice/cocktailer development by creating an account on GitHub.
github.com
1. React-hook-form의 이용
처음 사용하게 된 계기는 전에 들었던 강의를 통해 react-hook-form을 이용하면 form을 다루는 게 상당히 편리해진다는 기억을 가지고 있기 때문이었다. 사용을 위해 공부하고 적용하고를 반복하며, 조금은 익숙해진 것 같지만 아직도 사용 가능한 기능이 많이 존재하고 있다.
마주친 문제 하나, form validation을 위한 부분이 길어져 input element에 들어가는 내용이 너무 많아진다.
react-hook-form의 useForm은 resolver를 통해 validation을 진행할 수 있었다. 대표적으로 이용되는 validation library는 yup과 joi가 있었다. npm trends를 통해 보면 주간 다운로드 수는 joi가 더 많지만 좀 더 찾아보니 빌드 시 크기가 작은 등의 장점을 갖는 yup이 frontend 진영에서는 주로 이용되는 validation 라이브러리였기에 yup을 함께 적용하기로 결정했다. yup schema를 설정하고, useForm에 yup 설정을 추가해 주자 validation을 위해 input element 내부에 수많은 에러핸들링 로직을 적어 넣을 필요가 없어졌다.
마주친 문제 둘, 페이지마다 다른 input component.
공용으로 이용할 수 있는 컴포넌트를 제작하는 것이 좋겠다는 코치님의 권고를 받고 다시금 react-hook-form을 공부했다. 찾아낸 해결책은 form provider였다. react-hook-form은 form context를 통해 useForm의 methods를 하위 component로 전달하는 방식을 취할 수 있었고, 공용으로 제작한 Input component는 useFormContext를 통해 상위 form에서 전달된 methods(formState 등)을 받아서 이용할 수 있게 되었다.
두 가지 문제를 해결하며 공용 컴포넌트를 제작하는 과정을 경험했고, 공식문서를 통해 공부하는 데에 조금은 더 익숙해진 듯했다. 또한 동일한 기능을 하는 라이브러리에도 어디에서 이용되느냐에 따라 선택의 기준이 달라진다는 점도 배우게 되었다.
2. HOC(Higher Order Component)의 제작
고차 컴포넌트를 통해 코드의 중복을 해결하는 경험을 하게 되었다. 프로젝트 초기에는 로그인을 필요로 하는 페이지가 있다면 해당 페이지에서 useEffect를 실행하고 useAuth와 같은 커스텀 훅을 통해 로그인되었는지를 체크하는 과정을 진행하였다. 하지만, 코드의 중복을 해결하는 방법이 없을까 고민하던 중, 고차 컴포넌트를 통한 해결방식이 있음을 알게 되었다. withLogin이라는 이름의 고차 컴포넌트를 제작하게 되었다. 해당 컴포넌트는 내부에서 login 상태를 확인하고, login이 되어있지 않은 경우에는 로그인 페이지로 보내고 로그인되어 있는 경우 prop으로 받은 컴포넌트를 return 하는 형태로 제작되었다.
앞으로 생각해봐야 할 점 하나, withLogin을 통해 로그인페이지로 이동하는 경우
특정 페이지에 있다가 로그인페이지로 이동하는 경우에 대해 생각해 보았다. 사용자는 기존에 이용하던 페이지로 돌아가거나, 접근하려던 페이지로 접근하는 것을 원할 것이다. 사용자 경험을 가장 좋게 하기 위해서는 기존에 사용자가 있던/접근하려던 페이지를 queryString으로 전달하거나 browser stroage에 저장하는 방식을 이용하여 되돌아가게 하는 방식을 정용하는 것이 맞을 것 같다.
3. Redux
Recoil과 같은 다른 선택지도 있었지만, 배운 것을 일단 활용해서 익숙해보자는 의견을 따라 이번 프로젝트의 중앙 상태관리는 Redux를 사용하기로 했다.
하나, Container - Presentaitional Component
프로젝트 초기, Container component가 무엇을 의미하는지 모른 채, 단순히 컴포넌트의 집합을 감싸는 또 다른 컴포넌트로만 이해하고 팀원 전체가 작업을 진행하고 있었다. 하지만 API를 연결하고 redux를 작업하면서 react-redux에서 이용되는 container component와 presentational component가 무엇을 의미하는지를 알게 되기 시작했다. 따라서, 의미없게 작성되어있던 container/*를 모두 제거하고 pages/components로 돌려놓았고 redux가 적용되는 부분을 작업을 시작했다.
Container component는 mapStateToProps, mapDispatchToProps를 생성하여 Presentational component에 connect를 이용하여 props로 필요한 redux의 정보를 props로 전달한다. 진행했던 프로젝트에서 상태관리가 필요하다고 생각한 부분은 login을 통한 user의 정보였다. 따라서, Auth 부분에 주로 container를 생성하여 관리를 진행했다. (배우는 과정의 프로젝트인 관계로 주로 중앙 상태관리를 이용하지 않는 정보도 리덕스를 작업해보는 것을 권고받아 작업된 부분이 존재한다.)
둘, 로그인 유지
리덕스는 메모리에 정보를 보관한다. 새로고침이 일어나거나 페이지를 직접 이동하는 경우가 발생 시, 브라우저 메모리가 초기화되기 때문에 리덕스에 저장된 정보를 잃어버리는 경우를 만나게 되었다. 프로젝트의 로그인은 로그인 시 http-only, secure 상태의 cookie를 통해 JWT를 받아오는 형태로 작성되어 있었다. 스크립트를 통해 cookie의 JWT를 직접 확인하여 유저 정보를 가져오는 것은 가능하지 않았다. Redux-persist와 같이 브라우저 스토리지를 이용하여 정보를 유지하는 방식이 있었지만 위의 이유로 인해 이는 불가능했다. 백엔드 팀원분과 논의한 끝에 새로운 api를 하나 생성하게 되었고, 로그인이 되어있지 않은 경우 해당 api를 통해 GET 요청을 보내고 백엔드는 쿠키를 확인하여 로그인된 유저일 시 유저정보를 내려주는 형태로 작성을 하였다. 이런 과정을 통해 redux store에 다시금 유저정보가 기록되도록 하였고 로그인 유지를 하는 데 성공했다.
4. 팀 프로젝트의 경험
지난 2022년 3월에 진행했던 15일 챌린지와 10월에 진행한 바닐라 자바스크립트 기반의 팀 프로젝트에 이어서 3주간의 팀 프로젝트를 마쳤다. 이번 프로젝트는 정말로 배운 것들과 배울 것들을 모두 끌어모아 진행된 프로젝트였기에 느낀 점이 많았던 것 같다
하나, 타입스크립트 기반의 팀 프로젝트
타입스크립트를 팀 프로젝트 단위로 적용하고 백엔드와 하나의 repository를 이용하게 되었다. 백엔드에 보내야 하는, 그리고 백엔드가 받아야 하는 interface를 공용으로 types 폴더를 만들어 관리하게 되었다. 이를 통해, 양 directory에 중복으로 존재하게 될 interface와 type들이 많이 줄어들게 되었고 혹시 모를 타입 충돌도 방지할 수 있게 되었다.
둘, 매일 진행한 회의와 기록
아직 정확한 애자일의 의미에 대해서는 모르겠다. 하지만 매일 팀원들이 자신의 작업 진행 상황을 공유하고 오늘은 무엇을 할 것인지, 어떤 이슈가 있었는지를 공유하는 것은 상당히 좋은 프로세스라는 생각이 들었다. 더불어, 깃랩의 위키 시스템을 이용하여 스크럼을 기록하는 것, JIRA를 통해 티켓을 발행하여 어떤 일을 진행해야 하는지, 어떤 일은 종료가 되었는지를 관리하는 것이 작업의 능률에도 상당히 좋은 영향을 끼쳤다고 생각이 든다.
셋, 길게 잡은 기획과 설계의 기간
프로젝트 기간은 약 3주였지만, 초기의 약 3 ~ 4일은 기획과 설계에 대부분의 시간을 투자했다. 어떤 아이디어를 통해 어떤 페이지를 구현할 것인지, 구현한다면 어떤 기술을 이용할 것인지 오랜 시간의 회의를 거쳤다. 되돌아보면 이것조차 충분한 설계는 아니었던 것 같지만, 많은 부분을 사전에 계획하고 작업에 들어가는 것이 중요함을 알게 되었다. 어떤 작업들이 진행되어야 할지, 어떤 UI를 가지도록 컴포넌트를 분리해야 할지, 어떤 타입들이 필요할지 설계단계에서 상당수 그림이 그려졌다.