[TIL] Next.js 심화프로젝트!

기성·2024년 10월 17일

TIL

목록 보기
71/97

⚽ 구단주주총회

🖥️ 프로젝트 소개

온라인 게임인 FC ONLINE의 API를 활용하여 게임 내 사용자의 전적을 확인하고 유저들과 소통할 수 있는 전적 & 커뮤니티

  • 게임 내 전적을 그래프를 통해 수치화 하여 보여줄 수 있으며,
    기존 다른 FC Online의 전적 검색 사이트와는 다르게 커뮤니티의 기능을 추가한 프로젝트 입니다.

🔗 배포 링크

구단 주주 총회 배포 링크

👨‍👩‍👧‍👦 팀 소개

🧡권다정💛신한별💚이기성💙이석원💜정지형
@kwondajung@star1024cd@Leekee0905@seokwon27@stopbrother
커뮤니티 댓글 CRUD
ZUSTAND로 로그인 정보 전역 상태 관리
플레이 정보를 바탕으로 한 평점 페이지 및 상세 모달 구현로그인/회원가입
유저 검색
전적 검색 카테고리 내 데이터 활용(그래프)
마이페이지 구현(닉네임 변경 및 작성 게시글 확인)TOAST UI EDITOR를 활용한 커뮤니티 게시판 CRUD

🕰️ 개발 기간

총 개발 기간 : 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를 사용
글 작성 ToolTOAST 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

🧩 주요 기능

image

1. 회원 가입 및 로그인

SUPABASE를 사용하여 회원가입과 로그인을 구현 후
ZUSTAND를 사용해 로그인 여부를 전역상태로 관리합니다.

1-1. 회원가입

image

1-2. 로그인

image
image

  • 로그인 시 헤더에서 유저 정보 확인

2. 검색

search

  • 닉네임 검색으로 전적을 검색할 수 있습니다.

3. 전적 확인

image
more

3-1-1. 유저 정보

image

  • 검색한 유저의 정보와 전적을 확인할 수 있습니다.

3-2-1. 매치 타입

image
image

  • 매치 타입에 맞는 전적을 확인할 수 있습니다.

3-3-1. 평점

image
image

  • 특정 매치에 따른 선수 정보가 화면에 랜더링 되며, 클릭 시 모달로 선수 정보를 확인할 수 있습니다.

open

3-3-2. 슈팅

image

  • 특정 매치의 슈팅 정보를 그래프로 확인할 수 있습니다.

3-3-3. 패스

image

  • 특정 매치의 패스 정보를 그래프로 확인할 수 있습니다.

3-3-4. 수비

image

  • 특정 매치의 수비 정보를 그래프로 확인할 수 있습니다.

4. 커뮤니티

4-1. 게시글 확인

image

  • 게시글 목록을 확인할 수 있습니다.

muhan345

  • 무한 스크롤을 통해 페이지 이동 없이 전체 게시물을 확인할 수 있습니다.

image

  • 상세 게시물을 확인할 수 있습니다.

4-2. 게시글 CRUD

image
TOAST UI EDITOR를 사용하여 글쓰기를 할 수 있습니다.

image
image
image

  • 게시글을 수정 할 수 있습니다.

5. 댓글

image

  • 댓글을 작성할 수 있습니다.

image
image

  • 댓글을 수정/삭제할 수 있습니다.

6. 마이페이지

image

  • 가입 시 입력한 닉네임이 NEXON OPEN API서버에 존재할 경우 해당 유저의 정보를 받아옵니다.
  • 로그인 후 작성한 게시물을 확인할 수 있습니다.

🚨 트러블 슈팅

1. 랜더링 오류

1-1. 더보기 버튼 클릭 시 로딩 UI가 보이며 페이지가 깜빡 거리는 현상이 발생

  • 기존 : loading.tsx를 통해 loading 상태일 때 loading UI를 보여줘야 함

1-2. 해결 방법

image


해결 : 한 페이지에서 관리하던 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. 해결 방법

image


해결 : 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/10Next.js의 렌더링 기법을 더 다양하게 사용해보고 싶었는데 그러지 못해서 아쉬운 점이 살짝 남았습니다.
이석원7/10구상했던 기능들을 모두 구현했다는 점에서 많이 만족스럽지만, 서벅액션과 라우팅 핸들러에 대한 이해와 경험이 부족해서 아쉬움이 남는 것 같습니다.
정지형5/10"일단" 기능이 되긴 하기에 50점을 주었고, 코드 간결화가 안되어 있으며 API 함수도 제대로 관리하지 못하고 있습니다.

profile
프론트가 하고싶어요

0개의 댓글