스테디(Steady)

프로젝트 소개
스테디(Steady)는 IT 분야의 스터디 및 프로젝트 인원 모집 플랫폼입니다.
-
팀 구성: FE 3명 + BE 3명
-
작업 기간: 2023.10.09 ~ 2023.12.10
-
기술 스택: Next.js 13, TypeScript, Tailwind CSS, Zustand, Tanstack Query, React Hook Form, Zod
-
핵심 기능
- 관심 주제 스터디 및 프로젝트의 쉬운 조회
- 신청서 템플릿과 끌어올리기 기능을 통한 간편한 모집글 등록
- 유저 정보 카드 및 리뷰 정보로 참여도 및 역량 파악
담당 역할
SM(Scrum Manager)으로 활동
평일 오후 2시에 Scrum을 통해 FE와 BE가 서로 Todo와 Issue를 공유하도록 했습니다.
노션을 통해 프로젝트 일정이나 회의록을 정리하고, 트러블 슈팅 문서를 작성하여 트러블을 해결하는 시간을 절약하고 개발에 좀 더 집중할 수 있는 환경
을 조성했습니다.
회고를 통해 도출한 Action Item
을 다음 스프린트에 실행했습니다.
담당 기능
1. 로그인 온보딩 구현
로그인 온보딩은 최초 회원 가입한 유저에게 발생하는 과정입니다.
닉네임 설정 -> 관심 포지션, 기술 스택 설정 -> 스테디 이용 방법 등 step들이 존재합니다.
닉네임은 중복과 유효성 검사가 필요하고, 관심 포지션과 기술 스택은 필수 요소로 선택해야 합니다.
따라서, 많은 폼을 효과적으로 관리하기 위해서 React Hook Form과 Zod를 이용해서 로그인 온보딩 과정에서의 유효성 검사를 진행하는 스키마를 정의하고 구현
했습니다.
또한 로그인 온보딩 과정은 예상치 못한 일이 생겨도 다시 해당 step 모달이 발생해야 UX를 높일 수 있습니다.
따라서, Zustand의 persist 기능을 이용해 로그인 온보딩 과정을 전역 상태로 관리할 뿐만 아니라 LocalStorage에 저장하도록 구현
했습니다.
2. 스테디 상세, 내 스테디 목록, 신청자 목록 및 답변 열람 페이지, 내가 받은 리뷰, 신청서 작성, 신청서 수정 페이지 구현
하위 페이지가 상위 페이지와 유사한 layout을 가지고 있으면, Next.js의 특수 파일인 layout.tsx를 이용해 중복 코드를 피해 개발 시간을 단축
했습니다.
페이지에서 모든 data를 한 번에 가져오는 것 보다 Tanstack Query를 사용한 무한스크롤 훅을 통해 로딩 시간을 단축하여 UX를 향상
했습니다.
3. 에러, 로딩(스켈레톤 UI) 페이지 구현
로딩 시 스켈레톤 UI와 에러 발생 시에 에러 페이지를 구현하여 전반적인 UX를 향상했습니다.
useSuspenseQuery 사용 시 data fetch 완료 전에 로딩 처리가 필요하여 Next.js의 loading.tsx를 이용하여 구현했습니다.
트러블 슈팅
1. Axios Interceptor Server Function 에러
🚨 문제 상황
Client Component에서 Server Function을 사용해서 문제가 발생했습니다.
🌱 해결책
- Client Component에서 Server Function을 사용하지 않는다. ✅
- Data Fetching 로직을 Server Component로 옮긴 후, 데이터를 Client Component로 넘겨준다.
모든 페이지가 대부분 Client Comonent 이기 때문에 1번 방법을 선택했습니다.
Next.js 에서 제공하는 cookies 함수들은 Server 에서만 사용할 수 있으므로 Client Component에 사용하기에 적합하지 않습니다.
따라서, Client Component에서 사용할 수 있게 도와주는 cookies-next 라이브러리를 사용했습니다.
2. Client Component에서 Server Function 사용으로 인한 에러
🚨 문제 상황
Client Component에서 Server Function을 import 하거나 사용해서 오류가 발생했습니다.
Server Functions cannot be called during initial render. This would create a fetch waterfall.
Try to use a Server Component to pass data to Client Components instead.
🌱 해결책
- typeof window로 Client, Server 구분해서 확인하기
- Server Function을 import 만해도 오류가 발생을 하므로 import 해오는 시점을 서버인게 확인이 되면 import 한다. (코드 스플리팅)
export const cookieService = {
get: async (key: string) => {
if (typeof window === "undefined") {
const { cookies } = await import("next/headers");
return cookies().get(key);
}
const { getCookie: get_cookie } = await import("cookies-next");
return get_cookie(key);
},
set: async (key: string, value: string) => {
if (typeof window === "undefined") {
const { cookies } = await import("next/headers");
return cookies().set(key, value);
}
const { setCookie: set_cookie } = await import("cookies-next");
return set_cookie(key, value);
},
delete: async (key: string) => {
if (typeof window === "undefined") {
const { cookies } = await import("next/headers");
return cookies().delete(key);
}
const { deleteCookie: delete_cookie } = await import("cookies-next");
return delete_cookie(key);
},
};
따라서, 코드 스플리팅을 통해 Server와 Client를 구분하여 interceptor로 쿠키에 들어있는 AccessToken을 헤더에 넣도록 했습니다.
느낀점
처음으로 FE 팀원들과 BE 팀원들로 팀을 꾸려 프로젝트를 진행했습니다.
FE 팀원, BE 팀원들과의 협업으로 소통 역량과 협업 능력을 키울 수 있는 좋은 기회였습니다.
또한, Next.js 사용으로 Client Component와 Server Component을 적절히 사용하는 방법을 배우고, 여러 라이브러리를 사용해 보는 시간을 가졌습니다.
한 층 더 개발 실력을 향상했다고 느꼈습니다.