Code Monkey home page Code Monkey logo

deepening-project's Introduction

💚 모임이 끝나고 후기를 전할 수 있는 롤링페이퍼 프로젝트

리액트 심화주차 프로젝트로 NEXTJS를 통해 구현했어요.

어떤 모임을 마치고 소감은 듣고 싶은데, 막상 부탁하기 어려울 때! "어땠어?"를 사용해보는건 어떨까요?

0. 팀원 소개

남현재 정민석 조은영 임현석 안종현 한종섭
모임 전체 목록,
닉네임 수정 & 로그아웃 기능,
프로젝트 환경 셋팅
모임생성,
이미지 drag&drop
방식 추가 기능,
회원가입 & 로그인
소셜로그인(google, kakao)
모임 목록 페이지 리스트
(기본순, 모아보기)
모임 재배치 기능
모임 후기 글쓰기 및
편지지 색상 변경 기능
후기 상세페이지
디테일 페이지 헤더
카카오톡 공유하기



0-1. 프로젝트 진행 기간

  • 2024.07.08 ~ 2024.07.12

0-2. 프로젝트를 진행하며..

  • 서로의 진행 상황을 공유하기 위해 zep과 slack을 통해 소통했어요.
  • 서로의 코드를 리뷰하는 문화를 지향했어요.

0-3. 프로젝트 Github 전략

git-flow 전략을 간소화 하여 메인 브랜치인 main, dev와 보조 브랜치 feature 사용했어요.

main branch

  • 최종 프로젝트 버전을 배포하는 브랜치

dev branch

  • feature 브랜치의 분기가 되는 곳, 개발 브랜치

feature branch

  • 각자의 기능을 개발하는 브랜치 dev branch로부터 각자의 feature branch를 만들어 작업한 이후 PR을 통해 코드리뷰를 진행하고 merge를 했서요. 또한 2명 이상 approve가 있어야 dev에 merge 할 수 있도록 조건을 설정하였어요.

1. 사용한 라이브러리

tanstack-query

서버 상태 관리를 관리 하기 위해 사용하였으며, 비동기 로직을 간편하게 작성하기 위해 사용했어요

supabase

Supabase를 백엔드로 사용하여 실시간 데이터베이스를 사용했어요

tailwind css

재사용성이 높고, 코드의 가독성과 유지보수성을 향상시킬 수 있기에 사용했어요

Kakao Share API

카카오 API를 이용하여 사용자가 콘텐츠를 쉽게 공유할 수 있도록 하였어요.


2. 대표기능

  • 회원가입 로그인을 통해 인증된 사용자만 모임을 생성할 수 있어요.
  • 모임을 생성하고 모임 공유 기능을 통해 다른 사람들이 나에게 글을 쓸 수 있어요.
  • 모임 재배치 기능을 통해 포스트잇 처럼 마우스로 글을 옮길 수 있어요.
  • 글작성 페이지에서 배경색을 바꿀 수 있어요

3. 상세설명

1. Supabase Auth를 사용하여 로그인 회원가입 페이지를 구현


  • Supabase Auth를 사용하여 로그인 및 회원가입 페이지를 구현했어요.
  • 이메일 회원가입 및 소셜 로그인(구글, 카카오) 기능을 구현하여 편리하게 인증할 수 있어요

2. 내가 생성한 모임과 닉네임 변경 기능


  • 나의 모임을 통해 내가 생성한 모임을 빠르게 찾아볼 수 있어요.
  • 닉네임 변경을 통해 나만의 닉네임을 가질 수 있어요.

3. 모임 리스트 페이지 구현



  • 유저들이 생성한 모임들을 볼 수 있어요.
  • 무한 스크롤을 구현하였어요. 무한 스크롤시 로딩은 로딩 스피너를 통해 로딩중임을 알 수 있어요.

4. 모임 생성 페이지 구현



  • 드래그 방식으로 이미지를 넣어 모임을 생성할수 있어요.

4. 모임 상세페이지


  • 내가 생성한 모임에 다른 사람들이 써준
  • 버튼을 통해 보기 방식을 변경 할 수 있어요.
  • 다른 사람이 쓴 글을 마우스를 통해 배치할 수 있어요.


  • URL 공유하기와 카카오톡 공유하기 기능으로 비회원도 링크를 통해 글을 남길 수 있어요


  • 아이콘을 클릭해 글의 내용을 볼 수 있어요



  • 잘못된 경로로 접근한 경우 Not-Found UI를 보여줬어요
  • 에러 발생시 Error UI를 보여줬어요



  • 공유 받은 URL이나 카카오톡 공유를 통해 글을 작성할 수 있어요.
  • 카테고리별 선택과 배경색을 바꿀 수 있어요.

deepening-project's People

Contributors

