240724 TIL_최종 프로젝트_ 실시간 채팅

미밍·2024년 7월 25일

우당탕탕 개발 일기

목록 보기
85/108

실시간 채팅 기능 => 수파베이스로 구현하기로 함

  1. 프로젝트 기간 내내 수파베이스를 써서 익숙했음
  2. '구독(Subscribe)' 이라는 기능 발견 => 한 번 써보고 싶음

제일 먼저, 구독이 뭐길래 수파베이스 실시간 챗에서 많이 쓸까? 가 궁금했다.
이전에 crud는 해본 경험이 있어서, 실시간 챗도 막연하게 데이터를 보내면, 하나씩 불러오는 기능일 줄 알았는데~...

해봐야 알겠지만, 모든 변경사항(이벤트)을 알아서 감지하는 듯 하다.

수파베이스에 나와있는 기본 문법

const channel = supabase.channel("room1")

channel.on("broadcast", { event: "cursor-pos" }, (payload) => {
  console.log("Cursor position received!", payload);
}).subscribe((status) => {
  if (status === "SUBSCRIBED") {
    channel.send({
      type: "broadcast",
      event: "cursor-pos",
      payload: { x: Math.random(), y: Math.random() },
    });
  }
});

흠🧐 일단... 테이블은 서칭해보니 룸 / 챗 으로 나눠지는 듯 하여 (룸이 여러개일 경우를 대비) 룸에서 더미 데이터 삽입... 챗에도 더미 데이터를 하나 삽입하고, 일단 해보기로 함.

그 전에 인풋 관리 어떻게 할지 선택

  1. useState
  2. useRef : ui 반영할 때 어차피 useState 써야할 것 같은 기분
  3. formData : ui 반영할 때 어차피 useState 써야할 것 같은 기분2
    => 일단 useState로 하기로 했다.
    성능 때문에 문제가 생기면 혼합해서 쓰기로 함 (고려 중)

일단 기능부터 만들고 봐야 뭔가 좀 마음이 나을 것 같아서 일단 이건 쉬운 길로 가기로 함

오케 근데 일단 이제 생각을 해볼까~

const channel = supabase.channel("room1")

channel.on("broadcast", { event: "cursor-pos" }, (payload) => {
  console.log("Cursor position received!", payload);
}).subscribe((status) => {
  if (status === "SUBSCRIBED") {
    channel.send({
      type: "broadcast",
      event: "cursor-pos",
      payload: { x: Math.random(), y: Math.random() },
    });
  }
});

나의 예상

// 채널? 혹시 rooms 테이블에서 있는 친구를 하나 선택하는 걸까? 근데 뭔가 rooms 테이블 표기도 없는데 이게 되나?
const channel = supabase.channel("room1")

//실시간 채팅에 필요한 타입이 broadcast, 근데 이벤트가 커서 이벤트 말고도 또 뭐가 있을까? 이걸 페이로드로 보내네...
channel.on("broadcast", { event: "cursor-pos" }, (payload) => {
  console.log("Cursor position received!", payload);
  
  // 구독이 된 상태라면 얘네를 보낸다는 것 같긴 한데 어디로??
}).subscribe((status) => {
  if (status === "SUBSCRIBED") {
    channel.send({
      type: "broadcast",
      event: "cursor-pos",
      payload: { x: Math.random(), y: Math.random() },
    });
  }
});

지피티의 답변

// Supabase 클라이언트를 사용하여 "room1"이라는 이름의 채널을 생성합니다.
const channel = supabase.channel("room1");

// 채널에서 "broadcast" 이벤트를 수신하여 "cursor-pos" 이벤트가 발생했을 때,
// 수신된 데이터를 콘솔에 출력합니다.
channel.on("broadcast", { event: "cursor-pos" }, (payload) => {
  console.log("Cursor position received!", payload);
})

