TIL

2024.04.01 TIL #트러블슈팅 #supabase_realtime_vs_React-Query #새로고침

inz1234 2024. 4. 2. 03:41

오늘은 두 가지의 아주....힘들었던 트러블슈팅이 있었다..ㅠㅠ

Supabase의 Realtime 기능으로 실시간 채팅기능을 구현하는 중이었다.

 

트러블슈팅

1.  react-query랑 Supabase-Realtime이 뭐가 다른데?

왜 이런 의문점이 들었냐면, 우리가 보통 react-query를 많이 애용하는 이유는

 

- 캐시에서 데이터를 가져오기 때문에

새로 추가된 데이터가 있을 때, 전체 데이터를 처음부터 다시 요청하지 않아도 된다는 점

=> 동일한 데이터에 대해 반복적인 비동기 데이터 호출 방지, 바뀐 것만 요청 = 성능측면 Good

 

- DB에 데이터가 추가-변경-삭제될 시, 

캐시공간의 변화가 일어나면서 알아서 기존 데이터를 무효화시킨 뒤 새로운 데이터를 fetch -> re-렌더링 (invalidate)

=> 항상 최신정보 확인 가능

 

이것 말고도 또 있겠지만 chatting 기능을 구현하는 와중에 

움 어차피 최신 데이터를 알아서 revalitdate 해주는 건 react-query도 마찬가지 아닌데, 

굳이 Supabase - Realtime을 써야하나? 라는 생각이 들었다.

 

그런 다음 실제로 실행해보았는데, 데이터가 추가 또는 변경될 시 화면에 즉각 반영되는 Realtime과는 다르게,

React-Query는 focus가 바뀌어야 즉, 새로고침이 되거나 다른 곳으로 이동했다가 돌아오거나 

했을 때만 데이터가 최신화되었다.

 

왜인지 알아보니 React-Query는 단방향 통신(HTTP)방법이고,

Realtime은 WebSocket 방법으로 transport(literally -> 운송)을 해주기 때문에 handShaking만 된다면 바로 반영되고

focus가 바뀌어야 하거나 할 필요는 없었다.

 

그래서 결국 Supabase-Realtime을 사용하게 되었다.

 

2. Realtime으로 바뀌는 데이터를 즉각적으로 화면에 반영하는 것은 OK! 그런데 새로고침을 하면 없어진다?

말 그대로다.

Supabase Realtime에서는 서버 측 supabase를 이용해서 데이터를 가져오도록 권장한다.

 

처음에는 의문이었다. client 측 꺼 쓰면 안되나? 

안 되는 건 아니지만, 아마도 User들의 TTV를 위해서 보다 빠른 렌더링

+ 빈 화면에서 한번 깜빡해야 렌더링 되는 것 보다는 처음부터 받아져 온 화면을 보여주는 것이 나아서 인 것 같다.

(실제로 해서 실패해봄^)

 

그런데, 문제는 클라이언트 컴포넌트 단에서 이렇게 Realtime을 구독해서 setMessage로 상태 변경을 해주어도,

새로고침을 하면,

의존성 배열 안에 있는 messages나 setMessages가 컴포넌트 하단에서 호출되지 않는 이상,

useEffect가 재실행되지 않는 문제로 서버에서 받은 데이터를 다시 messages에 할당을 하지 못 하게 된다.

혹시 useState의 지역적 상태관리 문제일까 싶어서 zustand로도 시도해 보았으나, 똑같이 새로고침을 해도 데이터가 날아갔다.

그래서 한~~참 해매다가... 위에 트러블슈팅 때, react-query에서 server 측 supabase 말고, client 측 supabase로도 

table에서 SELECT가 가능했지!! 라는 생각이 번뜩 들었다.

그래서 밑에 또 하나의 useEffect를 만들어서

useChattingQuery는 client 측 supabase로 데이터를 가져오는 로직이니까,

CSR 컴포넌트 단에서 새로고침을 할 때마다 data를 가져오는 ussChattingQuery가 호출되고,

data가 useEffect의 의존성배열 안에 있음으로써 useEffect 안의 로직이 실행되면서 최신 데이터를 messages에 할당할 수 있다.


+) 추가

와.. 왜 구독을 해도 새로고침을 하면 서버에서 데이터를 다시 못 받아오는 이유를 알았다...

supabase.auth.getUser() 로직이 들어가야만(null 이어도) 새로고침을 했을 때 원하는대로 구독이 되어 잘 받아오는 것을 발견했다...

useQuery고 useEffect 고 다 필요가 없었다...


고로,,, 첫 번째 트러블 슈팅 때만 해도 react-query 뭐하러 시간들여 로직을 작성했나 했는데,

결국 둘 다 쓰게 되어서 너무 기분 좋다는~~

오늘의 TIL도 새벽 4시를 바라보는지라 두서없이 쓴 건 아닌지 모르겠다.

아무튼~ 굳밤