본문 바로가기
TIL

[react/nextjs] 데이터가 있는지 판단 후 insert 또는 update

by dev__log 2024. 4. 5.

음악 추천 리스트에서 + 추가 버튼을 누르면 현재 유저의 재생 목록 테이블에 데이터가 추가되어야 하는데 고려해야 할 부분이 있다. 

 

데이터가 있는지 판단하는 이유는 재생 목록에 추가하는 노래 id를 배열에 담기 때문에 한 번이라도 노래를 추가하여 재생한 적이 없다면 재생목록 테이블에 유저의 현재 재생 목록은 없다. (재생 목록 데이터가 있어야 그 데이터의 노래 컬럼에 배열로 재생할 노래를 담을 수 있다)

그렇기 때문에 먼저 이 유저가 현재 재생 목록을 가졌는지 판단 후 insert 또는 update를 해야 한다. 

 

사실 회원가입 할 때 유저의 현재 재생 목록을 가지도록 재생 목록 테이블에 빈 값으로 insert를 하는 건 어떨지 고민도 했다. 

만약 이 방법으로 한다면 추가할 때마다 재생 목록이 있는지 판단하는 요청을 supabase에 보내지 않아도 되기 때문에 리소스 낭비를 줄일 수 있을 것 같다는 생각이 든다. 

 

지금은 데이터를 추가할 때 판단하고 추가하도록 구현했다. 

 

이후에 팀원들과 논의해 보고 어떤 방식이 더 좋은지 고민해 보는 것도 좋을 것 같다. 

 

구현

먼저 유저가 재생 목록을 가지고 있는지 확인한다.

export const getCurrentMusicData = async (userId: string): Promise<PlaylistCurrent[]> => {
  try {
    const { data } = await supabase.from("playlistCurrent").select("currentId, userId, currentMusicIds").eq("userId", userId);

    return data as PlaylistCurrent[];
  } catch (error) {
    console.error(error);
    return [];
  }
};

 

 

userInfo는 zustand에 저장되어 있다. 이 데이터는 로그인할 때 담긴다. 

쿼리에서 enabled로 userInfo.uid 가 있으면 쿼리를 실행하도록 하였다. 

이렇게 하면 불필요한 요청을 방지할 수 있다. 

만약 이 설정을 하지 않으면 usreInfo에 zustand가 값을 가져오기 전에 useQuery가 실행되어 버려서 원하는 결과를 받지 못할 수 있다. 그렇기 때문에 userInfo에 의존하도록 만들어 주는 게 좋다.

const { userInfo } = useStore();

const { data: playListCurrent } = useQuery({
    queryFn: () => getCurrentMusicData(userInfo.uid),
    queryKey: ["playListCurrent"],
    enabled: !!userInfo.uid
  });

 

 

데이터가 있는지에 따라서 로직을 insert와 update로 분기했다.

playListCurrent 가 있으면 유저의 재생 목록이 있다는 것이므로 insert를, 없다면 update를 실행한다. 

또한, update 시에는 같은 노래가 이미 추가되어 있는지 판단한다. 

  const onClickAddCurrentMusicHandler = (userId: string, musicId: string) => {
    if (userId === "") {
      alert("로그인 후 사용할 수 있는 서비스입니다. 로그인 페이지로 이동합니다.");
      router.replace("/login");
      return;
    }

    if (playListCurrent && playListCurrent.length > 0) {
      const currentList = playListCurrent[0].currentMusicIds;
      if (currentList.find((el) => el === musicId)) {
        alert("이미 추가된 노래입니다."); //이후에 삭제 예정
        return;
      }
      currentList.push(musicId);
      updateMutation.mutate({ userId, currentList });
    } else {
      insertMutation.mutate({ userId, musicId });
    }
    alert("현재 재생목록에 추가 되었습니다."); //이후에 삭제 예정
  };

 

 

insert와 update를 수행하는 쿼리이다. 

  const insertMutation = useMutation({
    mutationFn: insertCurrentMusic,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["playListCurrent"] });
    }
  });

  const updateMutation = useMutation({
    mutationFn: updateCurrentMusic,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["playListCurrent"] });
    }
  });

 

export const insertCurrentMusic = async ({ userId, musicId }: { userId: string; musicId: string }) => {
  try {
    await supabase
      .from("playlistCurrent")
      .insert([{ userId: userId, currentMusicIds: [musicId] }])
      .select();
  } catch (error) {
    console.error(error);
  }
};

export const updateCurrentMusic = async ({ userId, currentList }: { userId: string; currentList: string[] }) => {
  try {
    await supabase
      .from("playlistCurrent")
      .update({ currentMusicIds: [...currentList] })
      .eq("userId", userId)
      .select();
  } catch (error) {
    console.error(error);
  }
};

 

 

결과

 

완성!

ui 작업도 곧 해야지..