nhjeans avatar ahnjonghyun87 avatar hyeonseok98 avatar eunyoung-jo avatar phantom2115 avatar hanjongseop avatar

Stargazers

 avatar

Watchers

Lucian avatar  avatar  avatar

deepening-project's Issues

Code Review(2024.07.14 13시 기준)

🔥 코드와 실행 결과만을 보고 작성하였음으로 의도와 다른 경우 comment 남겨주세요(7월 14일 13시 기준 코드입니다)

💡 제 개인적인 코드 리뷰임으로 토론은 언제든 환영입니다~!!


🌈 전체(To. 팀장님~)

1. (건의사항) input css 통일

  • input 클릭시 저희 메인 색깔인 outline-customGreen으로 지정하는건 어떨까 싶습니다.
    • 현재 /clubs/create에만 적용되어 있습니다.

2. ButtonSm 컴포넌트의 이름을 전체적인 컨벤션에 맞춰 SmallButton으로 변경하면 어떨까요?

3. ButtonSm 이외의 배경색이 customGreen이고 글자가 흰색인 버튼의 경우 글자가 잘 안보여서 균일하게 bold 해주면 좋을 것 같습니다.

✨ 로그인

1. email, back 이미지 위치 수정

2. /(sub)/auth/page.tsx

  • 일반적으로 early return을 사용하는 것은 불필요한 추가 로직을 실행하지 않기 위함입니다.
    현재 kakao 로그인이 아닌 경우에도 if(error)문이 실행되지만, 이는 kakao 로그인이 아닐 경우 실행되지 않아도 됨으로 if~else 문으로 변경해도 좋을 것 같습니다.
  const handleLogin = async (method: string) => {
    if (method === "kakao") {
      const { error } = await supabase.auth.signInWithOAuth({
        provider: "kakao",
        options: {
          redirectTo: `${window.location.origin}/api/auth/callback`,
        },
      });
      if (error) {
        console.error("Kakao login error:", error.message);
        return;
      }
      return; // 삭제
    }
    router.push(`/auth/${method}`); // else문으로 변경
  };

3. /(sub)/auth/kakao-redirect/page.tsx

  • useEffect 의존성 배열에 supabase를 추가하여 경고 밑줄을 없애도 좋을 것 같습니다.

4. /(sub)/auth/login/page.tsx

4-1. 10번째 줄: 불필요 공백줄 제거
4-2. 코드 내 if(result.error)와 같이 에러 처리 구문이 있지만, fetch하는 과정 자체에서 error가 생길 경우에는 result 이전에 에러가 생깁니다. 때문에 setError(null) 다음 코드부터 try~catch문으로 만들어 에러 처리 해주는 것도 좋아보입니다.

5. /(sub)/auth/sign-up/page.tsx

5-1. 사용하지 않는 구문 삭제

import { createClient } from "@/utils/supabase/client";

5-2. 9, 20번째 불필요 공백줄 제거

6. /(sub)/auth/socialNickname/page.tsx

6-1. 다른 위치로부터 가져오는 const supabase = createClient(); 부분은 따로 존재하기 보단 다른 const와 같이 붙어 있어도 좋을 것 같습니다.
6-2. [63~111번째 줄] 찾아보니 supabase에는 upsert라는 쿼리문이 있습니다. 중복되는 값이 있다면 Update를 하고 중복되는 값이 없다면 Insert를 하는 기능을 하며, 여기선 기존에 사용자가 있으면 업데이트하고, 없으면 삽입하는 로직을 대체할 수 있습니다. 이런 구문도 있다 정도로 참고해주세요(현재 50줄 -> upsert 사용시 20줄 정도 예상)

6.3 useEffect 의존성 배열에 supabase를 추가하여 경고 밑줄을 없애도 좋을 것 같습니다.
6.4 h1의 크기가 너무 커서 두 줄이 되어 있습니다.

6.5 input 좌우 여백이 조금 있으면 어떨까 합니다!
6.6 button에 hover 효과가 있으면 어떨까 합니다
6.7 한 페이지 내 '닉네임'이라는 단어가 많이 반복되고 있습니다(4번). 때문에 label은 없어도 깔끔하지 않을까 건의드려요
6.7 전체를 감싸는 div 대신 main, section, form과 같은 시멘틱 태그도 괜찮아 보입니다!


✨ 메인 페이지(clubs)

/(main)/page.tsx

  • 모임 생성 이후 새로고침 해주어야 새로 생성해준 모임이 보입니다.
  • /component/smallButton.tsx에서 w-[65px]로 width값이 설정되어 있어 버튼이 두 줄로 생성됩니다. 이 부분을 수정해야 할 것 같습니다.
  • 어제 밖에 있어 이제 확인했는데, 로그인 후 본인의 모임만 보도록 기획단계에서 논의된게 아닌가 하여 질문드립니다.
    익명이지만 개인사가 포함된 내용까지 볼 수 있어 '전체 모임'은 조금 부담스러운 기능이 아닐까 하는데 혹시 어떻게 생각하세용?

