TIL

2024.04.03 TIL #์ฑ„ํŒ…์‚ญ์ œ #Supabase_realtime #RLS #Delete

inz1234 2024. 5. 2. 18:08

๐Ÿ“Œ Task TODOLIST

- [x] user Table์—์„œ user ์ •๋ณด(user Id) ๊ฐ€์ ธ์™€์„œ chatting๊ณผ ์—ฐ๊ฒฐ์‹œํ‚ค๊ธฐ

- [x] RLS ์ถ”๊ฐ€ํ•˜์—ฌ ๋‚ด๊ฐ€ ์“ด ๊ธ€๋งŒ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋„๋ก

- [x] ์ฑ„ํŒ… ์‚ญ์ œ๊ธฐ๋Šฅ ๊ตฌํ˜„ + Realtime์œผ๋กœ ์‚ญ์ œ ๊ตฌ๋…ํ•˜๊ธฐ


 

1. user Table์—์„œ user ์ •๋ณด(user Id) ๊ฐ€์ ธ์™€์„œ chatting๊ณผ ์—ฐ๊ฒฐ์‹œํ‚ค๊ธฐ

๋จผ์ € SQL์˜ ์ผ์ข…์ธ progreSQL์„ ์ œ๊ณตํ•˜๋Š” Supabse์—์„œ

์ฑ„ํŒ…์— ์“ฐ์ด๋Š” message table์˜ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

์ด ์ค‘ send_from ์ด๋ผ๋Š” ์ปฌ๋Ÿผ์„ user table์˜ user_id์—์„œ ๊ฐ€์ ธ์™€์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— foreign Key๋กœ ๋“ฑ๋กํ–ˆ๋‹ค.

user ํ…Œ์ด๋ธ”์—์„œ ํ•ด๋‹น ์œ ์ €์˜ ์ •๋ณด๊ฐ€ update ๋˜๊ฑฐ๋‚˜ delete ๋  ์‹œ ๊ฐ™์ด ๋ฐ˜์˜๋˜๊ธฐ๋ฅผ ์›ํ•ด์„œ Cascade๋กœ ๋ฌถ์–ด์คฌ๋‹ค. 

 

2. RLS ์ถ”๊ฐ€ํ•˜์—ฌ ๋‚ด๊ฐ€ ์“ด ๊ธ€๋งŒ deleteํ•  ์ˆ˜ ์žˆ๋„๋ก

auth.uid() ๊ฐ€ send_from ์ปฌ๋Ÿผ์˜ ๊ฐ’๊ณผ ๊ฐ™์•„์•ผ๋งŒ delte ํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์ด ์ฃผ์–ด์ง„๋‹ค!

 

3. ์ฑ„ํŒ… ์‚ญ์ œ๊ธฐ๋Šฅ ๊ตฌํ˜„ + Realtime์œผ๋กœ ์‚ญ์ œ ๊ตฌ๋…ํ•˜๊ธฐ

const ChatDeleteDropDown = ({ msg }: { msg: Message }) => {
  const handleDeleteMsg = async (key: string) => {
    if (key === 'delete') {
      const { error: messageTableErr } = await clientSupabase
        .from('messages')
        .delete()
        .eq('message_id', msg?.message_id);
      messageTableErr && alert('์ฑ„ํŒ… ์‚ญ์ œ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค.');
    }
  };

  const useDeleteMsg = () => {
    const { mutate: deleteMsg } = useMutation({
      mutationFn: (key: string) => handleDeleteMsg(key)
    });
    return { mutate: deleteMsg };
  };

  const { mutate: deleteMsg } = useDeleteMsg();

  return (
    <Dropdown>
      <DropdownTrigger>
        <button>
          <CiMenuKebab className="my-auto w-6 h-6 rotate-90" />
        </button>
      </DropdownTrigger>
      <DropdownMenu aria-label="Static Actions" onAction={(key) => deleteMsg(String(key))}>
        <DropdownItem key="delete" className="text-danger" color="danger">
          Delete
        </DropdownItem>
      </DropdownMenu>
    </Dropdown>
  );

 

 useEffect(() => {
    if (roomId && chatRoomId) {
      const channel = clientSupabase
        .channel(chatRoomId)
        .on(
          'postgres_changes',
          { event: 'DELETE', schema: 'public', table: 'messages', filter: `chatting_room_id=eq.${chatRoomId}` },
          async (payload) => {
            if (payload) {
              await queryClient.invalidateQueries({ queryKey: [MSGS_QUERY_KEY, chatRoomId] });
              messages &&
                queryClient.setQueryData(
                  [MSGS_QUERY_KEY, chatRoomId],
                  messages.filter((msg) => msg.message_id !== payload.old.message_id)
                );
            }
          }
        )
        .subscribe();
      return () => {
        clientSupabase.removeChannel(channel);
      };
    }
  }, [messages, isScrolling, roomId, chatRoomId]);

- ์ฑ„ํŒ…์ด ์‚ญ์ œ๋˜๋Š” ๊ฒƒ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ตฌ๋…ํ•  ์˜ˆ์ •์ด๋ผ messages table์„ ๊ตฌ๋…ํ•˜๋˜,

ํ˜„์žฌ ์†ํ•ด์žˆ๋Š” ์ฑ„ํŒ…๋ฐฉ์— ํ•ด๋‹นํ•˜๋Š” ๋ฉ”์„ธ์ง€๋“ค๋งŒ ๊ตฌ๋…ํ•˜๊ณ (filter: `chatting_room_id=eq.${chatRoomId}`)

๋ฉ”์„ธ์ง€๋“ค ์ค‘ ์‚ญ์ œ๋œ ๋ฉ”์„ธ์ง€๋ฅผ ์ œ์™ธํ•œ ๊ฒƒ๋งŒ ๋ณด์ด๋„๋ก setQueryData() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.