최종 프로젝트 - 찜하기

Rock Kyun·2024년 1월 19일
0
post-thumbnail
post-custom-banner

오늘 했던 것

  • 찜하기 기능 구현
  • 채팅방 목록의 각 채팅방의 마지막 메세지 관련 정보 표기(마지막 메세지, 경과 시간)

1. 채팅방 목록에 정보 표기

접근 방법

  • 먼저 채팅방 목록 컴포넌트를 분리했다.
    그리고 처음에는 이거를 방이 생성되는 map에 돌려서 id값 비교 후
    표기가 되도록 해야되나.. 했지만
    방 개수에 비해 메세지가 심하게 많아서 index값이 닿지 않아서
    포기.. 그러다 생각난 함수 하나!!

1-1. 메세지들 가져와 state에 담기

  • DB에서 메세지들을 가져와 state에 담고
    각 채팅방 id를 인자로 받아 해당 채팅방에 속한 메세지만
    filter 후 시간순으로 정렬 하고
    index 제일 마지막 부분만 뙇 반환하는 함수🥹🥹🥹
  const findMatchMessage = (room: string): any => {
    if (allMessage !== null) {
      const Matched = allMessage
        .map((msg) => {
          return msg.chat_room_id === room && msg;
        })
        .sort((a: any, b: any) => a.created_at - b.created_at)
        .filter((msg) => msg !== false);

      return Matched[Matched.length - 1];
    }
  };
<UI 부분>
const ChatRoomList = () => {
  return (
// 생략... //

// 그래서 아래와 같이 <p> 태그 안에서 마지막 메세지를 반환 해줄 수 있게 되었다.
<St.StListLower>
  <p>{findMatchMessage(room.id).content}</p>
<span>{parseDate(findMatchMessage(room.id).created_at)}</span>
</St.StListLower>
 );
}

1-1에서 남은 찝찝함

  • 지금 DB의 메세지는 많아봐야 테스트 메세지 10개쯤..
    메세지의 용량도 몇 KB 안 하겠지만,
    혹시 나중에 메세지 데이터가 쌓여서 10,000개가 되도
    과연 DB의 메세지를 가져와서 state에 저장 후 작동까지
    지금과 같은 속도가 날까..? 싶은 걱정이 남았고

  • DB에서 가져올 때 애초에 유저가 속한 채팅방에 대한 메세지만 쇽쇽-
    가져올 방법을 생각했지만 각 채팅방의 ID를 모두 비교하여 가져오는
    방법을 찾지 못 했다.
    supabase 클라이언트에서 제공하는 eq 라는 것과 배열 메서드 forEach를 사용해서
    채팅방의 아이디가 같은 것만 쇽쇽 가져오려는 시도도 해봤지만 실패했다.

어쨌든.. 채팅방 결과물

2. 찜하기 기능

접근 방법

  • 찜 버튼을 누르면
    DB에서 해당 게시물의 id를 가진 row를 찾아서!
    컬럼 중 liked_user라는 배열에 좋아요를 누른 유저의 아이디를 업데이트 해주고!
    컬럼 중 likes라는 int4 형태의 값을 1 증가 시켜준다!

  • 유저 테이블의 row에 가서도
    like_post 배열에 게시물의 정보를 업데이트 해준다!

문제

내 머리는 뭘 해야하는지 정확하게 알고 있었다!
supabase 클라이언트에 update는 이상하다는걸 알기 전까지는..

내가 생각한 update는
예를 들어 {바꾸려는 칼럼: 업데이트 값} 이게 맞긴한데...
난 supabase가 바꾸려는 칼럼에 없는 값을 인지하고
추가를 해주는 그런 최첨단 차세대 DB로 알고 있던 거..

해결

  • 이게 맞나? 싶긴하지만
    DB에서 기존 값을 가져와 새 값을 추가하여 update 해주는 것으로 진행하였다.
const handleLike = async () => {
    // 해당 게시물의 현재 좋아요 수 가져오기
    const { data: likesField, error: likes } = await supabase
      .from('products')
      .select('likes')
      .eq('id', id);
    // 해당 게시물의 좋아요 누른 사람들 현재 값 가져오기
    const { data: existingData, error: user_no_exists } = await supabase
      .from('products')
      .select('like_user')
      .eq('id', id);

    //==============================
    // 이거슨 product 테이블 관련 처리
    //==============================
  
    if ( // 가져온 값이 존재하고, length > 0 이라는 조건 //) {
      
      // int 4 타입의 좋아요 값 증가는 생략 //

      // 배열인지, 배열이면 길이가 0이상인지 확인
      const like_userList =
        // 가져 온 값이 null이 아니고 배열이고 length가 0 보다 큰가? 라는 조건에
        existingData && Array.isArray(existingData) && existingData.length > 0
      	  // 참이면 existingData[0].like_user 가 배열이 아니면 빈 배열로 초기화
          ? Array.from(existingData[0].like_user || [])
          // 거짓이면 그냥 빈 배열로 초기화
          : [];
  
	  // 새로 추가할 데이터
      const newLikeUser = {
        userNickname: curUser?.nickname,
        user_uid: curUser?.uid
      };
      
      // 기존 값과 추가할 객체 데이터를 합체
      const updatedLikeUserList = [...like_userList, newLikeUser];

      // 좋아요한 사용자 업데이트
      const { status: likeUser, error: likeUserFail } = await supabase
        .from('products')
        .update({
          like_user: updatedLikeUserList // 합쳐진 값으로 업데이트!
        })
        .eq('id', id);

    /// 에러 처리 생략///

  	// 찜한 게시물인지 아닌지 판단하여 state를 변경하는 함수
  	// 이게 작동하면 state에 따라 찜 버튼이 달라집니다.
    isLikedProduct();
  };

결과물

  • 새로고침 해도 잘 유지가 된다...⭐

느낀점

  • DB를 설계할 땐 기능에 맞게!
    DB테이블을 아주아주 잘 구상하자..!!😫😫
    기능을 구현하려다보니 빠진 컬럼이나 추가되는 컬럼이 생기고
    설계를 잘 해놓으면 위기의 순간에 방법이 보일 수도..!
post-custom-banner

0개의 댓글