<CreateClubButton>

  • 마지막에 확인하시겠지만 31번째 줄 console.log()가 있습니당
  • Link 태그 내 flex를 주어 버튼 외의 공간에서도 link가 걸려있습니다(모임생성 왼쪽 빈 공간에서도 모임 생성 가능)
    위치 조정을 담당하는 태그를 하나 더 사용하시는 걸 추천드립니다!
  • 모임 생성 버튼 hover시 효과를 넣어보는건 어떨까 건의드려봅니다

<ClubsList>

  • <Link>와 <div>에 key가 중복되어 사용되어 div의 key값을 삭제 하는 것도 좋아보입니다!
 <Link key={club.id} href={`/clubs/${club.id}/comments`}>
<div key={club.id} ref={isLastClub ? lastClubRef : null} className="bg-white p-4 rounded-lg shadow-md">
  • <Image> src 안의 변수를 조금 더 의미를 담은 변수명으로 사용하면 어떨까 생각해보았습니다

<EditNickName>

  • 닉네임 수정시 " 피카츄"라고 쓰면 닉네임은 "피카츄"라고 나오지만 다음 정보수정 버튼을 눌렀을때 " 피카츄"라고 표기됩니다.
  • 때문에 아래 문장에 trim()을 추가하는 것도 좋아보입니다
 const newNickname = nicknameRef.current.value;
  • alert에 닉네임이 6글자를 초과할 때의 경우가 없어, 2글자 이상 6글자 이하임을 명시하면 좋을 것 같아요~!!
  • 전체적인 팀 프로젝트에서 error 처리를 early return문을 사용하고 있어 catch문의 error 처리를 동일한 컨벤션으로 가져가도 좋을 것 같아요
  • 39번째 줄 input className에 공백 제거 부탁드려요!

✨ 모임 만들기

  • CreateClub => CreateClubPage로 팀 전체적인 코드를 맞추는 것도 좋아보여요!
  • 이전 pr의 요청사항 동일
  • #8

✨ Club Detail

  • 모임명이 길어질 경우 사진이 작아지는 현상이 있어 수정이 필요합니다.

✅ 공유하기

  • 링크 공유의 url 수정이 이루어지면 좋을 것 같습니다.
  • 공유 게시글이 title과 description을 나눠서 보여주고, 이미지도 추가되면 예쁠 것 같아요. 사진은 ppt로... 해보았습니다...

<ClubTtitle>

  • useEffect의 의존성 배열에 supabase를 추가하여 경고 문구를 없애도 좋을 것 같습니다.
  • error와 !clubData 오류 처리의 태그명을 시멘틱 태그나 글이라는 걸 알 수 있는 태그명이면 좋을 것 같아요!

✅ 모임 만들기(리스트)

  • 현재 뒤늦게 합쳐진 pr에 따라 코드가 구성되어 있는데, 모달을 전역으로 할지 페이지 단위로 여닫을지 결정이 필요합니다.
  • 아래는 셀프 피드백입니다

<CommentGridItem>, <CommentListItem>

  • 전체 영역을 div가 아닌 section으로 변경

<NotFound>

  • h-[760px]이 아닌 h-screen으로 화면 높이에 맞출 수 있게 수정

/(main)/clubs/[clubId]/page.tsx

  • 2개의 조건문을 하나로 축약하여 사용 가능 해보임
commentList && commentList.length !== 0

// 변경 후
commentList.length > 0

✨ 글 생성

  • 현재님 pr 합친 버전으로 체크하였습니다.

1. (main)/guests/[id]/createPost/page.tsx

1-1. 8번째 공백줄 제거해도 좋을 것 같아요
1-2. if문과 함께 error처리를 할 때 <h1> 태그를 일반적으로 잘 사용하지 않아 다른 태그를 사용하는 걸 개인적으로 선호합니다.
1-3. 개인적으로 모임명은 예전처럼 조금 굵게 font-weight이 있어도 좋을 것 같아요
1-4. section className 맨 뒤의 공백 제거를 부탁드려요!
1-5. 아래 코드에 대한 내용입니다.

  • font color에 대한 속성은 제거해도 될 것 같아요
  • 왼쪽 뿐만 아니라 오른쪽 여백도 같은 여백 크기로 지정되면 좋을것 같아요
  • className 맨 뒤의 공백 제거를 부탁드려요!
<h1 className="font-black text-xl self-start ml-10 pb-5 ">{`${clubData[0].title}님의 모임`}</h1>

1-6 input 태그 내에도 텍스트 색상 지정은 제거해도 좋을 것 같습니다.

