Skip to content

Minju9187/final-07-gymnect

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🏋️‍♀️ 짐넥(GYM-NECT) 🏋️‍♀️

배포용 썸네일 이미지

🏋️‍♀️💪 운동을 기록하고 서로 공유하는 운동 아카이빙 SNS 플랫폼, 짐넥(Gym-Nect)


React Recoil React-Router

Axios StyledComponents Prettier


🗝️ 짐넥 배포 링크 및 테스트 계정

👉 짐넥 시작하기

ID: [email protected]
PW: !123123a

⭐ 0. 목차

  1. 서비스 소개
  2. 짐넥 팀원 소개
  3. 역할 분담
  4. 개발 일정
  5. 개발 환경 및 기술 스택
  6. 프로젝트 폴더 구조
  7. Git Branch 전략 - Github Flow
  8. 짐넥에서는 이렇게 협업해요
  9. 주요 기능 소개
  10. 상세 담당 업무
  11. 핵심 코드
  12. 트러블 슈팅
  13. 리팩토링 할 부분
  14. 리팩토링 한 부분

📢 1. 서비스 소개

짐넥(GymNect)은 GYM + CONNET의 합성어로, 단순히 운동을 기록하는것을 넘어, 사람들을 서로 연결하고 삶과 운동을 연결하는 것을 목표로 하는 온라인 플랫폼입니다! 우리는 운동 기록을 쉽게 저장하고 관리할 수 있는 기능을 제공함으로써, 운동의 진전을 추적하고, 개인적인 성취를 달성할 수 있도록 돕습니다. 또한, 사용자들이 자신의 운동 경험과 성과를 친구들과 공유함으로써, 서로를 동기부여하고, 건강한 경쟁을 통해 즐거움을 나눌 수 있는 커뮤니티를 조성하였습니다. 여러분의 삶에 활력을 더하고, 매일의 운동이 삶의 가치 있는 부분이 될 수 있도록 짐넥이 함께합니다.



🐈 2. 짐넥 팀원 소개

안녕하세요. 저희는 멋쟁이사자처럼 프론트엔트 스쿨 7기의 7조 🌠우주연가🌠 입니다!

(영)우+(민)주+연(정)+가(람) 네명의 팀원 이름으로 팀명을 지으며, 프로젝트를 통해 모두가 같은 마음으로 함께 이루어나가자는 의미를 담았습니다!


✴️ 3. 역할 분담


📅 4. 개발 일정

🐥 2023.10.12 - 2023.11.09



⚙️ 5. 개발 환경 및 기술 스택


왜 라이브러리를 사용했을까?


컨벤션

prettier

module.exports = {
  semi: true,  // 코드를 종료할 때 세미콜론을 사용
  printWidth: 80,  // 한 줄에 최대 80 개의 문자를 허용
  tabWidth: 2,  // 탭으로 들여쓰기 할 때, 탭의 너비 = 2
  singleQuote: false,  // 문자열을 작성할 때 큰따옴표를 사용
  jsxSingleQuote: false,  // JSX에서 문자열을 작성할 때 큰따옴표를 사용
  trailingComma: "none",  // 객체나 배열 등에서 마지막 요소 뒤에 콤마를 붙이지 않음
  bracketSpacing: true,  // 객체 리터럴에서 중괄호 안에 공백을 넣음
  bracketSameLine: true,  // 객체 리터럴의 닫는 중괄호를 같은 줄에 배치
  arrowParens: "always"  // 화살표 함수의 매개변수를 감쌀 때 항상 괄호를 사용
};

커밋 컨벤션

Feat: 기능 추가, 삭제, 변경
Fix: 버그, 오류 수정
Docs: 리드미, json 파일 등 수정, 라이브러리 설치 (문서 관련, 코드 수정 없음)
Design: CSS 등 사용자 UI 디자인 변경 (제품 코드 수정 발생, 코드 형식, 정렬 등의 변경)
Refactor: 코드 리팩토링
Test: 테스트 코드 추가, 삭제, 변경 등 (코드 수정 없음, 테스트 코드에 관련된 모든 변경에 해당)
Chore: 패키지 매니저 설정할 경우, etc 등 (ex. gitignore)
Comment:	필요한 주석 추가 및 변경
Rename:	파일 또는 폴더 명을 수정하거나 옮기는 작업만인 경우
Remove:	파일을 삭제하는 작업만 수행한 경우


