![[인프런 워밍업 클럽 3기] 풀스택 스터디 4주차 미션 회고 발자국](https://cdn.inflearn.com/public/files/blogs/dbc7e990-ec19-4452-967c-cf9440d722c5/thumbnail.png)
[인프런 워밍업 클럽 3기] 풀스택 스터디 4주차 미션 회고 발자국
학습 내용 요약
인프런 워밍업 클럽 3기 풀스택 스터디 4주차에는 Supabase의 Real Time Database와 Authentication, RLS(Row Level Security) 기능을 활용하여 실시간 채팅 기능을 지원하는 인스타그램 클론 프로젝트를 진행해 보았습니다. 인프런에서 발자국을 작성할 때 강의를 보지 않고도 강의 내용을 파악할 수 있을 만큼 자세한 내용을 작성하는 건 지양해 달라고 가이드한 만큼 강의에 대한 필기는 최소화 하고 회고 위주로 적어보겠습니다.
Supabase Realtime Database 주요 기능
데이터 실시간 업데이트
데이터베이스의
INSERT
,UPDATE
,DELETE
이벤트를 감지특정 테이블, 컬럼 또는 조건에 따라 변경 사항을 필터링 가능
PostgreSQL 기반 트리거 (Trigger) 활용
기존 Postgres 데이터베이스와 완벽하게 통합
트리거(Trigger)를 사용해 복잡한 로직을 추가 가능
채널 기반 구독 (Channels & Broadcast)
특정 테이블 또는 쿼리에 대해 채널을 구독(Subscribe) 하여 변경 사항 수신
클라이언트 간 브로드캐스트(Broadcast) 메시지 전송 가능
Row Level Security (RLS) 지원
실시간 데이터도 Postgres RLS 규칙을 준수
특정 사용자만 특정 데이터에 대한 실시간 업데이트를 수신 가능
저지연(Low Latency) 데이터 업데이트
PostgreSQL의 LISTEN/NOTIFY를 사용하여 빠른 데이터 전송
웹소켓(WebSocket) 기반으로 구현되어 빠른 응답 가능
Supabase Authentication 주요 기능
다양한 로그인 방식 지원
이메일/비밀번호 로그인 (기본 제공)
소셜 로그인 (OAuth) → Google, GitHub, Apple, Discord 등
Magic Link (비밀번호 없이 이메일 링크 클릭으로 로그인)
OTP (SMS 기반 인증)
SAML, OpenID Connect 지원 (엔터프라이즈 인증)
Row Level Security (RLS) 통합
Postgres의 Row Level Security (RLS) 를 활용하여 사용자별 데이터 접근 제한 가능
auth.uid()
함수를 사용하여 현재 로그인한 사용자 필터링 가능
JWT 기반 인증 및 커스텀 클레임
로그인 시 JWT(JSON Web Token) 가 발급됨
필요에 따라 사용자 정의 클레임(Custom Claims) 추가 가능
비밀번호 재설정 및 사용자 관리
이메일을 통한 비밀번호 재설정 기능 제공
사용자 프로필 정보 (
auth.users
테이블) 관리 가능
기기 기반 인증 및 다중 세션 관리
기기별 세션을 유지하고 관리할 수 있음
다중 기기 로그인 지원
Supabase RLS 주요 기능
사용자별 데이터 접근 제어
로그인한 사용자만 자신의 데이터에 접근하도록 설정 가능
auth.uid()
를 사용해 현재 로그인한 사용자의 UID를 자동 감지
PostgreSQL 정책(Policy) 기반 권한 관리
CREATE POLICY
를 사용하여 테이블 단위의 접근 정책 설정 가능특정 역할(Role) 또는 조건을 만족하는 사용자만 데이터 접근 허용
JWT 기반 인증과 연동
Supabase의 Authentication(JWT) 와 함께 사용 가능
JWT의 사용자 ID(UID), 이메일, 역할(Role) 정보를 활용하여 정책 적용
유연한 권한 설정
읽기(Read) 전용 정책 설정 가능
소유자(Owner) 기반 정책을 설정하여 자신의 데이터만 수정 가능
특정 사용자 그룹(Role)에게만 접근 권한 부여 가능
인스타그램 클론 미션 회고
풀스택 스터디 4주차 미션은 강의에서 진행하는 Next.js와 Supabase Realtime Database, Authentication, RLS를 활용한 인스타그램 클론 앱에 여러 편의 기능을 추가하는 것과, 지금까지 진행했던 모든 프로젝트들을 배포까지 해보는 것이었습니다. 이번에도 역시 강의와는 다르게 실제 인스타그램의 MVP를 구현하는 것을 목적으로 했으며, 4주간 학습했던 내용들을 최대한 담아보았습니다. 진행했던 미션은 해당 링크에서 보실 수 있습니다.
미션 수행 내용
아래는 제가 수행한 미션에 대한 내용을 정리해보았습니다.
로그인 기능
이메일 기반 로그인
Confirmation URL 방식
프로필 설정
아이디 설정 기능
이름 설정 기능
프로필 이미지 설정 기능
유저 탐색 기능
유저 프로필 조회 기능
팔로잉 수 조회 기능
팔로워 수 조회 기능
팔로잉 기능
팔로잉 목록 조회 기능
팔로워 목록 조회 기능
실시간 채팅 기능
메시지 삭제 기능
메시지 읽음 상태 확인 기능
채팅방 접속 상태 확인 기능
사용 기술
프레임워크:
Next.js v15
,React v19
데이터베이스:
Supabase
서버 상태관리:
Tanstack Query v5
클라이언트 상태관리:
Zustand v5
스타일 프레임워크:
TailWindCSS v3
,Mantine v7
,Tabler Icons
모노레포:
Turbo Repo
패키지 매니저:
pnpm
트러블 슈팅
Next.js useSearchParams 훅 빌드 환경 에러
개발환경에서는 다른 문제가 없었는데, 빌드 시점에 Next.js 에서 제공하는 useSearchParams
훅을 사용한 로직이 아래의 에러를 반환하는 문제가 있었습니다.
usesearchparams() should be wrapped in a suspense boundary at page "/404".
관련 이슈를 찾아보니 Next.js 14 버전 부터 useSearchParams
훅이 기본적으로 suspense boundary 에서 동작하도록 수정되어서 발생하는 이슈였습니다. 저의 경우에는 탐색 페이지의 검색어, 팔로잉 페이지의 탭메뉴, 리다이렉트 시 토스트 메시지 노출 로직에 쿼리 파라미터를 사용했기에 useSearchParams
훅을 사용한 부분을 모두 아래와 같이 Suspense
로 감싸주어 해결하였습니다.
const FollowingPage: React.FC = () => (
<WithAuth>
<Suspense>
<FollowingTabs />
</Suspense>
</WithAuth>
)
const SearchPage: React.FC = () => (
<Suspense>
<div className="p-4 pb-7 pt-5">
<SearchBar />
</div>
<SearchProfileResultList />
</Suspense>
)
export const Provider: React.FC<React.PropsWithChildren> = ({ children }) => (
<QueryProvider>
<MantineProvider theme={defaultThemeSchema} defaultColorScheme="auto">
<ColorSchemeScript defaultColorScheme="auto" />
<ModalsProvider labels={{ confirm: '확인', cancel: '취소' }}>
<Suspense>
<SearchParamsMessengerProvider>
{children}
<Toaster position="bottom-right" />
</SearchParamsMessengerProvider>
</Suspense>
</ModalsProvider>
</MantineProvider>
</QueryProvider>
)
Module Federation (Micro FrontEnd)
모노레포로 모든 프로젝트를 구성했기에 마지막 배포 미션에서 4개의 프로젝트를 모두 배포하는 대신 1개의 프로젝트만 관리할 목적으로 마이크로 프론트엔드 기술을 적용해 보고 싶었습니다. 빌드 시점에 4개의 프로젝트를 하나의 앱으로 통합하여 하나의 도메인을 공유하는 상태로 엔드포인트만 바뀌는 방식으로 배포해보고 싶었는데, 마이크로 프론트엔드를 구성하는 핵심 기술인 Module Federation의 Next.js 플러그인이 App Router는 지원하지 않더라구요. 저는 이미 App Router로 모든 로직을 작성한데다 지금 시점에서 모두 Pages Router로 포팅하기에는 시간이 부족하다 판단하여 해당 방식은 포기하였습니다.
그래서 대체재로 Wrapper 형식의 앱을 추가로 생성한 후 Next.js의 Multi Zones 기능과 Middleware, Rewrites 기능을 조합하여 4개의 프로젝트를 묶는 방식을 고려해봤었는데, 해당 방식은 결국 4개의 프로젝트를 개별로 배포해야하는 문제가 여전히 존재하여 결국 포기하게 되었습니다. 아무리 찾아봐도 마땅한 대안이 없더라구요.
해당 내용은 직접적인 트러블 슈팅은 아니지만 아쉬워서 남겨보았습니다.
후기
처음 OT 때도 코치님이 말씀해주셨지만, 이번 주차에서는 미션의 난의도가 확 올라갔던 것 같습니다. 저는 특히 테이블 설계가 어려웠던 것 같아요. 기본적인 테이블들을 정규화를 거쳐 분리해놓으니 각 기능 별로 JOIN 로직을 거치는 단계가 복잡해져서 API 로직을 작성하면서도 이게 맞나 라는 생각이 들었던 적이 많았던 것 같습니다. 백엔드와 작업할 때 상황별로 필요한 인터페이스를 하나의 API에 모아 달라고 요청하는 경우가 많았었는데, 그게 백엔드 입장에서는 생각보다 쉽지 않은 일일 수 있었겠구나 라는 생각도 하게 되었습니다.
이번 4주차 미션을 끝으로 워밍업 클럽을 완주하게 되었는데, 개인적으로 풀스택을 지향하기에 앞으로 백엔드를 더 공부해 볼 계획이라 이번 경험이 앞으로의 학습에 많은 도움이 될 것 같아요. 이번 스터디의 핵심인 Supabase는 한달 동안 사용해보니 커스터마이징 하고 싶은 부분이 몇가지 있어 Supabase 하나로 기존 백엔드의 역할을 모두 대체하는 것은 한계가 있다고 느껴졌지만, 백엔드를 모르는 프론트엔드 개발자도 손쉽게 하나의 서비스를 온전히 구현할 수 있을 정도로, 쉽고 강력하다는 장점이 크기에 앞으로도 간단한 MVP를 구현해볼 일이 있다면 종종 사용해 볼 것 같아요.
풀스택 3기 러너분들 모두 수고 많으셨습니다!
긴글 읽어주셔서 감사합니다. ☺
댓글을 작성해보세요.