프론트에서 간단하게 사용할 수 있는 오픈소스 백엔드 서비스인 Supabase 를 사용해보려고 합니다. Supabase는 데이터베이스 ,클라우드, 호스팅, 스토리지, 인증, 실시간 데이터 기능 등 많은 기능을 제공하고 무료 가격도 널널한 편이기 때문에 사이드 프로제긑로 사용하기 적합다고 생각했습니다.
SupaBase 이전에는 Firebase를 주로 사용했는데 SupaBase는 관계형 데이터 베이스이고 Firebase는 noSql의 차이점이 있습니다. Firebase 의 큰 단점이 비용과 복잡한 쿼리 처리에 제한이 있었습니다. 가장 큰 것이 비용인데 Firebase는 읽기/쓰기/삭제 비용으로 부담하지만 supabase는 저장된 데이터의 양에 따라 부과하고 속도도 supabase가 훨씬 빠릅니다
위 장단점 나열하면 이제는 정말 Supabase가 Firebase 상위로 생각이 들정도로 좋다는 생각을 했습니다
그럼 실제로 사용해보도록 하죠
1. 프로젝트 생성하기
new Project로 프로젝트 이름과 Database 비밀번호, 지역을 설정하고 생성해줍니다.
프로젝트 초기화가 끝난다면 이제 supabase를 사용할 수 있습니다
2. 프레임워크에 맞는 라이브러리 및 환경설정
위 각 프레임워크 별 환경설정 가이드를 확인하실 수 있습니다
가이드를 보면 굉장히 간단합니다
1. 기본 예시를 위한 테이블 생성
Supabase > SQL Editor에서 예시 테이블 생성 쿼리를 넣은 후 `RUN` 을 눌러 테이블을 생성합니다
2. 프레임워크 보일러 플레이트 생성
- 이미 사용해야할 프로젝트가 있다면 스킵하셔도 됩니다.
- 저는 스킵하였기 때문에 3번에서 환경설정은 처음부터 구성한다고 생각하시면 됩니다
npx create-next-app -e with-supabase
git: https://github.com/vercel/next.js/tree/canary/examples/with-supabase
2-1. 만약 사용하고 있는 프로젝트가 있다면?
- supabase 라이브러리를 다운받아 줍니다
cd my-app && npm install @supabase/supabase-js
// nextjs 일 경우 추가 설치 필요
npm install @supabase/ssr
3. Supabase 환경설정
react를 사용할 경우 createClient 를 한 후 테이블을 조회하면 되지만 nextjs 일 경우 ssr도 고려해야하기 때문에 서버용 보일러 플레이트 코드가 좀더 들어갑니다.
nextjs 의app directory를 사용한다면 브라우저용 컴포넌트과 서버 컴포넌트가 나뉘어서 사용하게 됩니다.
nextjs 가이드: https://supabase.com/docs/guides/auth/server-side/nextjs?router=pages
nextjs에서는 다양한 곳에서 supabase쿼리를 사용할 수 있기 때문에 각 위치에 맞게 utils를 생성해주면 됩니다.
브라우저에서 사용할 경우: utils/supabase/browserClient.ts
import { createBrowserClient } from "@supabase/ssr";
export const createClient = () =>
createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
);
nextJS의 getServerSideProps 를 사용할 경우: utils/supabase/serverClient.ts
import { createServerClient, type CookieOptions } from "@supabase/ssr";
import { cookies } from "next/headers";
export const createClient = () => {
const cookieStore = cookies();
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value;
},
set(name: string, value: string, options: CookieOptions) {
try {
cookieStore.set({ name, value, ...options });
} catch (error) {
// The `set` method was called from a Server Component.
// This can be ignored if you have middleware refreshing
// user sessions.
}
},
remove(name: string, options: CookieOptions) {
try {
cookieStore.set({ name, value: "", ...options });
} catch (error) {
// The `delete` method was called from a Server Component.
// This can be ignored if you have middleware refreshing
// user sessions.
}
},
},
},
);
};
nextjs의 API Route에서 사용한 경우
import { createServerClient, type CookieOptions, serialize } from '@supabase/ssr'
import { type NextApiRequest, type NextApiResponse } from 'next'
export default function createClient(req: NextApiRequest, res: NextApiResponse) {
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return req.cookies[name]
},
set(name: string, value: string, options: CookieOptions) {
res.appendHeader('Set-Cookie', serialize(name, value, options))
},
remove(name: string, options: CookieOptions) {
res.appendHeader('Set-Cookie', serialize(name, '', options))
},
},
}
)
return supabase
}
nextjs에서 getStaticProps에서 사용할 경우
import { createClient as createClientPrimitive } from '@supabase/supabase-js'
export function createClient() {
const supabase = createClientPrimitive(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
return supabase
}
그 후 환경변수 파일에 프로젝트의 환경변수를 넣어줍니다
.env
# https://app.supabase.com/project/_/settings/api
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
드디어 환경설정은 끝났습니다!
4. Supabase 쿼리 생성
browser 일 경우 아래와 같이 사용하면 됩니다
import { createClient } from '@/utils/supabase/browserClient';
// 타입 설정
interface NoteType {
id: number
title: string
}
// pages/Home
const Home = () => {
const [notes, setNotes] = useState<NoteType[]>([])
// 사용자 언어 감지
// useDetectLanguage()
useEffect(() => {
getNotes()
}, [])
const getNotes = async () => {
const { data } = await supabase.from('notes').select().returns<NoteType[]>()
setNotes(data || [])
}
return <pre>{JSON.stringify(notes, null, 2)}</pre>
}
5. 실행
각 프로젝트의 실행에 맞게 실행해서 잘 동작하는지 확인합니다.
사이드프로젝트를 할때 복잡한 서버 환경 구축하지 않고 supabase로 간단하게
백엔드를 사용해볼 수 있습니다
이상 글 읽어주셔서 감사합니다
'프로그래밍 > React|Next.js' 카테고리의 다른 글
사용 안하는 디펜던시 파일 지우기 (0) | 2024.04.04 |
---|---|
[DeepDive] 1장 - 자바스크립트: 클로저와 스코프 (0) | 2024.03.14 |
[DeepDive] 1장 - 자바스크립트: 데이터 타입과 함수 (0) | 2024.03.11 |
gatsby의 이미지 컴포넌트 비교(StaticImage, GatsbyImage) (0) | 2023.08.08 |
React로 크롬 익스텐션(extension) 만들기 (1) 튜토리얼 (0) | 2023.07.31 |