📂 6. 프로젝트 폴더 구조

  🌌우주연가

  🔭public
  ┣ 🌠favicon.ico
  ┗ 🌠index.html
  🔭src
  ┣ 🌠api
  ┃ ┣🪐auth.js
  ┃ ┣🪐axiosInstance.js
  ┃ ┣🪐comment.js
  ┃ ┣🪐follow.js
  ┃ ┣🪐post.js
  ┃ ┣🪐profile.js
  ┃ ┗🪐search.js
  ┣ 🌠assets
  ┃ ┣🪐images
  ┃ ┗🪐sprite
  ┣ 🌠atoms
  ┃ ┣🪐LoginAtom.js
  ┃ ┗🪐UserAtom.js
  ┣ 🌠components
  ┃ ┣ 🪐common
  ┃ ┃ ┣🪐Alert
  ┃ ┃ ┣🪐Button
  ┃ ┃ ┣🪐Comment
  ┃ ┃ ┣🪐Input
  ┃ ┃ ┣🪐Loading
  ┃ ┃ ┣🪐Modal
  ┃ ┃ ┣🪐Post
  ┃ ┃ ┗🪐Profile
  ┃ ┣ 🪐Footer
  ┃ ┣ 🪐Header
  ┃ ┗ 🪐Layout
  ┣ 🌠pages
  ┃ ┣ 🪐Calendar
  ┃ ┣ 🪐Chatting
  ┃ ┣ 🪐Error
  ┃ ┣ 🪐FollowList
  ┃ ┣ 🪐Home
  ┃ ┣ 🪐Login
  ┃ ┣ 🪐Posting
  ┃ ┣ 🪐Profile
  ┃ ┣ 🪐Signup
  ┃ ┣ 🪐Splash
  ┃ ┣ 🪐Upload
  ┣ 🌠routes
  ┃ ┣🪐AppRouter.jsx
  ┃ ┗🪐ProtectedRoute.jsx
  ┣ 🌠styles
  ┃ ┣🪐GlobalStyle.js
  ┃ ┗🪐Theme.jsx
  ┣ 🌠utils
  ┃ ┗🪐getTime.js
  ┣ 🌠App.js
  ┣ 🌠index.js
  🔭.gitignore
  🔭.prettierrc.js
  🔭package-lock.json
  🔭package.json
  🔭README.md

🪐 7. Git Branch 전략 - Github Flow

기능 브랜치를 사용한 작업 분리

  • feature 워크플로를 사용하여 각 기능을 분리해서 작업이 가능하기 때문에, 각 팀원이 독립적으로 기능을 개발 가능
  • 각 브랜치마다 책임이 명확하기 때문에 개발 이력을 추적하고 관리하는 것이 용이

지속적인 개발과 협업

  • 각 기능 브랜치는 완성되면 팀원의 리뷰 과정을 거쳐 develop 브랜치로 병합되기 때문에, 코드 리뷰를 통해 서로의 작업을 검토하고 피드백 제공 가능
  • 코드의 품질을 높이고 안정성을 확보할 수 있으며 문제가 발생했을 때 원인 파악과 해결이 용이

🪐 8. 짐넥에서는 이렇게 협업해요

코드리뷰

  • 스크럼 : 매일 오전 9시와 오후 5시에 진행하여 역할을 분담하고, 각 팀원들의 진행 상황과 겪고 있는 문제를 공유하며, 해결 방안에 대한 논의하였습니다.

  • 깃 플로우 전략 : 깃플로우 전략을 기능구현 페이지에 맞춰 활용함으로써 이슈 및 브랜치를 효율적으로 관리하여 충돌을 대비했습니다. 분담 된 이슈에 대해 각각 컨벤션에 맞춰 브랜치명과 커밋을 작성 함으로써 진행 상황에 대한 빠른 이해를 도왔습니다. 일일 작업을 마치면 DEVELOP으로 MERGE하고 PULL하여 작업이 정상적으로 작동되는지 확인합니다. 각자 PULL한뒤에 발생되는 오류가 있다면 회의를 통해 수정 및 재작업(브랜치 재생성)을 합니다.

  • 노션 : 하루 2회 이상 진행 되었던 스크럼 내용을 기록하고, 각 팀원들의 TodoList를 작성하여 체크함으로써 일정에 맞춰 작업진행이 원활하게 진행 됐습니다.

  • 디스코드 라이브 : 화면공유를 통해 구현하고자 하는 기능에 대한 정확한 이해 및 의견을 나눴으며, 문제 발생 시 실시간으로 함께 해결하는 과정의 도구로 유용하게 사용 됐습니다.