1-7. textarea 내 text-2xl과 border 사이 공백을 제거 부탁드려요!
1-8. 개인적으로 textarea 내 글자 크기가 조금 큰 것 같아요.

  • <h1> 태그가 text-xl 크기임으로 textarea의 크기는 text-base(아무것도 지정안한 브라우저 기본 크기)가 되면 좋을 것 같아요

1-9. 글을 작성하는 부분에 placeholder로 이곳에 글을 작성해주세요 등의 안내 문구가 있어도 좋을 것 같아요.(취향)

2. (main)/guests/[id]/postDetail/[postId]/page.tsx

2-1. 앞선 페이지처럼 font-black은 삭제를, 오른쪽 여백도 왼쪽 처럼 균등하게 있었으면 하는 바람입니당

<h1 className="font-black text-xl self-start ml-10 pb-3">{`${club.title}님의 모임`}</h1>

2-2. 짧게 category를 나타내는 부분이기에 div보다 다른 태그를 사용해도 좋아보여요!

<div className="w-1/5 bg-customGreen border rounded-md text-white shadow-md text-center">{post.category}</div>

2-3. text-2xl과 mb-4 사이 공백 제거를 부탁드립니닷! 그리고 위에 페이지의 모임을 나타낼 때 <h1> 태그를 사용해서 이부분은 한 단계 낮춘 를 사용해도 괜찮아 보여요!

<h1 className="text-2xl  mb-4">{post.content}</h1>

2-4. 앞으로 리스트가 나타날 의미로 해석되지만 해당 페이지 내에서 나타내는 것이 아니고, 버튼만을 감싼 태그이기에 ul보다는 다른 태그를 사용하는 것이 좋을 것 같습니다.

      <ul className="pt-10">
        <Link
          href={`/clubs/${id}/comments`}
          className="bg-customGreen border rounded-md text-white shadow-md text-center p-2 px-10"
        >
          모임 응원글 보러가기
        </Link>
      </ul>

<useSubmitPost>

  • use를 붙여 사용하는 custom Hook임으로 _components가 아닌 hooks 폴더로 옮겨서 사용해 주시거나, 해당 페이지 내에서만 사용할 훅이라면 _hook이라는 폴더를 만드셔서 거기로 파일을 이동하시는 걸 추천드립니다!
  • 모달창 안에서는 보통 <h1>이 사용되지 않습니다!(seo에 모달은 도움이 별로 되지 않기 때문이며, h1은 정말 중요한 곳에만 사용) 때문에 다른 태그를 사용하시는 걸 개인적으로 추천드려요
  • 해당 부분은 에러가 발생할 경우 early return을 통해 아래 로직이 실행되지 않게 최적화 할 수 있을 것 같습니다.
      if (!response.ok) {
        modal.open({
          title: "오류",
          content: (
            <div className="text-center">
              <h1>글 작성 중</h1>
              <p>오류가 발생했습니다.</p>
              <p>데이터가 올바르게</p>
              <p>전송되지 않았습니다.</p>
            </div>
          ),
        });
      }

<ColorButtons>

  • 해당 컴포넌트에서는 공통적인 로직이 발생하기 때문에 시간 남으시면 반복문으로 간추려도 좋을 것 같아요(시간 남으시면 리팩토링..?)
  • 아래 코드는 제가 테스트 한 내용이기에 참고하셔도, 하지 않고 개인적으로 진행하셔도 좋을 것 같습니다.(일부러 접어두었습니다...)
코드 보기/접기
"use client";

type ColorButtonsProps = {
  handleColorChange: (color: string) => void;
};

// 상수는 constants 폴더로 분리 가능
const COLORS = [
  { bgColor: "#ffcccc", colorCode: "#FFBABA" },
  { bgColor: "#ccffcc", colorCode: "#8DE8A6" },
  { bgColor: "#ccccff", colorCode: "#84BBFD" },
  { bgColor: "#ffccff", colorCode: "#E4AFED" },
];

const ColorButtons = ({ handleColorChange }: ColorButtonsProps) => {

  return (
    <div className="flex space-x-6 justify-center">
      {COLORS.map(({ bgColor, colorCode }) => (
        <button
          key={colorCode}
          className="transition-transform transform hover:scale-105"
          type="button"
          style={{ backgroundColor: bgColor }}
          onClick={() => handleColorChange(colorCode)}
        >
          <div className="w-12 h-12 shadow-md"></div>
        </button>
      ))}
    </div>
  );
};

export default ColorButtons;

✨ 그 외

✅ apis 폴더

  • club과 user 폴더로 구분해서 api들을 관리할 수 있을 것 같습니다.
  • fetchClubs.ts에는 함수 반환문에도 타입이 지정되어 있습니다. 반환 타입이 명확한 경우 타입을 지정해도 좋을 것 같습니다
    • (꼼꼼하게 지정하셔서 대박...)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.