Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

토이프로젝트2 2조 - Hogwartalk #5

Open
wants to merge 264 commits into
base: main
Choose a base branch
from
Open

Conversation

seungjun222
Copy link

호그와톡

💁 프로젝트 정보

주어진 API와 소켓을 활용한 채팅앱 제작 프로젝트입니다.

호그와트 학생 체험을 할 수 있도록 구성하였습니다.

개발기간: 2023.11.06 ~ 2023.11.16


🌐 배포 주소

배포 주소: https://hogwartalk.vercel.app/

테스트 계정 : ID : dumbledore / Password : dumbledore


🚖 개발 팀 소개

어승준 이승연 이승현 배경규 장문용
@seungjun222 @ewinkite @seungsimdang @kyungkyuBae @moonyah
채팅 기능 퀴즈, 클럽 페이지 관련 기능 채팅 기능 로그인/ 회원가입 기능 공통 컴포넌트(헤더 - 마이페이지, 친구 목록)

💻 개발 스택

환경

VSC GIT GITHUB

개발

Next.js REACT FIREBASE TYPESCRIPT Recoil

🌙 이슈 관리 및 소통

JIRA SLACK NOTION


🤝 협업 방식

커밋 컨벤션, 코딩 컨벤션, 깃허브 규칙 등의 내용은 아래의 노션 페이지를 참고해주세요!

🔗 노션 페이지



🤝 요구사항 반영 여부

필수 구현 사항

useStateuseReducer를 활용한 상태 관리 구현

Sass 또는 styled-component를 활용한 스타일 구현

react 상태를 통한 CRUD 구현

✅ 상태에 따라 달라지는 스타일 구현

custom hook을 통한 비동기 처리 구현

✅ 유저인증 시스템(로그인, 회원가입) 구현

jwt등의 유저 인증 시스템 (로그인, 회원가입 기능)

✅ 소켓을 이용한 채팅 구현

선택 구현 사항

Next.js를 활용한 서버 사이드 렌더링 구현

typescript를 활용한 앱 구현



🔍 팀원별 세부 구현 사항

어승준: 💬 채팅

image

1. 실시간 채팅

💡 소켓 연결을 통해 실시간 채팅을 할 수 있습니다. 클라이언트 화면 높이를 계산해 스크롤 맨 밑으로 이동 가능합니다.

2. 클럽 채팅방 생성 동적라우팅

💡 Next.js 동적라우팅을 통해 클럽 채팅방 생성 시, id, name값을 쿼리파라미터로 넘겨 정보에 맞게 페이지 렌더링을 시켜줍니다.

3. 내가 참여중인 대화방

💡 내가 참여중인 대화방을 보여줍니다. Polling 방식을 통해 latestMessages를 5초마다 업데이트 해줍니다.

이승연: 🌐 퀴즈, 클럽, 공통

1. 기숙사 배정 퀴즈 페이지 (회원가입)

시나리오에 따른 기숙사 배정 로직 구현

1퀴즈

💡 시나리오에 따라 답변을 클릭하면 점수가 누적되며, 이에 따른 기숙사 배정이 이루어집니다.
문항별 선택한 답변 정보를 저장하여 이전/다음 이동시에도 답변이 유지됩니다.

2. 클럽 페이지

채팅방 목록 조회

3채팅방목록조회

💡 네 개의 기숙사 채팅방을 제외한 모든 채팅방을 불러옵니다.
이때 update 일시를 기준, 최신순으로 정렬되어 노출됩니다.
로그인한 사용자가 참여중인 채팅방의 경우 개별적으로 표기합니다.

채팅방 생성

4채팅방생성

💡 새로운 채팅방을 생성하며, 생성이 완료되면 해당되는 채팅방으로 이동합니다.
제목은 필수값이며 채팅방 공개 여부 설정에 따라 목록 조회가 업데이트 됩니다.

채팅방 참여

5채팅방참여

💡 현재 참여중인 채팅방의 경우 바로 해당되는 채팅방으로 이동하며,
참여중이지 않은 채팅방의 경우 참여 여부를 묻는 다이얼로그가 노출됩니다.

3. 공통

로딩 페이지

2클럽로딩