🪐 9. 주요 기능 소개

1) 홈

스플래쉬 화면 로그인 화면 회원가입 화면
스플래쉬 화면 로그인 화면 회원가입 화면
프로필 설정 화면 검색 화면 홈 피드 화면
프로필 설정 화면 검색 화면 홈 피드 화면

2) 채팅 & 404 & 운동 관리 & 로딩 화면

채팅방 화면 404 페이지 운동분석 화면
채팅방 화면 404 페이지 운동분석 화면
캘린더 화면 로딩 화면
캘린더 화면 로딩 화면

3) 게시글

상세 페이지 화면 게시물 작성 - 운동 선택 게시물 작성 - 인풋 삭제
상세 페이지 화면 게시물 작성 - 운동 선택 게시물 작성 - 인풋 삭제
게시글 작성 - 업로드 게시물 삭제
업로드 화면 삭제 페이지 화면
게시물 신고하기 화면 게시글 보기 방식 변경 화면 좋아요 화면
게시물 신고하기 화면 게시글 보기 방식 변경 화면 좋아요 화면
댓글 달기 화면 댓글 삭제 화면 댓글 신고 화면
댓글 달기 화면 댓글 삭제 화면 댓글 신고 화면

4) 프로필

마이 프로필 화면 상대방 프로필 화면 프로필 수정 화면
마이 프로필 화면 상대방 프로필 화면 프로필 수정 화면
팔로워 팔로잉 화면 로그아웃 화면
팔로워 팔로잉 화면 로그아웃 화면

🪐 10. 상세 담당 업무

🖤 공통

  • 컨벤션 지정
    • 커밋 메시지 컨벤션, 코드 컨벤션, 네이밍 컨벤션, 디렉토리 구조
  • 프로젝트 관리
    • 이슈 관리
    • 이슈 진행 상황 관리
    • 버그 관리
    • 요구사항 문서 작성

🖤 민주

📜 프로젝트 총괄

  • 코드 오류 분석 및 수정
  • 프로젝트 초기 세팅 작업
  • Netlify를 이용한 프로젝트 배포

💻 화면 개발

  • 공통 버튼 컴포넌트
  • 공통 인풋 컴포넌트
  • Splash
    • keyframes를 이용해 전구가 켜지는듯한 애니메이션을 넣음
  • 회원가입
  • 프로필
  • 상세 게시물
    • 공통 Post 컴포넌트
    • Comment 컴포넌트

⚙️ 기능 개발

  • 회원가입
    • 실시간으로 아이디, 비밀번호, 유효성 검사
  • 회원가입 프로필 설정
    • 이름, UserId 유효성 검사
    • 이미지 안넣을시 기본 이미지로 대체 기능 구현
  • 프로필
    • recoil를 이용한 로그아웃 기능 구현
    • 프로필 수정 기능 구현
    • useParams를 사용해 UserId에 따라 마이프로필 / 아더프로필 화면 렌더링
    • 작성한 게시물들 실시간으로 렌더링
    • 이미지 있는 게시물들만 가져와 grid 형태로 렌더링 / 이미지 클릭시 해당 게시물로 이동
    • 누락된 이미지를 예외 처리 후 기본 이미지로 렌더링
  • 상세 게시글
    • Post 컴포넌트
      • 좋아요 갯수가 실시간으로 렌더링
      • 댓글 갯수가 실시간으로 렌더링
      • 팔로우, 팔로잉 숫자가 실시간으로 렌더링
      • 게시글 데이터를 가져와 화면에 렌더링
      • 게시물 프로필 클릭 시 해당 프로필로 이동 / 이미 프로필로 이동했을시 클릭 못하도록 기능 구현
      • 게시물 정보창 클릭 시 상세 게시물로 이동 / 이미 상세 게시물로 이동했을시 클릭 못하도록 기능 구현
      • 한정된 데이터 공간에 넣은 압축된 데이터를 정제 후 원하는 대로 데이터 출력
      • 누락된 이미지를 예외 처리 후 기본 이미지로 렌더링
  • 팔로잉
    • 팔로잉 버튼 컴포넌트 제작
      • 본인 계정과 일치할 경우 팔로워, 팔로잉 버튼 생략
    • 실시간 팔로잉, 팔로워 반영

🖤 영우

📜 프로젝트 구상

  • 프로젝트 전반적인 컨셉과 아이디어 구상
  • 프로젝트 이름 구상

🖥️ 화면 개발

  • 로그인 화면
  • 검색 화면
  • 채팅 화면
  • 로딩 화면
  • 홈화면 팔로워 있을때
  • 운동분석 모달창

⚡ 기능 개발

  • 로그인 기능
    • 서버에 로그인 요청을 보내고 응답에 따라 사용자 인터페이스를 업데이트
    • 사용자의 로그인 정보를 Recoil 상태에 저장하고, 로컬 스토리지에 토큰을 저장한 후 홈 경로로 리다이렉트
    • 정규 표현식을 사용하여 입력값이 올바른 형식인지 확인하는 유효성검사 후 실패시 에러메시지 출력
    • 로그인 데이터가 일치하지 않으면 떨리는 애니매이션효과 구현
  • 홈화면 피드
    • API 함수를 호출하여 팔로우하는 사람들의 게시물 데이터를 피드화면에 보여주고 만약 없다면 NoFollowerHome컴포넌트 보여줌
  • 리액트 라우터 보호기능
    • 로그아웃 된 상태에서 주소창 입력으로 내부로 접근하지 못히도록 ProtectedRoute구현 (리코일 atom을 이용하여 로그아웃 상태인지 검사 후 라우터 주소 반환)
    • 로그인 된 상태에서 주소창 입력으로 로그인 창에 접근하지 못하도록 막고 경고창 띄움.
  • 채팅 기능
    • 메시지를 리스트에 넣어 화면에 띄우고 새로운 메시지가 추가될때마다 아래쪽으로 스크롤되는 기능 추가
    • 사진업로드 기능 및 현재시간 출력하는 기능 추가
    • 채팅리스트에서 useParams훅을 이용하여 채팅상대 이름 가져와서 헤더에 출력
  • 검색 기능
    • 검색어가 변경될때마다 API 함수를 호출하여 검색결과 가져옴
    • 프로필이미지 없는 사용자의 이미지 예외 처리 후 기본이미지 렌더링
  • 로딩기능
    • useEffect훅을 사용하여 서버에서 데이터를 받아오는동안 로딩화면 렌더링

🖤 가람

📜 프로젝트 문서화 및 데이터 가공

  • 커뮤니케이션
    • 프로젝트 기간 동안 일 2회 이상 회의의 진행 상황과 목표를 지속적으로 공유하여 노션에 작성
  • 프로젝트 진행을 위한 작업
    • 기능구현 확인을 위한 데이터 가공 및 수집
    • GitHub 리드미 작성 및 사용 UI gif 생성
    • GitHub 이슈 템플릿, PR 템플릿 등록

🖥️ 화면 개발

  • 게시글 삭제, 신고하기, 로그아웃 등의 알럿 & 모달 공통 컴포넌트 제작
    • DeleteAlert, LogoutAlert, ReportAlert
    • AnalysisModal, DeleteEditModal, PostModal
  • Splash 후 로그인 모달 애니메이션
    • LoginModal
  • 회원가입 후 프로필 설정
  • 프로필 수정
  • 404 페이지 퍼블리싱
  • 게시물 나열 방식(기본-그리드 상호 변경)
  • 운동분석 모달창

⚡ 기능 개발

  • 로딩 페이지
    • 회원가입 후 로그인 모달이 올라오는 로딩페이지
  • 팔로워 목록 및 팔로워 취소&팔로우
    • 팔로워 목록을 getFollowerList로 서버에 요청하여 리스트 출력
    • 팔로우, 언팔로우를 서버에 요청하고 postFollow를 화면에 바로 적용

♻️ 컴포넌트 리팩토링 및 중복 제거

  • 컴포넌트 리팩토링 및 중복 제거
    • 로그인시 사용되는 화면과 스플래시 후 올라오는 로그인 모달창에서 사용되는 Form이 공통적으로 사용되어 LoginForm 컴포넌트로 분리

🖤 연정

🎨 디자인 담당

  • 전체적인 UI 디자인
  • 로고 디자인 및 이미지 제작

