Firebase 의 상위 버전이 나왔다고? Supabase 알아보고 세팅하기
2년 전 쯤이었나..
프론트엔드 개인 프로젝트를 해 보려고 서버리스 서비스인 파이어베이스를 활용했던 적이 있었다.
웹 쪽 레퍼런스가 많지는 않았어서 힘들었지만 나름대로 만족했었던 툴.
Firebase 는 비관계형 데이터베이스(nosql)로 제공이 되었었고,
Supabse 는 PostgreSQL을 기반으로 관계형 데이터 베이스 구축이 가능하다는 점이 가장 큰 차이점이었는데
조금 더 장단점을 살펴보자.
Firebase 장점
- Google의 강력한 생태계와 통합되어 있어 Google Cloud 서비스와 쉽게 연동됩니다.
- 실시간 데이터베이스와 NoSQL 데이터베이스 기능이 뛰어나며, 인증, 호스팅, 클라우드 함수 등 풍부한 기능을 제공합니다.
- 모바일 및 웹 앱 개발에 특화되어 있고, SDK가 매우 안정적입니다.
- 큰 커뮤니티와 풍부한 문서화로 학습 리소스가 많습니다.
Firebase 단점
- 대규모 데이터나 복잡한 쿼리에서는 성능과 비용 효율성이 떨어질 수 있습니다.
- 벤더 락인(Vendor Lock-in)의 위험이 있으며, 다른 플랫폼으로의 마이그레이션이 어렵습니다.
- 상세한 데이터베이스 스키마 설계와 관계형 데이터베이스 기능이 제한적입니다.
Supabase 장점
- PostgreSQL 기반으로 관계형 데이터베이스의 강력한 기능을 제공합니다.
- 오픈소스 접근 방식으로 더 높은 유연성과 커스터마이징 옵션을 제공합니다.
- 실시간 변경 감지, Row Level Security 등 현대적인 데이터베이스 기능을 지원합니다.
- Firebase보다 더 저렴한 가격 정책을 가지고 있습니다.
Supabase 단점
- Firebase에 비해 상대적으로 커뮤니티와 생태계의 규모가 작습니다.
- 일부 기능들이 아직 완전히 성숙하지 않았을 수 있습니다.
- Google의 광범위한 클라우드 통합 기능만큼 포괄적이지 않을 수 있습니다.
사실 Firebase 의 아쉬운 점이 복잡한 쿼리작업에 한계가 있다는 점 정도라면 내가 할 프로젝트에는 그정도의 쿼리가 필요하지는 않기 때문에 큰 의미는 없지만, Firebase 를 한번 써 보기도 했었고, 비관계형 데이터 베이스가 개인적으로는 살짝 불편한 느낌이라 이번 사이드 프로젝트에는 Supabase 를 활용해보기로 결정!
프로젝트 Setting
나는 Next.js 프로젝트에 세팅 예정이다. 우선 Supabase 사이트에 접속하자.
Supabase 에 회원가입, 로그인을 했다면 Organization과 Project 생성이 필요하다.
생성을 완료했다면 제공되는 API key와 Project URL 을 복사해두자.
그리고 내 Next.js 프로젝트의 env 파일에 해당 값들을 넣어둔다.
그리고 supabase 웹 사이트에서 자체적으로 테스트용 테이블들을 생성해서 row 들을 추가해 두었다.
그리고 난 후
Next.js 프로젝트에 @supabase/supabase-js 패키지를 설치하자.
yarn add @supabase/supabase-js
그리고 supabse 를 불러올 파일을 내 Next.js 프로젝트에 하나 생성한다.
나는 utils 라는 폴더를 만들고 그 안에 파일을 생성했다.
// src/utils/supabase/client.ts
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL as string;
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY as string;
export const supabase = createClient(supabaseUrl, supabaseKey);
이렇게 생성된 supabase 클라이언트를 export 해서 서버 요청 시 활용할 수 있는데,
이 요청을 하기 위한 폴더를 api 라는 이름으로 새로 생성했다.
// src/api/test/test.ts
import { supabase } from "@/utils/supabase/client";
export default async function handler() {
const { data: user, error } = await supabase.from("user").select("*");
console.log(user);
console.log(error);
return user;
}
이렇게 supabase 에 접근해서 user 라는 테이블에 모든 rows 를 가지고 오라는 명령어를 입력하고 콘솔창에 잘 나오는지 확인
만든 handler 함수를 활용하기 위해서 React Component 페이지에서 해당 함수를 호출했다.
"use client";
import { useEffect } from "react";
import handler from "@/api/test/test";
export default function Server() {
useEffect(() => {
const testFunction = async () => {
await handler();
};
fetchUser();
}, []);
return (
<div>
<h1>Server Test Page</h1>
<pre>{JSON.stringify(user, null, 2)}</pre>
</div>
);
}
이렇게 supabase 테스트 완료! 인 줄 알았는데...
에러 핸들링 - 테이블 데이터 조회를 하는데 빈 배열이 나오는 현상
왜 빈 배열이 나오는거지???????
분명히 테스트 테이블에 2개의 데이터를 넣어두었는데 말이다...
RLS policy 문제인 것으로 의심
여기서 잠깐 RLS 란? Row Level Security 정책의 약자로 데이터베이스 수준에서 테이블의 각 행에 대한 접근 권한을 세밀하게 제어하는 PostgreSQL의 보안 기능이다.
쉽게 말해서 권한이 없어서 그렇다는 것
우선 Add RLS policy 버튼을 클릭해서 정책을 추가해주자.
이렇게 RLS 정책을 disable 하니까 테이블 데이터 조회는 잘 됨
그런데 찝찝하자나,,
권한 정책 설정을 해 보자.
요렇게 Policy Name 을 설정하고 using 에 원하는 값을 넣어주면 정책 설정이 가능하다.
권한에 따라 이렇게 다양하게 설정할 수 있으니 참고!
1. 공개 읽기 권한 정책 생성
-- 모든 사용자에게 읽기 권한 부여
CREATE POLICY "Allow public read"
ON your_table
FOR SELECT
USING (true);
2. 인증된 사용자에게만 권한 부여
CREATE POLICY "Allow authenticated users to read"
ON your_table
FOR SELECT
USING (auth.uid() IS NOT NULL);
3. 특정 조건부 접근 정책
CREATE POLICY "Allow specific conditions"
ON your_table
FOR SELECT
USING (
-- 예: 특정 컬럼 값에 따른 접근 제어
some_column = current_user_id()
);
4. Supabase 클라이언트 측 권한 설정
const supabase = createClient('YOUR_SUPABASE_URL', 'YOUR_SUPABASE_ANON_KEY', {
auth: {
persistSession: true
}
})