TIL (240201)

Jtiiin:K·2024년 2월 1일
0

내일배움캠프

목록 보기
82/85
post-thumbnail

실시간 알림 (내가 해냄😤)

내가 쓴 리뷰에 댓글이 달리면 실시간 알림이 오는 기능!


✅ 오늘 계획


어제 알림을 띄우는 것까지는 성공했으니
추가로 해야할 것에 대해 먼저 생각해봤다
1. 알림을 어떻게 보여줄까?
2. 어디에 알림버튼을 둘까?
3. 여러 개의 알림을 어떻게 하나씩 읽음처리할까?
4. 모든 알림을 어떻게 한 번에 읽음처리할까?

프로젝트가 거의 막바지라 초반부처럼 일단 코드를 냅다 짜면서 만들기에는
다른 코드들까지 많이 건들게 될 것 같아서
위의 네가지를 어떻게 할지 미리 생각해보는 데만
오전 시간을 다 쓴 것 같다 🤔

알림을 어떻게 보여줄까?

  • 모달
    실시간 알림을 처음 구현할 때는 모달 형태로 보여주고 싶었는데
    모달로 구현된다면 여러개의 댓글이 연달아 달리는 상황을 가정하면
    모달이 계속해서 겹치는 형태가 되고 사용자에게 불편을 줄 것 같았다
  • 드롭다운 형식
    여러 개의 댓글이 연달아 달린다고 해도 한개의 드롭다운 안에
    모든 내용이 들어가기 때문에 모달처럼 겹치는 문제는 없을 것 같아서
    드롭다운 형식을 선택했다

어디에 알림버튼을 둘까?

그렇다면 드롭다운을 펼칠 버튼은 어디에 두는 것이 좋을까?
처음부터 헤더를 고려한 것은 아니지만
어느 페이지에 있어도 실시간 알림을 확인할 수 있는 곳은
헤더밖에 없는 것 같아서 헤더에 두기로 했다
(모든 페이지에 있어서 unmount 되지 않는 컴포넌트이기도 함)

여러 개의 알림을 어떻게 하나씩 읽음처리할까?

테이블에 read column을 만들어서 초기값을 false로 지정해두고
알림을 클릭할 때마다 read : true 로 수정하자!

모든 알림을 어떻게 한 번에 읽음처리할까?

모두 읽음 버튼을 만들어서 모든 알림을 한번에 read: true 로 수정!


✅ 적용

커스텀 훅(useAlarm)

useAlarm이라는 커스텀 훅에 Query로 서버통신하기

  • 알림 가져오기 (data = alarmData)
    └'alarm' 테이블에 현재 로그인한 유저id로 온 알림 중 read: false 인 데이터
  • 알림 추가하기 (댓글 등록시)
  • 한 개의 알림 수정하기 (read:true)
  • 모든 알림 수정하기 (read:true)

적용 방법

커스텀 훅에서 읽어온 알림데이터 (alarmData)를 가져와서
alarm 테이블에 변화가 생겼을 때(INSERT,UPDATE) 알림 아이콘의 상태값을 바꾸고
아이콘이 클릭됐을 때 펼쳐지는 드롭다운에 알림 내용을 넣어줬다

💥 문제 💥
알림을 모두 확인한 후 alarmData가 빈배열이 되면
다시 알림 아이콘을 돌려놔야 하는데 이 부분이 계속 바뀌질 않았다
useEffect의 dependency array에 alarmData를 넣어도
해당 값이 변하는 걸 알아채지 못했다
결국 useEffect를 하나 더 만들어서 alarmData를 따로 담아줬더니 해결!
(alarmData를 가져오는 useQuery가 비동기로 실행돼서 그런듯!)

🔽 내가 생각한 코드 🔽

 .on(
        'postgres_changes',
        {
          event: 'UPDATE',
          schema: 'public',
          table: 'alarm',
          filter: `received_id=eq.${userId}`,
        },
        (payload) => {
          queryClient.invalidateQueries({
            queryKey: ['alarm', userId],
          });
          // 안되던 부분
          if(alarmData?.length===0){
             setAlarmState(false)
        }
        },
      )

🔽 해결된 코드 🔽

// header.tsx
 useEffect(() => {
    if (!userId) return;
    const subscription: RealtimeChannel = supabase
      .channel('custom-filter-channel')
      .on(
        'postgres_changes',
        {
          event: 'INSERT',
          schema: 'public',
          table: 'alarm',
          filter: `received_id=eq.${userId}`,
        },
        (payload) => {
          queryClient.invalidateQueries({
            queryKey: ['alarm', userId],
          });
          // 알림 아이콘 변경
          setAlarmState(true);
        },
      )
      .on(
        'postgres_changes',
        {
          event: 'UPDATE',
          schema: 'public',
          table: 'alarm',
          filter: `received_id=eq.${userId}`,
        },
        (payload) => {
          queryClient.invalidateQueries({
            queryKey: ['alarm', userId],
          });
        },
      )
      .subscribe();
    return () => {
      subscription.unsubscribe();
    };
  }, []);

// alarmData 가 빈배열 일 때 (= 새 알림이 없을 때) 
  useEffect(() => {
    if (alarmData?.length === 0) {
      // 알림 아이콘 변경
      setAlarmState(false);
    }
  }, [alarmData]);

✅ 추가 보완할 점

한 리뷰에 여러 개의 댓글이 달릴 경우 한 번만 리뷰페이지에 방문하면
사실상 해당 리뷰에 대한 댓글을 모두 확인하는 것인데
이를 어떻게 처리할지 아직 고민 중이다
추가로 좋아요에 대한 알림과 댓글이 실시간으로 화면에 반영될 수 있도록 하는 것도 해볼 예정!
빡세다 빡세 😣

profile
호기심 많은 귀차니즘의 공부 일기

0개의 댓글