Supabase 완벽 가이드: Firebase 대안으로 떠오르는 오픈소스 백엔드 플랫폼
안녕하세요, 쌍팔년생 개발자입니다.
작년에 저희 팀에서 새로운 프로젝트 백엔드를 선택하면서 정말 고민이 많았어요. Firebase를 쓰자니 비용이 부담스럽고, NoSQL의 한계도 있고... 그렇다고 처음부터 백엔드를 구축하자니 시간도 부족하고 복잡하고...
특히 Firebase의 Firestore를 사용하면서 "복잡한 쿼리를 어떻게 하지?"라는 고민이 계속 있었거든요. 관계형 데이터베이스의 강력함이 그리웠는데, 그렇다고 처음부터 구축하기에는 너무 큰 작업이었어요.
그러던 중 시니어 개발자분이 "Supabase라는 플랫폼이 있는데, PostgreSQL 기반으로 Firebase 같은 편의성을 제공한대"라고 알려주셨어요. 처음에는 "또 다른 BaaS인가?"라는 생각이었는데...
TL;DR: Supabase는 PostgreSQL 기반의 오픈소스 백엔드 플랫폼으로, Firebase의 완벽한 대안입니다. 실시간 데이터베이스, 인증 시스템, 파일 스토리지, Edge Functions를 통합 제공하며, SQL의 강력함과 NoSQL의 편의성을 동시에 제공합니다.
실제로 사용해보니 저희가 고민하던 문제들을 정말 깔끔하게 해결해주더라고요. 이 글에서는 그때의 경험을 바탕으로 Supabase가 무엇인지, 왜 선택하게 되었는지, 실제 사용하면서 느꼈던 점들을 공유해드리려고 해요.
저희가 겪었던 백엔드 선택의 딜레마
1. Firebase의 아쉬운 점들
이전 프로젝트에서 Firebase를 사용했었는데, 몇 가지 아쉬운 점들이 있었어요:
비용 문제
- 사용량이 늘어날수록 예상보다 훨씬 많은 비용 발생
- "이 속도로 가면 예산 초과할 것 같은데..."라는 우려
NoSQL의 한계
- 복잡한 관계형 쿼리 구현이 어려움
- "JOIN을 어떻게 하지?"라는 고민의 연속
- 데이터 정규화의 어려움
벤더 락인 우려
- Firebase에 너무 종속되는 것 같은 느낌
- "나중에 다른 플랫폼으로 이동할 수 있을까?"라는 걱정
2. 직접 구축의 부담
그렇다고 처음부터 백엔드를 구축하자니 부담이 컸어요:
- 시간 부족: 인증, 실시간 기능, 파일 업로드 등을 모두 구현하기에는 시간이 너무 부족
- 복잡성: 보안, 확장성, 유지보수 등을 고려하면 더욱 복잡
- 팀 리소스: 프론트엔드 개발에 집중하고 싶었는데 백엔드까지 신경 쓰기 어려운 상황
3. 팀 내 의견 충돌
팀 미팅에서도 의견이 갈렸어요:
- "그냥 Firebase 계속 쓰자": 빠른 개발을 원하는 의견
- "PostgreSQL로 직접 구축하자": 장기적 관점을 중시하는 의견
- "다른 대안은 없을까?": 절충안을 찾고 싶어하는 의견
Supabase 발견과 첫 인상
시니어 개발자의 추천
그때 저희 팀의 시니어 개발자분이 "Supabase라는 플랫폼을 찾았는데, 우리가 원하는 걸 모두 제공하는 것 같아"라고 하시면서 자료를 공유해주셨어요.
"PostgreSQL 기반이면서 Firebase처럼 쉽게 사용할 수 있다고 해. 게다가 오픈소스야."
처음에는 "정말? 그런 게 있어?"라며 반신반의했죠.
첫 번째 테스트
팀에서 함께 공식 문서를 보면서 첫 테스트를 진행했어요. 설치부터 간단한 CRUD까지 해보는데...
"어? 이거 정말 간단하네?"
몇 줄의 코드로 PostgreSQL 기반의 실시간 데이터베이스가 동작하는 걸 보고 정말 놀랐어요.
// 이렇게 간단한 코드로!
const { data, error } = await supabase
.from('posts')
.select('*')
.eq('published', true)
.order('created_at', { ascending: false })
"복잡한 SQL 쿼리도 쉽게 작성할 수 있잖아?"라며 팀원들이 감탄했어요.
Supabase가 저희 문제를 해결한 방법
1. SQL의 강력함 + NoSQL의 편의성
가장 마음에 든 점은 PostgreSQL의 모든 기능을 그대로 사용할 수 있다는 거였어요:
-- 복잡한 조인과 집계도 자유롭게!
SELECT
u.name,
COUNT(p.id) as post_count,
AVG(p.likes) as avg_likes
FROM users u
LEFT JOIN posts p ON u.id = p.author_id
WHERE u.created_at >= '2024-01-01'
GROUP BY u.id, u.name
HAVING COUNT(p.id) > 5
ORDER BY post_count DESC;
"드디어 복잡한 쿼리를 마음껏 쓸 수 있겠네!"라는 생각에 정말 기뻤어요.
2. 실시간 기능의 놀라운 구현
Firebase의 실시간 기능만큼 중요했던 요구사항이었는데, Supabase의 실시간 구독을 보고 깜짝 놀랐어요:
// PostgreSQL에서 실시간 구독이!
const subscription = supabase
.channel('public:posts')
.on('postgres_changes', {
event: '*',
schema: 'public',
table: 'posts'
}, (payload) => {
console.log('실시간 업데이트!', payload)
})
.subscribe()
"PostgreSQL에서도 실시간이 된다고? 어떻게?"라며 팀원들이 신기해했어요.
3. 보안도 데이터베이스 레벨에서
Row Level Security(RLS)를 보고 정말 감탄했어요:
-- 사용자는 자신의 게시물만 볼 수 있도록
CREATE POLICY "Users can view own posts" ON posts
FOR SELECT USING (auth.uid() = user_id);
"보안 설정을 데이터베이스 레벨에서 할 수 있네? 이거 정말 안전하겠는데!"
실제 프로젝트 적용 경험
첫 번째 프로젝트: 블로그 플랫폼
팀에서 결정한 첫 번째 Supabase 프로젝트는 간단한 블로그 플랫폼이었어요.
데이터베이스 설계
-- 사용자 프로필
CREATE TABLE profiles (
id UUID REFERENCES auth.users(id) PRIMARY KEY,
username TEXT UNIQUE NOT NULL,
full_name TEXT,
bio TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 블로그 포스트
CREATE TABLE posts (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
author_id UUID REFERENCES profiles(id) NOT NULL,
published BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
"PostgreSQL이니까 설계가 훨씬 직관적이네!"라며 팀원들이 만족해했어요.
실시간 기능 구현
// 새 포스트가 등록되면 실시간으로 업데이트
export function usePosts() {
const [posts, setPosts] = useState<Post[]>([])
useEffect(() => {
// 초기 데이터 로드
const fetchPosts = async () => {
const { data } = await supabase
.from('posts')
.select('*, profiles(username, avatar_url)')
.eq('published', true)
.order('created_at', { ascending: false })
setPosts(data || [])
}
fetchPosts()
// 실시간 구독
const subscription = supabase
.channel('public:posts')
.on('postgres_changes', {
event: '*',
schema: 'public',
table: 'posts'
}, () => {
fetchPosts() // 변경사항 발생시 다시 로드
})
.subscribe()
return () => subscription.unsubscribe()
}, [])
return { posts }
}
"Firebase보다 더 직관적인 것 같은데?"라는 반응이었어요.
개발 속도의 향상
실제로 개발해보니 속도가 정말 빨랐어요:
- 인증 시스템: 몇 줄의 코드로 완성
- 파일 업로드: Storage API로 간단하게 구현
- 실시간 기능: PostgreSQL과 완벽 연동
- 복잡한 쿼리: SQL로 자유자재로 작성
팀장님도 "이렇게 빨리 개발이 될 줄 몰랐네"라고 하시면서 만족해하셨어요.
예상치 못한 장점들
1. 오픈소스의 안정감
"혹시 회사가 망하거나 정책이 바뀌면 어떻게 하지?"라는 걱정이 있었는데, 오픈소스라서 그런 걱정이 없어졌어요.
2. PostgreSQL 생태계 활용
기존에 사용하던 PostgreSQL 도구들을 그대로 사용할 수 있어서 좋았어요:
- pgAdmin으로 데이터베이스 관리
- 기존 SQL 지식 그대로 활용
- PostgreSQL 확장 기능들도 사용 가능
3. 합리적인 가격 정책
Firebase 대비 가격이 정말 합리적이더라고요:
플랜 | 월 요금 | 주요 특징 |
---|---|---|
Free | $0 | 2개 프로젝트, 500MB DB |
Pro | $25 | 무제한 프로젝트, 8GB DB |
"이정도면 스타트업에서 부담 없이 시작할 수 있겠네!"
아쉬운 점들과 한계
완벽한 솔루션은 아니었어요. 몇 가지 아쉬운 점들도 있었어요:
1. 학습 곡선
팀원 중에 SQL에 익숙하지 않은 분들은 처음에 어려워하셨어요. "NoSQL이 더 쉬웠는데..."라는 의견도 있었죠.
2. 일부 고급 기능의 제약
Firebase 대비 일부 기능들이 아직 부족한 부분이 있었어요:
- Analytics 기능이 제한적
- 일부 확장 기능들이 아직 Beta 단계
3. 한국어 자료 부족
영어 문서는 풍부하지만 한국어 자료가 부족해서 팀원들이 초기에 적응하는 데 시간이 걸렸어요.
팀의 최종 결론
몇 개월간 사용해본 결과, 팀 전체가 만족하고 있어요:
긍정적인 결과
- 개발 속도 향상: Firebase 대비 오히려 더 빠른 개발
- 비용 절약: 예상보다 훨씬 저렴한 운영비
- 기술적 만족도: SQL의 강력함을 마음껏 활용
- 팀 역량 향상: PostgreSQL과 SQL 실력 전체적으로 향상
앞으로의 계획
현재 새로운 프로젝트들은 모두 Supabase를 기본으로 고려하고 있어요. 특히 다음 프로젝트에서는 Edge Functions도 활용해볼 예정이에요.
// 다음 프로젝트에서 시도해볼 Edge Function
// 이메일 발송 기능
const sendEmail = async (emailData) => {
const { data, error } = await supabase.functions.invoke('send-email', {
body: emailData
})
return data
}
결론
저희 팀의 Supabase 도입 경험을 돌아보면, 확실히 Firebase의 훌륭한 대안이라고 생각해요. 특히 SQL에 익숙하거나 복잡한 데이터 관계를 다뤄야 하는 프로젝트라면 정말 추천하고 싶어요.
물론 모든 프로젝트에 완벽한 솔루션은 아니에요. 하지만 개발 속도, 비용, 확장성, 그리고 개발자 경험을 모두 고려했을 때 매우 균형 잡힌 선택이었습니다.
혹시 저희와 비슷한 고민을 하고 계신 분들이 있다면 한번 시도해보시기를 추천드려요. 시니어 개발자분이 알려주신 덕분에 저희 팀의 백엔드 개발 방식이 완전히 바뀌었거든요.
더 궁금한 점이나 실제 도입 경험을 공유하고 싶으시면 언제든 댓글로 남겨주세요! 함께 고민해보면 좋겠어요.
참고 자료