[인프런 워밍업 클럽 Full-Stack 3기] 4주차 발자국 - 인스타그램 클론코딩

[인프런 워밍업 클럽 Full-Stack 3기] 4주차 발자국 - 인스타그램 클론코딩

이번주는 강의 볼륨이 제일 많았던 인스타그램 클론코딩을 진행했다. 로그인, 회원가입을 위한 Supabase Auth와 실시간 채팅을 구현하기 위한 Supabase Realtime Database 배포까지 구현해볼 수 있었다. 이번시간엔 거의 다른 주차에 비해 2배정도 되는? 양인거 같아 월요일부터 틈틈히 해서 겨우 시간을 맞출 수 있었다.

 

수강 내용

Section 6 인스타그램 클론코딩 - Supabase 인증 구현 Part 1

이번 챕터에서는 Supabase 인증 시스템을 구현해보는 것이었다. 다음과 같은 기능을 구현했다.

  1. 이메일 인증을 통한 회원가입

  2. OTP 인증을 통한 회원가입

  3. 로그인

  4. (추가) 카카오 소셜 로그인

이는 Supabase Auth를 통해 구현했다. 강의에서는 위의 내용들만 구현했지만 Supabase Auth에는 더 다양한 기능들을 제공하고있었다. JWTSession 등을 지원하기도했고, 권한관리 등도 제공했다.

그리고 강의를 들으면서 느꼈던 것이지만 React Query를 잘 사용하셔서 React Query의 활용성에 대해서도 한번 더 성장한다는 느낌을 받았다.

Section 7 인스타그램 클론코딩 - 인스타 DM 채팅 기능 구현 Part 2

인증 기능을 모두 마친 뒤에는 실시간 채팅 기능을 구현했다. 이 시간에 Supabase Realtime Database를 학습할 수 있었다. 사실 그냥 Database랑 어떤 차이인지는.. 잘 모르겠지만 해당 기능을 켰을 때 실시간으로 채팅 기능을 수현할 수 있었다. 이때에도 React Query를 이용해 데이터를 캐싱하고 다시 불러오는 작업을 함으로써 좀 더 효율적으로 Supabase Table 데이터들을 관리할 수 있었다. 그리고 전에도 얘기했던것이지만 Database라서 그런지 메서드 자체가 SQL문을 그대로 가져와서 학부시절 DB를 배워놨었던 부분이 이해하기도, 적응하기에도 좀 더 편했었다.

export async function getAllMessages({ chatUserId }: { chatUserId: string }) {
  const supabase = await createServerSupabaseAdminClient();
  const { data, error } = await supabase.auth.getSession();

  if (error && !data?.session) {
    throw new Error("User is not authenticated");
  }

  const { data: messages, error: messagesError } = await supabase
    .from("message")
    .select("*")
    .or(`receiver.eq.${chatUserId},receiver.eq.${data?.session?.user.id}`)
    .or(`sender.eq.${chatUserId},sender.eq.${data?.session?.user.id}`)
    .order("created_at", { ascending: true });

  if (messagesError) {
    throw new Error("Failed to get messages");
  }

  return messages;
}


const {
  data: messages,
  error: messagesError,
  isLoading: messagesLoading,
  refetch,
} = useQuery({
  queryKey: ["messages", selectedIndexState],
  queryFn: async () => {
    const allMessages = await getAllMessages({
      chatUserId: selectedIndexState,
    });
    return allMessages;
  },
});
useEffect(() => {
  const channel = supabase
    .channel("message_postgres_changes")
    .on(
      "postgres_changes",
      {
        event: "INSERT",
        schema: "public",
        table: "message",
      },
      (payload) => {
        console.log(payload);
      }
    )
    .subscribe();

  return () => {
    channel.unsubscribe();
  };
}, []);

그리고 메시지를 주고받고 한 다음 채팅을 그냥 보여주기만 하면 실시간으로 동기화가 안된다는 문제점이 있어 (새로고침을 해야 보여진다.) 그 때를 위한 동기화 작업을 supabase channel기능을 사용했다.

Section 8 웹사이트 배포하기 - 도메인 등록, Vercel, AWS 배포

Vercel 배포같은 경우는 개인적으로 포트폴리오 배포할 때 유용하게 사용했었고 AWS배포도 한번쯤은 해보는것이 좋다고 해서 해본적이 있어서 좀 가볍게 들었다. 그리고 배포 시 빌드 에러를 최소화하기 위해 항상 push하기 전에 build한번 하고 push를 해서 빌드 오류도 없이 무난하게 모든 프로젝트를 배포할 수 있었다.

미션

4주차 미션은 다음과 같았다.

  1. 작성한 모든 프로젝트 배포하기

  2. 채팅 메시지 삭제 기능 구현

  3. 채팅 읽음, 안읽음 표시 기능 구현

삭제기능, 읽음/안읽음 표시 기능을 위해 supabase data table에 is_readis_deleted 항목을 추가하고 각 항목들을 update하는식으로 구현했다. 그리고 동기화를 위해 channelupdate 항목을 추가해주는걸로. 인터넷에서 찾아보니 *을 이요해 모든 이벤트 INSERTDELETEUPDATE 등을 포함할 수 있다고 했지만 그냥 업데이트만 하나 추가해주었다.

 image

ui는 그렇다 치고.. 일단 삭제 기능이랑 읽음 기능까지는 구현해봤다.

마무리

인스타그램 클론코딩을 끝으로 이렇게 4주간의 대장정이 마무리가됬다. Supabase 프로젝트 한번 해보겠다고 들을까 말까 했던 강의였는데 이렇게 다같이 스터디할 수 있는 기회가 생겨서 나 혼자 했으면 흐지부지 되었을텐데 이렇게 끝까지 완강할 수 있어서 개인적으로 뜻깊었던 스터디 기간이었다.

강의 내용도 부실하지 않고 적당히 그리고 자세하게 알려주셔서 내용을 이해하기도 쉬웠다. 또한 Supabase 자체에 국한되지 않고 Next.js나 React Query같은 프론트엔드 지식도 함께 쌓아 더 괜찮은 시간이었다. 지금 이 토대를 기반으로 다음에 할 Supabase를 통한 개인 프로젝트도 화이팅해야겠다!

댓글을 작성해보세요.


채널톡 아이콘