프로젝트

[프로젝트] supabase 여러 테이블 데이터 한번에 가져오기

ejunyang 2024. 8. 8. 17:07

 

적용

 

 

아래 코드는 디테일 페이지에서 특정 상품의 데이터를 가져오는 부분이다. 원래는 상세 정보와 리뷰 탭이 없었는데 UT를 진행하면서 리뷰가 있었으면 좋을 것 같다는 피드백이 많아서 구현하게 되었다. UT를 해볼 기회는 없었는데 이번에 해보게 되어서 너무 좋았다(?) 피드백을 받고 수정하는데 테스트 전보다 완성도 높은 작업물이 나올 것 같다.

const {
    data: food,
    isPending,
    error
  } = useQuery({
    queryKey: ['localfood', id],
    queryFn: async () => {
      const { data, error } = await supabase
        .from('local_food')
        .select('*')
        .eq('product_id', id)
        .single();

      if (error) throw new Error(error.message);

      return data;
    }
  });

 

 

그런데 여기서 문제. 저 리뷰 탭에 리뷰의 개수가 보여야하는데 저 개수만 보여주려고 리뷰 데이터를 패치해야하는 상황이 생겼다. 라우터 핸들러로 만들어놓긴 했지만 저 개수를 띄우려고 코드를 몇줄 이상 써야하는게 비효율적이라고 생각이 들었다. 구글링하다가 supabase join 기능이 있다고해서 참고했다. supabase 초반에 사용할 때 들었던 기능 같은데, 프로젝트에서 써먹어본건 최종까지와서다.. 막상 기억이 잘 안나서 사용하지 못했다,, 이제라도 알아서 다행이다^.~

 

Querying Joins and Nested tables | Supabase Docs

The Data APIs automatically detect relationships between Postgres tables.

supabase.com

 

supabase join 으로 여러 데이터 한번에 가져오기

최근 프로젝트에서 팔로워 리스트를 가져오는 기능을 구현하던 중, 나를 팔로우한 유저의 프로필 정보를 가져오는 과정이 너무 복잡하고 비효율적이라는 생각이 들었다. 그래서 리팩토링을 진

velog.io

 

 

수정코드

리뷰 테이블의 모든 데이터를 가져왔다.

const {
    data: food,
    isPending,
    error
  } = useQuery({
    queryKey: ['localfood', id],
    queryFn: async () => {
      const { data, error } = await supabase
        .from('local_food')
        .select('*, reviews(*)')
        .eq('product_id', id)
        .single();

      if (error) throw new Error(error.message);

      return data;
    }
  });

 

사용할 땐 두개의 테이블 이름을 같이 써서 아래와 같이 사용하면 된다.

    <li
            className="flex-1 cursor-pointer"
            onClick={() => setActiveTab('리뷰')}
          >
            <p
              className={`pb-2 w-[140px] mx-auto ${
                activeTab === '리뷰'
                  ? 'text-primary-20 border-b-4 border-primary-20'
                  : 'text-label-assistive'
              }`}
            >
              {`리뷰(${food.reviews.length})`}
            </p>
          </li>