⚽ 구단주주총회
🖥️ 프로젝트 소개
온라인 게임인 FC ONLINE
의 API를 활용하여 게임 내 사용자의 전적을 확인하고 유저들과 소통할 수 있는 전적 & 커뮤니티
- 게임 내 전적을 그래프를 통해 수치화 하여 보여줄 수 있으며,
기존 다른 FC Online의 전적 검색 사이트와는 다르게 커뮤니티의 기능을 추가한 프로젝트 입니다.
🔗 배포 링크
구단 주주 총회 배포 링크
👨👩👧👦 팀 소개
🕰️ 개발 기간
총 개발 기간 : 24.10.10 ~ 24.10.16
프로젝트 기획 : 24.10.10 ~ 24.10.10
프로젝트 기본 세팅 : 24.10.11~24.10.11
기능 구현 완료 : 24.10.11 ~ 24.10.15
추가 구현 완료 : 24.10.15 ~ 24.10.16
📊 기술적 의사 결정
요구사항 | 선택지 | 사용 근거 |
---|
전역상태 라이브러리 | zustand | 과도한 props 사용을 방지하고 가벼운 전역 state 관리를 위해 zustand 사용 |
서버상태 라이브러리 | tanstack-query | 서버상태 관리를 쉽게 해주고 복잡한 비동기 로직을 단순화 하기 위해 사용 |
백엔드 서비스 | Supabase | 로그인 및 회원가입 서비스를 도와주는 백엔드 서비스와 게시물 관리를 위해 DB를 사용 |
글 작성 Tool | TOAST UI Editor | 글 작성 시 편의성을 극대화 하기 위해 TOAST UI Editor 사용 |
UI 통일성 | Shadcn | 전적 검색 시 Accordion이나 버튼, input등의 UI의 통일성/편의성을 위해 사용 |
📂 폴더 구조
폴더구조
📦9danjuju
┣ 📂public
┃ ┗ 📂img
┃ ┃ ┣ 📜anonPlayerImage.png
┃ ┃ ┣ 📜favicon.png
┃ ┃ ┣ 📜field_img.jpg
┃ ┃ ┗ 📜homeBackgroundImage.jpg
┣ 📂src
┃ ┣ 📂app
┃ ┃ ┣ 📂api
┃ ┃ ┃ ┣ 📂@modal
┃ ┃ ┃ ┃ ┗ 📂(...)detail
┃ ┃ ┃ ┃ ┃ ┗ 📂[nickname]
┃ ┃ ┃ ┣ 📂matchDetail
┃ ┃ ┃ ┃ ┗ 📜route.ts
┃ ┃ ┃ ┣ 📂matchId
┃ ┃ ┃ ┃ ┗ 📜route.ts
┃ ┃ ┃ ┣ 📂playerdata
┃ ┃ ┃ ┃ ┗ 📂detail
┃ ┃ ┃ ┃ ┃ ┗ 📜route.ts
┃ ┃ ┃ ┣ 📂playerposition
┃ ┃ ┃ ┃ ┗ 📂detail
┃ ┃ ┃ ┃ ┃ ┗ 📜route.ts
┃ ┃ ┃ ┣ 📂user
┃ ┃ ┃ ┃ ┗ 📂detail
┃ ┃ ┃ ┃ ┃ ┗ 📜route.ts
┃ ┃ ┃ ┗ 📂usermatch
┃ ┃ ┃ ┃ ┗ 📂detail
┃ ┃ ┃ ┃ ┃ ┗ 📜route.ts
┃ ┃ ┣ 📂community
┃ ┃ ┃ ┣ 📂write
┃ ┃ ┃ ┃ ┗ 📜page.tsx
┃ ┃ ┃ ┣ 📂[id]
┃ ┃ ┃ ┃ ┣ 📂modify
┃ ┃ ┃ ┃ ┃ ┗ 📜page.tsx
┃ ┃ ┃ ┃ ┗ 📜page.tsx
┃ ┃ ┃ ┣ 📜loading.tsx
┃ ┃ ┃ ┗ 📜page.tsx
┃ ┃ ┣ 📂detail
┃ ┃ ┃ ┗ 📂[nickname]
┃ ┃ ┃ ┃ ┗ 📜page.tsx
┃ ┃ ┣ 📂fonts
┃ ┃ ┃ ┣ 📜NEXON-Football-Gothic-B.otf
┃ ┃ ┃ ┗ 📜NEXON-Football-Gothic-L.otf
┃ ┃ ┣ 📂login
┃ ┃ ┃ ┣ 📜loading.tsx
┃ ┃ ┃ ┗ 📜page.tsx
┃ ┃ ┣ 📂modal
┃ ┃ ┣ 📂mypage
┃ ┃ ┃ ┣ 📜loading.tsx
┃ ┃ ┃ ┗ 📜page.tsx
┃ ┃ ┣ 📂signup
┃ ┃ ┃ ┣ 📜loading.tsx
┃ ┃ ┃ ┗ 📜page.tsx
┃ ┃ ┣ 📜error.tsx
┃ ┃ ┣ 📜globals.css
┃ ┃ ┣ 📜layout.tsx
┃ ┃ ┗ 📜page.tsx
┃ ┣ 📂components
┃ ┃ ┣ 📂auth
┃ ┃ ┃ ┗ 📜AuthForm.tsx
┃ ┃ ┣ 📂comments
┃ ┃ ┃ ┗ 📜Comment.tsx
┃ ┃ ┣ 📂community
┃ ┃ ┃ ┣ 📜CommunityActionButton.tsx
┃ ┃ ┃ ┣ 📜CommunityList.tsx
┃ ┃ ┃ ┣ 📜HomeCommunityList.tsx
┃ ┃ ┃ ┗ 📜PostEditor.tsx
┃ ┃ ┣ 📂detail
┃ ┃ ┃ ┣ 📜DetailGraph.tsx
┃ ┃ ┃ ┣ 📜MatchAccordion.tsx
┃ ┃ ┃ ┣ 📜MatchContainer.tsx
┃ ┃ ┃ ┣ 📜MatchDetailContents.tsx
┃ ┃ ┃ ┣ 📜MatchRateDetail.tsx
┃ ┃ ┃ ┣ 📜PlayerImage.tsx
┃ ┃ ┃ ┗ 📜UserInfoBox.tsx
┃ ┃ ┣ 📂Field
┃ ┃ ┃ ┗ 📜Field.tsx
┃ ┃ ┣ 📂layout
┃ ┃ ┃ ┗ 📜Header.tsx
┃ ┃ ┣ 📂mypage
┃ ┃ ┃ ┣ 📜MyInfo.tsx
┃ ┃ ┃ ┣ 📜MyPostsList.tsx
┃ ┃ ┃ ┣ 📜Nickname.tsx
┃ ┃ ┃ ┣ 📜Post.tsx
┃ ┃ ┃ ┣ 📜PostsTable.tsx
┃ ┃ ┃ ┗ 📜Selected.tsx
┃ ┃ ┣ 📂ui
┃ ┃ ┃ ┣ 📜accordion.tsx
┃ ┃ ┃ ┣ 📜button.tsx
┃ ┃ ┃ ┗ 📜input.tsx
┃ ┃ ┣ 📜LoadingSpinner.tsx
┃ ┃ ┗ 📜SearchBar.tsx
┃ ┣ 📂hooks
┃ ┃ ┣ 📜useGetMatchIdQuery.ts
┃ ┃ ┣ 📜useGetPlayersNameQuery.ts
┃ ┃ ┣ 📜useGetPositionQuery.ts
┃ ┃ ┗ 📜useMatchDetailDataQuery.ts
┃ ┣ 📂lib
┃ ┃ ┗ 📜utils.ts
┃ ┣ 📂provider
┃ ┃ ┗ 📜QueryProvider.tsx
┃ ┣ 📂types
┃ ┃ ┣ 📂detail
┃ ┃ ┣ 📜matchType.ts
┃ ┃ ┣ 📜maxDivisionType.ts
┃ ┃ ┗ 📜userInfoType.ts
┃ ┣ 📂utils
┃ ┃ ┣ 📂detail
┃ ┃ ┃ ┗ 📜datailApi.ts
┃ ┃ ┣ 📂mypage
┃ ┃ ┃ ┣ 📜api.ts
┃ ┃ ┃ ┗ 📜type.ts
┃ ┃ ┣ 📂services
┃ ┃ ┃ ┣ 📜matchDetailDataConverter.ts
┃ ┃ ┃ ┗ 📜utcTimeToKstConverter.ts
┃ ┃ ┣ 📂supabase
┃ ┃ ┃ ┣ 📜client.ts
┃ ┃ ┃ ┣ 📜middleware.ts
┃ ┃ ┃ ┗ 📜server.ts
┃ ┃ ┣ 📜client-action.ts
┃ ┃ ┗ 📜server-action.ts
┃ ┣ 📜middleware.ts
┃ ┗ 📜userStore.ts
┣ 📜.env.local
┣ 📜.eslintrc.json
┣ 📜.gitignore
┣ 📜.prettierrc
┣ 📜components.json
┣ 📜database.types.ts
┣ 📜next-env.d.ts
┣ 📜next.config.mjs
┣ 📜package.json
┣ 📜postcss.config.mjs
┣ 📜pull_request_template.md
┣ 📜README.md
┣ 📜tailwind.config.ts
┣ 📜tsconfig.json
┗ 📜yarn.lock
🧩 주요 기능
1. 회원 가입 및 로그인
SUPABASE
를 사용하여 회원가입과 로그인을 구현 후
ZUSTAND
를 사용해 로그인 여부를 전역상태로 관리합니다.
1-1. 회원가입
1-2. 로그인
2. 검색
3. 전적 확인
3-1-1. 유저 정보
- 검색한 유저의 정보와 전적을 확인할 수 있습니다.
3-2-1. 매치 타입
- 매치 타입에 맞는 전적을 확인할 수 있습니다.
3-3-1. 평점
- 특정 매치에 따른 선수 정보가 화면에 랜더링 되며, 클릭 시 모달로 선수 정보를 확인할 수 있습니다.
3-3-2. 슈팅
- 특정 매치의 슈팅 정보를 그래프로 확인할 수 있습니다.
3-3-3. 패스
- 특정 매치의 패스 정보를 그래프로 확인할 수 있습니다.
3-3-4. 수비
- 특정 매치의 수비 정보를 그래프로 확인할 수 있습니다.
4. 커뮤니티
4-1. 게시글 확인
- 무한 스크롤을 통해 페이지 이동 없이 전체 게시물을 확인할 수 있습니다.
4-2. 게시글 CRUD
TOAST UI EDITOR
를 사용하여 글쓰기를 할 수 있습니다.
5. 댓글
6. 마이페이지
- 가입 시 입력한 닉네임이
NEXON OPEN API
서버에 존재할 경우 해당 유저의 정보를 받아옵니다.
- 로그인 후 작성한 게시물을 확인할 수 있습니다.
🚨 트러블 슈팅
1. 랜더링 오류
1-1. 더보기 버튼 클릭 시 로딩 UI가 보이며 페이지가 깜빡 거리는 현상이 발생
- 기존 :
loading.tsx
를 통해 loading 상태일 때 loading UI를 보여줘야 함
1-2. 해결 방법
해결 : 한 페이지에서 관리하던 loading.tsx
를 Suspense
를 통해 로딩 UI를 보여줘야 하는 곳을 세분화,
전적 검색페이지는 예외로 useInfiniteQuery
의 isLoading
을 통해 로딩 UI를 넣어주어 매치타입이 변할 때만 로딩 UI가 보이도록 수정
2. TOAST UI Editor 오류
2-1. PostEditor 최상단에 "use client"를 선언하고 Write 페이지로 이동할 시 ReferenceError: navigator is not defined
에러가 발생
기존 : TOAST UI Editor Form이 나타나야 한다.
- app/community/write/page.tsx - CommunityWritepage (서버 컴포넌트)
components/community/PostEditor.tsx - (클라이언트 컴포넌트)
CommunityWritePage 컴포넌트안에 PostEditor 컴포넌트가 있고 PostEditor에서
Toast ui Editor 라이브러리를 사용하려고 하는 구조이다.
2-2. 해결 방법
해결 : dynamic 함수를 사용해서 컴포넌트를 ssr에서 제외 시켜 서버사이드에서 빌드를 무시하게 하였다. const PostEditor = dynamic(() => import('@/components/community/PostEditor'), { ssr: false });
자체 평가 의견
이름 | 점수 | 피드백 |
---|
권다정 | 8/10 | 팀프로젝트 하면서 CRUD를 온전히 맡아본 적이 없었는데 이번에 맡을 수 있어서 좋았고, 제가 두려워했던 것 중 하나인 zustand도 직접 사용해볼 수 있어서 대체적으로 만족스럽습니다. |
신한별 | 7/10 | 좀 더 깔끔한 코드를 작성하고 싶었는데 그러지 못했고, 아직 Next.js에 대한 이해도가 부족해서 장점을 활용하지 못한 것 같아 아쉽습니다! (ex. 모달을 parallel routes & Intercepting Routes로 구현). 하지만 생각했던 것들은 구현해서 만족스럽습니다. |
이기성 | 8/10 | Next.js의 렌더링 기법을 더 다양하게 사용해보고 싶었는데 그러지 못해서 아쉬운 점이 살짝 남았습니다. |
이석원 | 7/10 | 구상했던 기능들을 모두 구현했다는 점에서 많이 만족스럽지만, 서벅액션과 라우팅 핸들러에 대한 이해와 경험이 부족해서 아쉬움이 남는 것 같습니다. |
정지형 | 5/10 | "일단" 기능이 되긴 하기에 50점을 주었고, 코드 간결화가 안되어 있으며 API 함수도 제대로 관리하지 못하고 있습니다. |