💡 API 호출 중 로딩 페이지가 노출됩니다.

BGM(헤더)

6BGM

💡 홈페이지 최초 진입 후 특정 영역을 클릭시 BGM이 재생됩니다.
헤더에서 아이콘을 통해 제어가 가능하며, 경로 이동되어도 재생 상태가 유지됩니다.

이승현: 💬 채팅

1. 기숙사 선택 페이지

image

💡 로그인 후에 처음으로 표시되는 페이지입니다.
사용자가 배정받은 기숙사 채팅방만 입장할 수 있으며, 가운데의 클럽 로고를 누르면 클럽 페이지로 이동합니다.

2. 채팅방

채팅방 헤더

image

💡 채팅방에 참여, 초대를 받아 현재 채팅방의 제목과 인원수가 표시됩니다.
노란 뱃지를 눌러 사용자를 초대할 수 있으며 더보기 버튼을 눌러 채팅방 정보를 보거나 채팅방에서 나갈 수 있습니다.

채팅방 초대 모달

image

💡 기숙사 채팅방을 제외한 모든 클럽 채팅방에서 사용자를 초대할 수 있습니다.
현재 채팅방에 참여하고있는 사람을 제외한 모든 사용자가 보여지며, 사용자의 프로필 사진, 닉네임, 기숙사 정보가 표시됩니다.

채팅방 정보 모달

image

💡 현재 채팅방의 정보를 보여줍니다.
채팅방 제목, 인원수, 호스트 이름, 채팅방 개설일, 참여자 목록을 확인할 수 있습니다.

배경규: 🔑 로그인/ 회원가입

로그인시 Jwt토큰 발급하여 쿠키에 저장

login__token

토큰은 액세스 토큰,리프레시 토큰

회원가입

signup

제공된 api의 이미지 용량이슈 때문에 타db를 사용하여 이미지를 저장하고 url사용
회원가입시 빈칸 있는지 유효성 검사
중복된 아이디가 있는지 체크
퀴즈를 보러가도 회원가입 폼 상태저장

모든 페이지에서 액세스 토큰 만료시 재발급

Retoken

모든 페이지에서 액세스토큰 만료시 axios 요청 가로채서 인터셉터로 액세스토큰을 재발급 하는 로직구현

권한 없을 시(리프레시 토큰x) 로그인 페이지 유도

로그인페이지유도

로그인 페이지 유도

장문용: 📑 공통 컴포넌트

1. 헤더 제작

header

💡각 아이콘은 클릭 및 토글 상태에 따라 스타일이 변합니다.

2. 마이페이지 토글

MyPageToggle 컴포넌트는 사용자의 프로필 정보를 표시하고 편집하는 기능을 제공하는 사이드바입니다.

로그인된 사용자 정보 표시

mypage_1

💡쿠키에 저장된 accessToken을 사용해 이름을 가져오고 Firebase Storage에서 프로필 이미지, Firebase Database에서 기숙사 정보를 가져옵니다.

로그인된 사용자 정보 편집하기

mypage_2

💡사용자가 편집 모드로 전환하면 이름, 기숙사, 프로필 이미지를 변경할 수 있습니다. 각 변경 사항은 제공된 서버와 Firebase에 업데이트됩니다.

3. 친구목록 토글

FriendSearchToggle 컴포넌트는 친구를 검색하고 확인하는 역할을 하는 사이드바입니다.

사용자 목록 출력 (이름, 기숙사 정보, 접속 유무 표시)

userlist

💡 서버와 소켓 통신을 통해 전체 유저와 접속 중인 유저 정보를 가져와, 각 사용자의 접속 상태를 실시간으로 표시합니다. Firebase 데이터베이스에서는 사용자의 기숙사 정보를 가져옵니다.

화면에는 각 사용자의 프로필 이미지, 이름, 학급, 그리고 실시간으로 변하는 접속 상태가 표시됩니다. 사용자의 기숙사 정보도 표시되며, 데이터는 계속해서 업데이트되어 화면에 실시간으로 반영됩니다.

4. 로그아웃

페이지 이동 & 쿠키 삭제

logout