🖥️ 화면 개발

  • 공통 헤더 네브바
  • 공통 푸터 네브바
  • 공통 BasicLayout 레이아웃
  • 팔로잉 없을 때 홈 화면
  • 채팅방 목록
  • 캘린더
  • 팔로잉, 팔로워 목록
  • 게시글 등록 페이지
  • 백그라운드 배경
  • 삭제 / 신고 모달창

기능

  • 라우터 초기 셋팅
  • 게시물 등록
    • 여러 운동을 선택할 수 있게 토글 기능 추가 및 선택한 운동마다 작성할 수 있는 인풋창이 다르게 설정
    • 토글 Open, Close에 따라 인풋창 높이 자동 조절
    • api 전송 한계로 인해 한 공간에 저장하여 보낼 수 있게, 데이터를 연산자로 구분하여 한줄로 전송
    • 이미지 추가 및 삭제 가능
  • 캘린더
    • 최대 6개월까지 렌더링되도록 제한된 무한 스크롤 기능
    • 현재 날짜에 회색 원, 게시글 작성 목록 데이터를 가져와 업로드날짜만 추출하여 게시글을 작성한 날에만 파란 원이 채워지게 구현
    • 게시글을 작성한 날에만 마우스가 호버되며 클릭시 작성된 게시글 상세 페이지로 이동
  • 게시글 삭제 / 신고
    • userId를 통해 유저를 구별하여 타인의 경우 신고 기능, 본인일 경우 삭제 기능 구현
  • 댓글 작성 / 신고 / 삭제
    • 시간 계산 기능을 통해 작성 시간에 따라 지나간 시간을 계산해서 표시
    • userid를 통해 댓글 작성 input 창에 작성자의 프로필 사진을 렌더링
    • 댓글 목록에서 누락된 이미지를 예외 처리 후 기본 이미지로 렌더링
    • userId를 통해 유저를 구별하여 타인의 경우 신고 기능, 본인일 경우 삭제 기능 구현
  • 공통 헤더 네브바 컴포넌트
    • BackspaceHeader, HomeHeader, ModalHeader, ProfileEditHeader, SearchHeader, UploadHeader
  • 공통 푸터 네브바 컴포넌트
    • Navbar
  • 공통 레이아웃 컴포넌트
    • BasicLayout


🪐 11. 핵심 코드

주어진 API에서 데이터 필터링하기

운동 종류를 선택하는 시스템을 구축했고, 여기서 사용자가 근력 운동을 선택하면, 해당 운동의 이름과 사용하는 무게, 그리고 반복 횟수를 입력할 수 있습니다. 만약 걷기, 달리기, 등산, 자전거 타기와 같은 유산소 운동을 선택하면, 사용자는 이동 거리를 킬로미터 단위로 입력할 수 있습니다. 다른 운동을 선택한 경우에는 운동의 종류만 표시됩니다.

저장 공간의 한계로 인해, 우리는 데이터를 '&&&&'로 구분하여 한 공간에 저장하도록 설정했습니다. 이 구분자를 기준으로 데이터를 분류하고, 이를 통해 사용자가 원하는 정보를 정확하게 출력할 수 있도록 했습니다.