// 채널이 구독 상태로 변경될 때 실행되는 콜백 함수를 설정합니다.
// 상태가 "SUBSCRIBED"일 때만 이벤트를 발생시킵니다.
.subscribe((status) => {
  if (status === "SUBSCRIBED") {
    // 채널을 통해 "broadcast" 타입의 메시지를 전송합니다.
    // 여기서는 "cursor-pos" 이벤트를 발생시키고, 임의의 x, y 좌표를 포함하는 페이로드를 보냅니다.
    channel.send({
      type: "broadcast",
      event: "cursor-pos",
      payload: { x: Math.random(), y: Math.random() },
    });
  }
});

^^; ....
지피티의 답변을 듣고 난 생각
1. 커서 이벤트 말고 다른 이벤트를 찾아봐야겠다.
2. 페이로드는 인풋 값으로 넣으면 되지 않을까?
3. 채널에다 넣는다는데 그 채널은 어떻게 접근하면 되는 거냐? 테이블은... 뭘까?

=>

좀 더 생각 중...

  1. 커서 이벤트라고 이름 짓는 건 내 마음 같다. 그냥 인풋 이벤트로 해도 될 것 같음.
  2. payload는 객체로 전달되는 모양이니 객체로 넣으면 되는 걸까?
  3. 데이터 베이스랑.... 실시간 채팅 채널은 아예 다른 구조인 거 같다....???

=>

좀 더 생각 중...

3-1) DB랑 연결했을 때의 장점
데이터 복구 가능할 것 같다... 본인이 쓴 채팅 확인 가능

3-2) DB랑 연결하지 않았을 때의 장점
메시지 기록을 유지할 필요가 없는 경우라면 더 간단하게 가능할 것 같다.

=>

좀 더 생각 중

  1. DB랑 연결시키기로 한다. => 단, 데이터 관련 처리를 해줘야 할 것 같다. 하루가 지나면 삭제 되는 등의 로직을 추가 구현하기로 한다. usertest 기간에는 좀 더 짧게 구현해야 하는지는 고민을 더 해보기. 시간 관련은 수정만 하면 될 듯 하여 이후에 말씀 드려도 될 것 같다.

채널 구독을 하지 않으면 실시간 이벤트를 쓰지 못하기 때문에 채널 구독 + DB 올리는 것으로. 웬만하면 이번 주말까지 구현해보도록 한다~~~

=>

  1. useState vs react-qeury

  2. 더미데이터를 불러오기부터 할까? 채널 구독하기? 구독하는 건 잠깐 멈춰 ~~~

  3. react-query... 일단 보내기만 하는데 쿼리는 좀 너무 갔나..? 하지만 쿼리... 조아...

=>
react-query 채택...

1) 일단 더미 데이터로 시작한다...
2) room id 를 더미로 넣고 시작!


db에 채팅 메세지를 넣어야 하기 떄문에 일단 cr 로직은 기본적으로 필요하다.

cr 로직부터 출발~~
라우트 핸들러를 쓰는 게 조금 어색한 참... get 까지는 이거저거 없어도 작동해서 하는데, post 부터 버벅일 것 같다.


오늘 알아낸 거
1. DB에 채팅을 넣기로 함
2. 채팅에 넣는 POST 랑 // 구독은 별개
3. 라우트 핸들러 다시 복습해

API docs 로 가니 맨 밑에 구독이 있었다.

const chat = supabase.channel('custom-all-channel')
  .on(
    'postgres_changes',
    { event: '*', schema: 'public', table: 'chat' },
    (payload) => {
      console.log('Change received!', payload)
    }
  )
  .subscribe()

흐으음 '-'

const chat = supabase.channel('custom-insert-channel')
  .on(
    'postgres_changes',
    { event: 'INSERT', schema: 'public', table: 'chat' },
    (payload) => {
      console.log('Change received!', payload)
    }
  )
  .subscribe()

팀원들이 귀여운 짤 가지고 온다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

내일 할 거
1. 라우트 핸들러 강의 다시 보기....
2. POST
3. 서버 구독 관련 좀 더 확인해보기

실시간 채팅은 주말까지 끝낸다... 못 끝내면 월요일...!

profile
프론트앤드; Frontend

0개의 댓글