본문 바로가기
내일배움캠프 TIL

2024-01-11 본 캠프 70일차 / 89일차 TIL (supabase rpc 함수 및 realtime table)

by KMS_99 2024. 1. 12.

2024-01-11 본 캠프 70일차 / 89일차 TIL (supabase rpc 함수 및 realtime table)

 

주요 진행사항 :
- supabase rpc 함수 제작 

- supabase realtime table 검증

 

예정사항

- realtime chat 테스트

 


supabase rpc 함수 제작

dm을 구현하기 위해서 api 호출을 통해 supabase 테이블에 접근해야한다.

유저당 스페이스 별 dm 채널을 가져오기 위해서 1차로 user가 접속한 space를 확인하고 2차로 해당 space 내부의 dm 채널 중에서 나의 dm채널만을 확인해야하는 번거로움이 있었다.

이러한 문제는 api 호출을 이후 클라이언트에서의 로직으로 해당 유저의 dm채널을 가져와야하는 문제가 발생되었다.

 

나는 애초에 api를 호출할 때 해당 채널의 지정한 유저의 dm 채널만을 가져오고 싶었다.

 

그러던 중 supbase의 rpc 함수라는 것을 알 수 있었다.

 

rpc : Remote Procedure Call (원격 프로시저 호출)

별도의 원격제어를 위한 코딩 없이 다른 주소공간에서 함수나 프로시저를 실행할 수 있게하는 통신 기술

supabase는 rpc 기술을 통해 sql 로직을 함수화 하여 제공한다.

 

따라서 나는 복잡한 sql로직을 다음과 같이 함수화 하였다.

CREATE OR REPLACE FUNCTION get_dm_channels(p_space_id text, p_user_id text, p_receiver_id text)
RETURNS SETOF dm_channels AS $$
BEGIN
  RETURN QUERY 
  SELECT * FROM dm_channels d
  WHERE d.space_id::text = p_space_id AND 
  (
    (d.user::text = p_user_id AND d.other_user::text = p_receiver_id) OR 
    (d.user::text = p_receiver_id AND d.other_user::text = p_user_id)
  );
END; $$ 
LANGUAGE 'plpgsql';

 

이 함수를 통해서 클라이언트 단에서는 다음과 같이 코드를 간소화 할 수 있다.

 

export const checkDmChannel = async ({
  receiverId,
  currentUserId,
  spaceId,
}: checkDmChannelArgs) => {
  const dmChannel = await supabase.rpc("get_dm_channels", {
    p_space_id: spaceId,
    p_user_id: currentUserId,
    p_receiver_id: receiverId,
  });

  return dmChannel.data?.length ? dmChannel.data[0].id : null;
};

 


supabase realtime 검증

supabase은 realtime 기능을 제공하여, 실시간으로 일어나는 여러 작업들을 구독할 수 있다.
해당 기능으로 테이블의 이벤트, 유저의 채널접속, broadcast 등 여러 이벤트를 처리할 수 있다.

현재 구현하고자 하는 realtime chat 기능은 supabase realtime을 메인으로 처리하는 기술이다.

필요로 하는 기술은 테이블 이벤트를 실시간으로 추적하는 기능이므로 supabase realtime의 postgres-changes 이벤트를 처리하였다.

 

우선 구독하고자 하는 테이블에 realtime 체크를 해준다.

 

해당 테이블의 이벤트를 구독하기 위해서 필요한 것은 채팅을 하기위한 user 간 같은 채널을 공유하는 것이다.

 const dmChannel = supabase.channel(`dm_channel_${space_id}`);

 

다음과 같이 채널을 세팅하였다면, postgres_changeres이벤트를 구독하면 되겠다.

 dmChannel.on(
          "postgres_changes",
          {
            event: "INSERT",
            schema: "public",
            table: "dm_messages",
            filter: `receiver_id=eq.${response?.id}`,
          },
          () => {
            console.log("메시지가 도착했어");
          }
        );

 

여기서 event는 테이블에 일어나는 이벤트를 이야기하며 INSERT, DELETE, UPDATE, * 이 존재한다.

내가 여기서 굵은 글씨로 강조한 이유가 있다.

event는 무조건 대문자로 작성해야한다... 아니면 오류가 발생한다.

나도 알고싶지 않았다...ㅎ

 

해당 event 부분이 아닌 다른 부분에 오류가 나타나기 때문에 찾는데 오랜시간 걸렸다. (한 1시간 헤맸다)

 

다음으로 구독하고자하는 table 명과 해당 테이블에서 필터링할 데이터를 설정할 수 있다.

 

마지막 부분에 콜백함수를 통해 해당 이벤트가 발생했을 때 이벤트 처리를 해주면 되겠다.