//데이터 저장
  const createApiData = () => {
    let contentData = postContent;
    let imageString = uploadedImages.join(", ");
    let exerciseData = "";

    if (selectedValue === "근력 운동") {
      exerciseData = exerciseEntries
        .map((entry) => {
          return `${entry.name}-${entry.sets
            .map((set) => `${set.weight}x${set.reps}`)
            .join(", ")}`;
        })
        .join(";");
      exerciseData = `${exerciseData}`;
    } else if (
      ["걷기", "달리기", "등산", "자전거 타기"].includes(selectedValue)
    ) {
      exerciseData = `${distanceInput}km`;
    } else {
      exerciseData = `${selectedValue}`;
    }

    let timeData = `${hour}시간 ${minute}분`;

    contentData = `${selectedValue}&&&&${exerciseData}&&&&${contentData}&&&&${timeData}`;
//데이터 정제
if (kind === "근력 운동") {
  return (
    <>
      {data.split(";").map((item1, idx1) => {
        const arr2 = item1.split("-");
        return (
          <HealthWrap key={`item1-${idx1}`}>
            <HeaderWrap>
              <Logo />
              <HealthKind>{arr2[0]}</HealthKind>
            </HeaderWrap>
            {arr2.slice(1).map((item2, idx2) => {
              return (
                <HealthCntWrap key={`group-${idx1}-${idx2}`}>
                  {item2.split(",").map((item3, idx3) => {
                    const arr = item3.split("x");
                    return (
                      <DataWrap key={`item2-${idx1}-${idx2}-${idx3}`}>
                        <DataKg>{arr[0]} kg</DataKg>
                        <DataCnt>{arr[1]}</DataCnt>
                      </DataWrap>
                    );
                  })}
                </HealthCntWrap>
              );
            })}
          </HealthWrap>
        );
      })}
    </>
  );
} else if (
  kind === "걷기" ||
  kind === "달리기" ||
  kind === "등산" ||
  kind === "자전거 타기"
) {
  return (
    <>
      <HealthWrap>
        <HeaderWrap>
          <Logo />
          <HealthKind>{kind}</HealthKind>
        </HeaderWrap>
        <HealthCnt>{data}</HealthCnt>
      </HealthWrap>
    </>
  );
} else {
  return (
    <>
      <HealthWrap>
        <HeaderWrap>
          <Logo />
          <HealthKind>{kind}</HealthKind>
        </HeaderWrap>
      </HealthWrap>
    </>
  );
}
캘린더 제한된 무한 스크롤 기능
const [months, setMonths] = useState([
  moment().subtract(1, "months").format("YYYY-MM"),
  moment().format("YYYY-MM"),
  moment().add(1, "months").format("YYYY-MM")
]);

const handleScroll = (e) => {
  const { scrollTop, clientHeight, scrollHeight } = e.target;
  if (scrollTop + clientHeight >= scrollHeight && months.length < 6) {
    setMonths((prevMonths) => [
      ...prevMonths,
      moment(prevMonths[prevMonths.length - 1])
        .add(1, "months")
        .format("YYYY-MM")
    ]);
  }
};

위의 코드는 사용자가 달력을 스크롤할 때 새로운 달들을 동적으로 불러오는 코드 입니다. 전형적인 무한 스크롤 방식을 사용하되, 최대 6개월까지만 달력을 확장할 수 있게 제한적으로 구현하였습니다. 사용자가 스크롤을 통해 달력의 맨 아래에 도달하면, 다음 달의 정보를 불러오는데, 이때 'months' 배열에 새로운 월이 추가됩니다. 'months' 배열의 길이가 6에 도달하면, 더 이상 새로운 월을 추가하지 않습니다. 이렇게 제한을 둔 이유는 무한 스크롤의 경우 실제 데이터의 양을 스크롤 막대가 정확히 반영하지 않고, 사용자가 처음 위치로 돌아오기 어렵다는 문제를 해결하기 위해 제한을 두었습니다. 사용자가 스크롤 인터페이스의 끝에 도달했는지를 감지하고, 만약 'months' 배열이 아직 6개월에 도달하지 않았다면, moment 라이브러리를 이용해 마지막 월에 한 달을 추가하여 배열에 삽입합니다. 이렇게 추가된 새로운 월은 "YYYY-MM" 포맷으로 표시됩니다.

현재 날짜 표시 및 작성 게시글이 있을 시 이동 기능
const currentDate = moment().format("YYYY-MM-DD");

for (let i = 1; i <= daysInMonth; i++) {
  const dayDate = moment(`${month}-${String(i).padStart(2, "0")}`).format(
    "YYYY-MM-DD"
  );
  const isToday = dayDate === currentDate;
  const isUploadDay = postDates.includes(dayDate);
  const post = myPosts.find(
    (p) => moment(p.updatedAt).format("YYYY-MM-DD") === dayDate
  );
  days.push(
    <DayCell
      key={i}
      $isToday={isToday}
      $isUploadDay={isUploadDay}
      onClick={() => post && onDayClick(post.id)}
      style={{ cursor: post ? "pointer" : "default" }}>
      {i}
    </DayCell>
  );
}

moment 라이브러리를 활용하여 각 날짜에 대해 "YYYY-MM-DD" 포맷으로 날짜 문자열을 생성한 후, 해당 날짜가 오늘 날짜와 일치하는지 비교합니다.

게시글 목록 API로부터 받아온 게시물 데이터에서 업로드 시간을 추출하여, 각 게시물이 업로드된 날짜를 포함하는 배열을 확인합니다. 이를 통해 생성된 날짜 문자열이 이 배열 안에 존재하는지 검사하여, 해당 날짜에 업로드된 게시물이 있는지 확인하였습니다.

각 날짜에 맞는 DayCell 컴포넌트를 생성하면서, 그 날짜가 오늘인지와 게시물이 업로드된 날짜인지를 속성으로 전달합니다. 만약 특정 날짜에 게시물이 존재한다면, 해당 DayCell 컴포넌트를 클릭할 때 onDayClick 콜백 함수를 호출하도록 설정하여 클릭시 해당 게시물이 표시된 페이지로 이동시키게 설정하였습니다.


🪐 12. 트러블 슈팅

이미지 예외처리 현상: 서버에서 사용자의 프로필 이미지를 불러올시에 이미지가 없는 사용자에게 기본 프로필 이미지가 렌더링 되지 않는 오류 원인: 이미지의 URL을 확인할 때, 서버가 반환하는 문자열에 올바르지 않은 키워드가 입력되어 있어서 이미지가 있는것으로 판단하고 기본이미지를 렌더링 하지 않음
/*이미지가 있으면 보여주고 없으면 기본이미지 보여줌*/
const getImageSrc = (index) => {
  if (
    //만약 이미지가 존재하면서 특정 키워드를 포함하는 경우
    searchResults &&
    searchResults[index].image.includes("api.mandarin.weniv.co.kr") &&
    !searchResults[index].image.includes("undefined")
  ) {
    console.log("이미지가 존재합니다.");
    return searchResults[index].image;
  } else {
    console.log("!!이미지가 존재하지 않습니다.");
    return profileImage;
  }
};

해결 방법: 서버 응답을 검증할 때, 이미지 URL이"api.mandarin.weniv.co.kr"를 포함하고 "undefined"를 포함하고 있지않다면 기본 이미지 URL로 대체하도록 로직을 추가

게시글 업로드 시 예외처리 버그 현상 : 업로드 시 운동 종류를 선택하는 토글에서 근력운동이 아닌 다른 운동을 선택할 시에도 운동 이름을 입력해주세요 라는 Alert창이 뜸 원인 : emptyExerciseNames를 체크할 때 근력 운동을 클릭하면 exerciseEntries에 값이 담겨서 아래 코드를 실행했을 때 false가 나오니까 Alert이 뜨지 않고 다른 운동들의 경우에는 따로 운동 이름을 입력하지 않으니까 항상 emptyExerciseNames가 true라서 Alert이 뜸
const emptyExerciseNames = exerciseEntries.some(
  (entry) => !entry.name || entry.name.trim().length === 0
);

해결 방법 : 다른 운동들의 경우는 운동 이름을 따로 입력할 필요가 없으니 해당 Alert이 뜨는 조건문을 아예 if (selectedValue === "근력 운동") 부분으로 이동

조건부 렌더링 현상 : Post 컴포넌트에 props를 통해 전달된 데이터를 콘솔에서 확인 시 undefined로 출력되며, 브라우저에 빨간색 에러 메시지가 표시됨.

원인 : Post 컴포넌트는 props로부터 데이터를 받기 전에 해당 데이터를 렌더링하려고 시도했으며, 이 때 props 데이터가 undefined 상태였기 때문에 에러가 발생함.

조치 : 데이터가 undefined 상태가 아닐 때만 값을 렌더링하도록 조건부 렌더링을 적용함. 특정 조건 하에 데이터를 출력하기 위해 JavaScript의 논리 연산자 &&와 조건부 연산자 ? :를 사용함.

구현 : 다음과 같이 코드를 수정하여 props로 받은 데이터의 유효성을 검증함

// 논리 연산자 `&&`를 사용하여 `data`가 유효할 때만 `data.account`를 렌더링함
{data && data.account}

// 조건부 연산자 `? :`를 사용하여 `data`의 존재 여부에 따라 `data.account`를 렌더링함
{data ? data.account}

결과 : 위의 변경으로 props의 데이터가 로드되지 않은 상태에서의 접근을 방지하고, undefined에 대한 안전한 처리를 통해 에러 없이 데이터를 올바르게 출력할 수 있게 되었음.


🪐 13. 리팩토링 할 부분

  • 코드정리 및 주석 개선

    • 주석을 통해 코드의 목적과 기능 설명
    • 사용되지 않는 코드 및 파일 제거
  • 에러 처리 강화

    • 프론트엔드에서의 사용자 입력 검증 강화(유효성 검사 강화)
    • 백엔드 통신 실패 시 사용자에게 명확한 피드백 제공
  • 성능 최적화

    • 이미지 레이지 로딩을 이용하여 이미지와 같은 정적 자원의 지연 로딩 최소화
    • 이미지 압축적용
  • 스타일 및 UI/UX개선

    • 사용자 경험을 위한 인터랙티브한 반응형 애니메이션 전반적으로 적용
    • 모바일 화면에 국한되지 않는 pc화면용 UI구현
  • 기능 및 서비스 추가

    • 사용자가 올린 운동 데이터를 정제하여 모달창으로 보여주는 분석기능 구현
    • 사용자의 데이터를 분석하여 칼로리 계산하는 기능 추가
  • 프로필 수정 화면

    • 전에 데이터를 저장하여 입력하지 않은 input창에 정보가 남아있게 기능 수정
  • 검색 디바운스 기능 추가

    • 성능 향상을 위해 일정 시간이 지난 후, 검색이 되도록 수정
  • 피드에서 최상위로 이동하는 버튼 추가

  • 상대방 프로필에서 프로필 주소 복사 기능 추가

  • 게시물 이미지 여러장 업로드 기능 추가 && 게시물 이미지 여러장 렌더링 기능 추가


🪐 14. 리팩토링 한 부분

🐥 2023.12.01 - 2024.01.19

🖤 민주

  • 무한 스크롤
    • 무한 스크롤 기능을 통해 초기 로딩 시 모든 데이터를 한 번에 불러오는 대신, 사용자가 페이지 하단에 도달할 때마다 추가 데이터를 불러오도록 개선하였습니다. 이로 인해 대용량 데이터를 처리할 때 발생하던 긴 로딩 시간을 줄임
  • 프로필 수정 기능 개선
    • 프로필 정보를 수정할 때 이전에 입력했던 데이터가 자동으로 입력
  • 테스트 계정 토글 버튼 추가
    • 테스트 계정 토글 버튼을 추가하여 손쉽게 테스트 계정을 사용 가능

🖤 영우

  • 운동 분석 기능 구현
    • 데이터 반영: 게시물로 올린 데이터를 API에서 추출하여 가공 후 운동 분석 창에 반영. 다음과 같은 데이터 포함
    • 볼륨, 거리, 시간, 소비 칼로리(운동별 칼로리 계산 공식 추가)
    • 데이터 가공: 추출된 데이터를 날짜별로 가공하여 주간 단위 (일월화수목금토)로 표시
    • 그래프 구현: API로 추출한 데이터를 바탕으로 운동 분석 그래프기능을 chart.js 방식으로 구현
    • 화면 구역 분할: 기존의 모달 방식에서 캘린더 방식으로 운동분석창 이동. 화면 상단에는 운동 분석 그래프를, 하단에는 캘린더를 배치하여 정보 접근성 향상
    • 주차별 이동 버튼 추가: 지난주 데이터로 이동할 수 있는 버튼 구현하고 이번주까지만 이동할 수 있도록 제한을 두어 사용자의 혼란 방지
  • 성능 최적화
    • 달력 버튼 클릭 시 그래프가 재렌더링 되는 문제 해결: 사용자 인터페이스의 안정성과 성능 향상
  • 검색 기능 개선
    • 검색 디바운스 추가: 사용자 경험을 개선하기 위해 검색 기능에 디바운스를 추가하여 입력 중에는 검색이 지연되도록 함

🖤 연정

  • 스크롤 캘린더를 버튼 캘린더로 변경
  • 캘린더 날짜 클릭 시 게시글 이동 기능
    • 단일 게시글: 해당 날짜에 게시글이 하나만 있을 경우, 사용자가 날짜를 클릭하면 바로 해당 게시글의 상세 페이지로 이동
    • 다수의 게시글: 해당 날짜에 여러 게시글이 있을 경우, 'PostList' 페이지를 추가하여 사용자가 날짜를 클릭하면 게시글 목록이 표시. 사용자는 목록에서 원하는 게시글을 선택하여 상세 페이지로 이동 가능
  • 게시물 수정 기능 추가
  • 로그인 토큰 유효기간 수정
    • 로그인 토큰의 유효기간을 조정하여 보안을 강화하고 사용자 경험을 개선하는 데 도움


About

멋쟁이사자처럼 7기 프로젝트 7조

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 99.8%
  • HTML 0.2%