[TIL] 240713 (심화 프로젝트 타입, 좋아요 즉시 미적용, 정렬 시 무한 스크롤 중단 오류 해결)

·2024년 7월 13일

TIL

목록 보기
97/268
post-thumbnail

🥞 오늘 한 일

  • 심화 프로젝트
    • 공연 정보 페이지 쪽 타입 오류 잡기
    • router handler 다 빼기 (배포 시 문제 때문에)
    • img 태그 Image 태그로 변경
    • 공연 상세 페이지에서 좋아요 클릭 후 뒤로 갔을 때 바로 적용되지 않는 문제 해결
    • 좋아요 클릭 여부에 따라 하트 컬러 상태 구현
    • 푸터 쪽 style 수정
    • 링크 유효성 검사 추가
    • sort 기능 시 무한 스크롤되지 않는 오류 해결
    • 제출 PPT 제작

🍽️ 트러블 슈팅

심화 프로젝트

공연 관련링크 문제

링크에 어떤 값을 넣어도 게시글 작성 및 수정이 되는 것이 문제였다. 잘못된 값을 넣을 경우 오류가 나므로, 페이지를 이용하는데에 큰 결함이 있을 것으로 생각했다. 때문에 링크에 관련한 url 유효성 검사를 추가하여 문제를 해결하였다.

const urlRegex = /^(https?|ftp):\/\/(-\.)?([^\s\/?\.#-]+\.?)+(\/[^\s]*)?$/i;
if (link && !urlRegex.test(link)) {
  alert("링크 형식이 잘못되었습니다.");
  return;
}

관련 링크는 선택이기 때문에 link가 있을 경우에만 유효성 검사를 하는 것으로 했고, urlRegex는 구글링을 통해 링크 형식을 검사하는 코드를 가지고 왔다. 만약 제대로 된 링크 형식이 아닐 경우 alert 후 바로 return을 하도록 했다.

좋아요 버튼 클릭 시 즉시 미적용 문제

공연 상세 페이지에서 좋아요 버튼을 클릭한 다음, 공연 정보 페이지(리스트 페이지)로 이동하면 좋아요 숫자가 바로 적용이 되지 않는 문제가 있었다. 캐싱 때문에 그런 것 같았으나 캐싱을 없애고 싶지는 않았기에, 어찌 보면 간단한 방법으로 좋아요 버튼을 클릭하면 바로 invalidateQueries를 통해 적용을 바로 시켜주는 로직을 사용했다. tanstack query의 장점이 바로 이런 곳에서 나오는 게 아닐까 하는 생각이 들었다.
아래는 좋아요 버튼을 클릭할 경우의 전체 함수이다.

const onClickLikeHandler = async () => {
  if (!user) {
    alert("로그인한 사용자만 가능합니다.");
    return;
  }
  const newLike = {
    like_id: uuidv4(),
    post_id: postId,
    user_id: user.id,
  };
  const { data } = await supabase
    .from("concert_likes")
    .select()
    .eq("post_id", postId)
    .eq("user_id", user.id);
  if (data && data.length) {
    await supabase
      .from("concert_likes")
      .delete()
      .eq("post_id", postId)
      .eq("user_id", user.id);
    setHeart(false);
    setLike(like - 1);
  } else {
    await supabase.from("concert_likes").insert(newLike).select();
    setHeart(true);
    setLike(like + 1);
  }
  // concerts 갱신
  queryClient.invalidateQueries({
    queryKey: ["concerts"],
  });
};

바로 갱신을 하여 뒤(공연 정보 페이지)로 가더라도 바로 적용된 것을 볼 수 있었다.

정렬 기능 시 무한 스크롤되지 않는 오류

문제

공연 정보 페이지에는 공연 리스트를 최신순, 랭킹순, 공연종료임박순으로 정렬을 할 수 있는 기능이 있다. 그러나 처음 들어갔을 때의 페이지인 최신순 페이지를 제외하고는, 무한 스크롤 기능이 작동하지 않았다.
게다가 현재 가져온 6개의 리스트 내에서만 랭킹순, 공연종료임박순 정렬을 했기에, 만약 그 뒤의 리스트가 1위라 하더라도 가져오지 못하는 현상이 발생했다. 때문에 대대적인 리팩토링이 필요하다고 느꼈다.

해결

기존의 방식은 가져온 데이터를 똑같이 공유하면서 해당 데이터 내에서 정렬을 해주는 방식을 사용했지만, 그 방법이 이제 통하지 않으므로 정렬을 할 때마다 새롭게 supabase에서 가져오는 방식을 택했다. activeSort 상태관리를 통해 해당 상태를 인자로 넣어줌으로 getConcerts 함수를 구현했다.

// getConcerts.ts
import supabase from "./supabase/client";

export default async function getConcerts(page = 0, sort = "latest") {
    const limit = 6

    let query = supabase.from('concert_posts').select(`*, concert_likes(post_id)`, { count: 'exact' });
    
      if (sort === "latest"){
        query = query.order('created_at', { ascending: false })
      } else if (sort === "imminent") {
        query = query.order('end_date', {ascending:true})
      }

      const {data:posts, error: postError, count} = await query

      if (postError) {
        throw new Error(postError.message);
      }

      let sortedPosts = posts;
      if (sort === "ranking"){
        sortedPosts = posts.sort((a,b)=>b.concert_likes.length - a.concert_likes.length)
      }

      const start = page * limit;
      const end = start + limit;
      const paginatedPosts = sortedPosts.slice(start, end);

      if (count){
        const nextCursor = end < count ? page + 1 : null;
        return { posts: paginatedPosts, nextCursor };
      }
    return { posts: paginatedPosts, nextCursor: null };
}

전체 데이터를 가져온 다음 받아온 sort 인자에 따라 정렬을 해준다. 이 때 ranking의 경우는 order를 통해 가져올 수 없기 때문에 (배열의 length로 비교를 해줘야하는 조금 특이한 방식이기 때문에) 가져온 데이터에 따로 sort를 진행해주는 것으로 했다. 그 다음 가져온 posts를 잘라서 return해준다. 다른 부분은 기존의 방식과 같았다.
이렇게 하니, 굳이 리스트 파일에서 sortedConcerts같이 정렬된 리스트 상태를 따로 관리해줄 필요가 없었다. 클릭 할 때마다 매번 activeSort 상태만 업데이트해주면 됐다.

// sort 기능

// 최신순 정렬
const latestSort = () => {
  setActiveSort("latest");
  refetch();
};

// 랭킹순 정렬
const rankingSort = () => {
  setActiveSort("ranking");
  refetch();
};

// 공연 종료 임박순 정렬
const imminentSort = () => {
  setActiveSort("imminent");
  refetch();
};

기존의 함수보다 훨씬 간단해졌다. 그저 activeSort 상태를 갱신하고 refetch를 해주면 해결됐다.
이런 식으로 코드를 리팩토링 하니 각 정렬에 따른 리스트들도 잘 가져올 수 있었고, 무한 스크롤 기능도 다른 정렬에서도 제대로 작동할 수 있었다.

🍳 내일 목표

  • 심화 프로젝트
    • 타입 오류 리팩토링
profile
웹 프론트엔드 개발자

0개의 댓글