🔎 프로젝트 소개

‘루틴’ 이라는 용어와 그 필요성이 상승한 것과는 달리, 사람들은 이를 실천하기를 어려워 합니다.
이러한 문제를 해결하기 위해, 그룹 + 보상 이라는 시스템으로 루틴을 실천할 수 있도록 도와주는 서비스인 모아밤을 기획/개발했습니다. (기획 문서 보기)
루틴 목록 보기
- 사용자는 본인이 속한 루틴 방의 목록을 볼 수 있습니다.
그룹 목록 보기
- 사용자는 전체 방을 조회 및 검색할 수 있습니다.
그룹 상세 보기
- 사용자는 각 방의 정보를 조회할 수 있으며, 참여할 수 있습니다.
- 방 내에서 루틴을 수행할 수 있으며, 루틴을 수행하면 방 레벨이 오르고 얻는 벌레의 수가 증가합니다.
새 커스텀 하기
- 루틴 방에서 얻은 벌레는 자신의 새를 커스텀 하는 데에 사용할 수 있습니다.
쿠폰 받기
- 사용자는 이벤트 페이지에서 선착순 쿠폰을 지급받을 수 있습니다.
- 쿠폰으로 벌레를 얻거나 결제 할인을 받을 수 있습니다.
루틴 목록 보기, 그룹 목록 보기, 쿠폰 받기, 오프닝 페이지를 맡았습니다.
👩🏻💻 개발 내용
1. 그룹 조회 및 검색 기능

- 루틴 그룹을 아침/밤 으로 필터링하고, 키워드를 입력해 검색 결과를 조회하는 기능입니다.
- debounce 처리를 통해 입력 시 자동으로 검색 결과가 보여지도록 구현했습니다.
- useInfiniteQuery 를 활용하여 무한 스크롤 기능을 구현했습니다.
- 검색 결과 내에서 사용자 입력 키워드가 강조되어 나타나는 하이라이팅 기능을 구현했습니다.
- 서버 데이터에 의존적인 기능이기 때문에, MSW 를 활용하여 mock 서버 로직을 작성해 테스트했습니다.
2. 오프닝 페이지, 메인 페이지 (Swiper)

- 오프닝 페이지에서 메인 페이지로 이동이 모바일 잠금화면처럼 작동하도록 구현했습니다.
- 자연스러운 UI 를 위해서는 각각의 페이지가 겹쳐서 위치해야 했으나, 데이터 요청이 중복으로 발생하는 문제가 있었습니다.
- SkeletonUI 를 재사용하여 아래에 위치할 mock 페이지를 작성하고, Swiper 라이브러리의 onReachEnd 속성을 활용하여 인터랙션이 완전 끝난 후 페이지 이동이 실행되도록 했습니다.
- 오프닝 페이지 → swipe (메인 페이지의 Skeleton UI) → 메인 페이지
- 사용자가 참여중인 루틴 그룹을 아침, 밤으로 나누어 조회할 수 있습니다.
- 토글 버튼으로 시간대를 전환하는 UI를 적용하기 위해, 슬라이딩 토글 버튼을 구현했습니다.
- Swiper 라이브러리의 Control 모듈을 활용하여 슬라이드와 토글 버튼을 양방향으로 연결하였습니다.

3. 선착순 쿠폰 발급

- 이벤트 발생 시 알림 배너가 뜨고, 선착순 쿠폰을 발급받을 수 있는 기능입니다.
- query 옵션으로 refetchInterval 을 활용해 이벤트 유무를 지속적으로 요청합니다.
- 사용자 클릭이 여러번 발생할 경우, 서버 에러가 증가하는 상황이 있었습니다.
- useMutaion 의 isPending 상태를 활용해 발급 요청 중에는 버튼을 disabled 처리하며 에러를 방지하고자 했습니다.
- 쿠폰 요청 이후에는 응답 받은 http 상태 코드에 따라 분기처리하여 disabled 버튼 UI 가 달라지도록 구현했습니다.
- 사용자의 불편을 해소하고, 불필요한 네트워크 요청을 감소시킬 수 있었습니다.
4. 로딩 UX 개선

- useSuspenseQuery 와 Suspense 를 활용하여 데이터 로딩 시 Skeleton UI 가 나타나도록 구현했습니다.
- 하위 컴포넌트의 렌더링을 미세하게 지연시키는
Deffered
컴포넌트 방식을 제안하고, 구현했습니다.. - 로딩 시간이 짧아질 경우 Skeleton UI 가 깜빡이는 문제를 해결하였습니다.
- 빈화면 → SkeletonUI → 실제 데이터로 UI 전환을 줌으로써 사용자의 기다림이 짧게 느껴지도록 유도했습니다.
5. 공통 코드 개선
router 관련 로직 공통화 (↗️)


route 에 종속되는 각종 데이터들이 하나의 객체에서 관리되도록 설계했습니다.
- 각종 데이터 : auth, navbar 유무, params, 페이지 이름
- router 생성과 관련 커스텀 훅들이 해당 객체만을 참조하도록 설계하여, 하나의 파일만 수정하면 되게끔 하였습니다.
관련 로직들을 공통화한 커스텀 훅을 구현했습니다.
- useRouteData : 현재 path의 페이지 데이터들을 반환
- useMoveRoute : 각종 페이지 이름을 타입화 하여, 선언적으로 페이지 이동을 실행
- 휴먼 에러를 감축시키고, url 에서 데이터를 가져오는 로직을 통일시킬 수 있었습니다.
코드 스니펫 작성 (↗️)

팀 코드 컨벤션에 맞게, React 컴포넌트와 Storybook 작성을 위한 코드 스니펫을 작성했습니다.
- 파일명을 가져와서 컴포넌트와 prop 타입의 이름, 코드의 틀이 자동으로 작성되도록 하였습니다.
팀원간의 코드 일관성을 지키고 반복되는 작업을 줄일 수 있었습니다.
👥 협업 과정
Git All In One

- 각종 문서화와 스크럼, 회고, 스프린트 관리를 모두 Github 내에서 진행했습니다.
- discussion, issue, project, milestone 을 적극 활용하여 대부분의 개발 플로우가 Github 내에서 이루어졌습니다.
- 백엔드와의 진행 상황 공유가 수월해졌으며, 개발 시 다른 문서나 페이지로의 접속 횟수를 줄이고 개발 효율을 증대시킬 수 있었습니다.
팀 내 스터디

- 팀 내에서 Next.js 공식 문서 스터디를 진행했습니다.
- Next.js 도입 여부를 결정하기 위해 팀원들과 함께 공식 문서를 학습하였습니다. 해당 기술이 프로젝트 기능에 부합한 지 이야기를 나눌 수 있었습니다.