💡로그아웃 버튼을 누르면 로그인 페이지로 이동하고 js-cookie 라이브러리를 사용하여 'accessToken'과 'refreshToken' 쿠키를 삭제하여 로그아웃을 수행합니다.

kyungkyuBae and others added 30 commits November 8, 2023 18:55
…info-toggle

Feat: MyPage토글, FriendSearch토글 UI/UX
@seungjun222 seungjun222 self-assigned this Nov 17, 2023
gahyuun added a commit that referenced this pull request Nov 17, 2023
Design: 전체 레이아웃 구성 및 폰트 , 테마 설정
dbstjrals pushed a commit that referenced this pull request Nov 17, 2023
기능개발 브랜치 생성을 위해 dev브랜치로 pullrequest한다.
JeongMin83 pushed a commit that referenced this pull request Nov 17, 2023
Feat: 토큰 세션 임시 저장 처리
jseo9732 added a commit that referenced this pull request Nov 18, 2023
Talk 6  feat/chat 채팅페이지 구성
Yamyam-code pushed a commit that referenced this pull request Nov 18, 2023
Feat: login token 생성 및 localstorage 저장 기능
noSPkeepgoing added a commit that referenced this pull request Nov 18, 2023
Fix setting & Modify pocketRequest & Add feature of lobby , role
LeHiHo added a commit that referenced this pull request Nov 18, 2023
LeHiHo added a commit that referenced this pull request Nov 18, 2023
로그인, 회원가입 구현
Copy link

@LEEJAEHYUB LEEJAEHYUB left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체적으로 모두 구현을 잘하시고 어려우 부분을 잘해결해 나갔던 것 같습니다.
모든 분들 자기가 맡은 역할을 잘해내셨고 고생많으셨습니다!!
이번 토이프로젝트를 통해 프론트팀 내에서 소통하는법, 업무분배, 코드 싱크 맞추기 등의 연습을 잘 해내신 것 같습니다. 앞으로 남은 실전 미니프로젝트, 파이널 프로젝트에서도 좋은 역량 잘 발휘하시길 바라겠습니다! 고생하셨습니다 :)

}

export interface ResponseValue {
messgae: string;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오타를 조심하세요!

import { MyChatting } from '@components/MyChatting';
import { Header } from '@components/Header';

export default function ClubChatting(props: any) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

props로 any타입을 지정하기 보다는 구조분해 할당으로 ({param})을 받고 해당 타입을 지정해주는 게 더 좋아보입니다.


import { Dormitory } from '@components/Dormitory';

const ClubChatting = (id: any, name: any) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id: number, name: string 으로 보통 타입을 받을 수 있겠죠


const ClubChatting = (id: any, name: any) => {
if (!id || !name) {
return <div style={{ backgroundColor: 'white' }}>로딩중...</div>;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인라인 스타일은 급한 경우를 제외하고는 지양하는게 좋습니다.

return (
<>
<Header />
<div

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인라인스타일이 꼭 나쁜건 아니지만 최대한 클래스나 스타일드 컴포넌트를 이용해보아요

<styled.ParticipantsWrapper>
<styled.ParticipantsGrid>
{users?.map((user, index) => (
<UserItem key={index}>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map을 돌릴때 key값에 index보다는 고유한 값이 있다면 고유한 값으로 넣어주는게 좋습니다.
ex. key={user.id}

// extraHeaders: headers,
// });
const chatSocket = useMemo(() => {
return io(`https://fastcampus-chat.net/chat?chatId=${chatId}`, {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

endpoint는 상수화해서 재사용하거나 은닉하는 것도 좋은 방법입니다.

import { getToken } from '@utils/service';
import UserIcon from '@assets/icon/UserIcon.svg';

type ResponseValue = any;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정확한 타입을 지정해주는게 좋을 것 같습니다.

minute: 'numeric',
});

return (

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반복되는 컴포넌트에서 마크업의 양이 많고 로직이 많이 들어가면 따로 컴포넌트를 분리하는 것 이 유지보수에 유리합니다.

}
setDormitoryState(true);

if (!isThere) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정답은 아니지만, 보통 좀 더 짧고, 코드의 중첩을 줄이기 위해 조건을 만족하는 경우 함수를 빠르게 return 시키는 패턴으로 작성하면 좋습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants