์ด์ ํํ๋ก์ ํธ์์๋ BaaS๋ก firebase ๋ง ์จ๋ดค์๋๋ฐ ์ด๋ฒ ํ๋ก์ ํธ์์ supabase๋ฅผ ์ฒ์์ผ๋ก ์จ๋ณด๊ฒ ๋๋ค. firebase๊ฐ ์ฌ์ฉํ๊ธฐ ํธ๋ฆฌํ ๊ฑฐ ๊ฐ์ supabase๋ ์ด๋ ต์ง ์์๊น ๊ณ ๋ฏผ์ด ์์์ง๋ง supabase๊ฐ ์ต์ํด์ง๊ธฐ๋ง ํ๋ฉด ์ ๋ง ์ข๋ค๊ณ ๋ค์๋๋ฐ ์ด๋ฒ ๊ธฐํ์ ์ฌ์ฉํ๊ฒ ๋์ด ์ค๋ ๋คใ ใ ๊ฐ๋ตํ๊ฒ supabase์ ๋ํด์ ์์๋ณด๊ณ DB๋ฅผ ์์ฑํด ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ๊ณผ์ ๋ ์กฐ๊ธ ์จ๋ณด๊ธฐ๋ก!
๐ 1. Supabase ๋?

- firebase (ํ์ด์ด๋ฒ ์ด์ค) ์ ๋์์ผ๋ก ์ธ๊ธฐ๋ฅผ ์ป๊ณ ์๋ *BaaS ํ๋ซํผ์ด๋ค.
- PostgreSQL ๊ธฐ๋ฐ์ SQL DB ๊ธฐ๋ฅ, REST API ๋ฑ์ ๊ธฐ๋ฅ์ ์คํ ์์ค๋ก ์ ๊ณต
- firebase๋งํผ ํธ๋ฆฌํ๋ฉด์๋, firebase๊ฐ ๋ชป ๊ฐ์ถ ์ฅ์ ์ ์ง๋๊ณ ์๋ค.
- RDB(Relational-Database)๋ฅผ ํตํด ์์ ์ํธ์ฒ๋ผ ๋ด์ฉ์ ์ฑ์ฐ๋ DB๋ฐฉ์์ ์ ๊ณต
- firebase๋ NoSQL ๊ธฐ๋ฐ DB๋ก, ์ฟผ๋ฆฌ ๊ธฐ๋ฅ์ด ํ์ํด ๋ฐ์ดํฐ ๊ฒ์์ด ์ด๋ ต์ง๋ง, supabase๋ PostgreSQL ๊ธฐ๋ฐ์ SQL DB ๊ธฐ๋ฅ์ ์ ๊ณตํด ๋ฐ์ดํฐ ๊ฒ์ ๋ฑ ์ฉ์ดํ ์ ์ด ๋ง์
- SQL Editor๋ฅผ ํตํด SQL ์ฟผ๋ฆฌ๋ฅผ ์นํ์ด์ง์์ ์์ฑ,์ ์ฅ,์คํ ๊ฐ๋ฅํ๊ณ , Table Editor๋ก ๋ฐ์ดํฐ๋ฅผ ์คํ๋ ๋์ํธ(์์ )์ฒ๋ผ๋ ์กฐํ,์์ฑ ๊ฐ๋ฅ
- ํด๋ผ์ด์ธํธ, ์๋ฒ ํ๊ฒฝ ๋ชจ๋์์ ๋์ผํ ๋ฐฉ์ ์์ ์ด ๊ฐ๋ฅํ ismorphic JavaScript ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๊ณต
* Baas : Backend as Service - ์๋น์คํ ๋ฐฑ์๋๋ก, ํ๋ก ํธ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฑ์๋ ์๋น์ค๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ๋ชจ๋ธ. BaaS๊ฐ ๋ฐฑ์๋ ์ฝ๋๋ฅผ ๋ง๋ค์ด์ค์ DB ์๋ฒ ์ด์/๊ด๋ฆฌ ๋ฑ์ ๋ฐฑ์๋ ์ ๋ฌด๋ฅผ ์์์ ๋ค ๋งก์์ฃผ๊ธฐ ๋๋ฌธ์, BaaS ์ฌ์ฉ์๋ ํ๋ก ํธ์๋/์ฌ์ฉ์ ์ธก๋ฉด ๊ฐ๋ฐ์๋ง ์ง์ค ํ ์ ์๋ค.
(ex ) Firebase, Supabase, AWS Amplify ๋ฑ)
๋ํ supabase ๋ firebase auth ์ฒ๋ผ ์์ ๋ก๊ทธ์ธ์ ๋น๋กฏํด ๋ก๊ทธ์ธ/ํ์๊ฐ์ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์๋ค.
์ค๋์ ์ผ๋จ next.js ํ์ ์์ฑ ํ DB๋ฅผ ์์ฑํ๊ณ ๋ถ๋ฌ์๋ดค๋๋ฐ ์ฒ์ ํ๋ค๋ณด๋ ์ข ์ ๋ฅผ ๋จน์๋ค .. (ํนํ RLS policy๋๋ฌธ์ ๐ฅฒ) ๊ณต์๋ฌธ์์ ๊ตฌ๊ธ๋ง์ ํตํด ํด๊ฒฐํ ์ ์์๋๋ฐ, ์ด ๊ณผ์ - Supabase - DB ์์ฑ, ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๋ ๋ฐฉ๋ฒ์ ๊ธฐ๋กํด๋ณด๊ธฐ๋ก ํ๋ค.
๐ 2. Next.js ํ๋ก์ ํธ๋ฅผ supabase์ ํจ๊ป ์์ฑํ๊ณ supabase์ ์ฐ๊ฒฐํด์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ
1 ) supabase ์ฌ์ดํธ์์ (next.jsํ์ ๊ณผ ์ฐ๊ฒฐํ ) ํ๋ก์ ํธ ์์ฑํ๊ธฐ
์ฐ์ supabase ์ฌ์ดํธ์ ๊ฐ์ ํ ์ ์ด ์๋ค๋ฉด ๊ฐ์ ์ ํ๊ณ ๋ก๊ทธ์ธ์ ํ๋ค.
Supabase | The Open Source Firebase Alternative
Build production-grade applications with a Postgres database, Authentication, instant APIs, Realtime, Functions, Storage and Vector embeddings. Start for free.
supabase.com
๊ทธ๋ฆฌ๊ณ start your project ๋, ๋ด dashboard ์์ New project ๋ฅผ ๋๋ฌ ํ๋ก์ ํธ๋ฅผ ์์ฑํ์.

ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ฉด ์ ์ด๋ฏธ์ง์ฒ๋ผ ํ๋ก์ ํธ url, ํ๋ก์ ํธ api key ๊ฐ ๋ฌ๋ค!
์๋์ JS ๋ฑ์ผ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์ฝ๋๋ก ์ฐ์ฌ์์
2 ) IDE : supabase์ ํจ๊ป next.js ํ๋ก์ ํธ ์์ฑํ๊ณ .env ์ ํ๋ก์ ํธ url, api key ๋ฃ๊ธฐ
๋ก์ปฌ IDE ํฐ๋ฏธ๋ ์์ (์ ๋ VSC ํฐ๋ฏธ๋ ์ฌ์ฉ) next.js ํ๋ก์ ํธ ์์ฑ๊ณผ ๋์์ supabase๊น์ง ๊ฐ์ด ์ค์น!
โจ ์๋๊ณต์๋ฌธ์ ์ฐธ์กฐ
https://supabase.com/docs/guides/getting-started/quickstarts/nextjs
Use Supabase with Next.js | Supabase Docs
_10 return {JSON.stringify(notes, null, 2)}
supabase.com
โyarn ํจํค์ง ๋งค๋์ ๋ฅผ ์ด๋ค๋ฉด, yarn create next-app -e with-supabase ํด๋ ๋ง์ฐฌ๊ฐ์ง๋ก ์ ์ค์น๋๋ค.
(์ฌ๊ธฐ์ - ํ๋๋ผ๋ ๋น ์ง๋ฉด ์๋๋๊น ์ฃผ์ํ์ ใ ใ )
์ด๋ ๊ฒ ์ค์นํ๋ฉด ์์์ next.js ํ๋ก์ ํธ ์์ฑ ํ supabase api ํค ๋ฑ์ ๋ด์๋ ์ ์๋ .env.example ํ์ผ๊น์ง ์น์ ํ๊ฒ ์์ฑ๋๋ค.
NEXT_PUBLIC_SUPABASE_URL=<SUBSTITUTE_SUPABASE_URL>
NEXT_PUBLIC_SUPABASE_ANON_KEY=<SUBSTITUTE_SUPABASE_ANON_KEY>
๊ทธ๋ผ .env ํ์ผ์ ์์ฒ๋ผ ํ๋ก์ ํธ url๊ณผ api key๋ฅผ ์จ์ฃผ์.
< .. > ๋ถ๋ถ์ ์๊น supabase์์ ๋ง๋ ํ๋ก์ ํธ์ url , api key ์ฐ๊ธฐ ( < > ์ฐ๋ ๊ฑฐ ์๋๋๋ค!)
3 ) supabase ์ฌ์ดํธ์์ ํด๋น ํ๋ก์ ํธ์ ๋ค์ด๊ฐ table editor๋ก ํ ์ด๋ธ ์์ฑํ๊ธฐ
(table editor ๋ง๊ณ ๋ sql editor ๊ฐ ์์ง๋ง, sql ๋ฌธ์ ์์ฑ ์ํด๋ดค๋ค๋ฉด ํ ์ด๋ธ์ด ํธํ ๊ฒ์ด๋ค)
schema ๋ ๋ณดํต public. ์ฌ๊ธฐ๋ค๊ฐ new table ์์ฑํด์, ํ ์ด๋ธ๋ช ์ ์ง๊ณ
*RLS ๋ ์ถ์ฒํ๋ค๊ณ ํ๋ ์ค์ ํ๋๊ฒ ์ข๊ณ - (์์ง ๋๋ ์์ธํ๋ ๋ชจ๋ฅธ๋ค... ํ์ง๋ง ํ ์์ค์ ๋ณด์์ด๋ผ๋ ์ ์ ๋ ์ฒดํฌ.)
(*RLS : Row Level Security ํ ์์ค ๋ณด์์ผ๋ก, '์์ ์ ๋ฐ์ดํฐ๋ง ๊ฐ์ ธ์ฌ ์ ์๋ค'๋ฅผ ๊ตฌํํ ์ ์๋ ๋ณด์ ์ ์ฑ ์ค์ ์ด ๊ฐ๋ฅํ๋ค๊ณ ํจ.)
Enable Realtime ๋ ์ฒดํฌํด์ผ ์ค์๊ฐ์ผ๋ก ๋ฐ์๋๋ค๊ณ ํ๋ค.
๊ทธ๋ฆฌ๊ณ columns ๋ฅผ ๋ง๋ค๋ฉด ๋ !
โcolumns ๋ง๋ค ๋ ์ฃผ์์ฌํญ
- ํ์ด์ด๋ฒ ์ด์ค ๋์ ๋ฌ๋ฆฌ, ์๋ฃํ ํ์
์ด ๋ค์ํ๊ธฐ ๋๋ฌธ์ ์ข ๋ ์ฃผ์ํ ๊ฒ.
number (int, float, numeric,..) ๋ string (varchar, text) ์ type ๋ ๋ค์ํ๊ธฐ ๋๋ฌธ์ ์ข ๋ ์๊ฐํด์ผ ํ๋ค
๐ถโ๐ซ๏ธ (๋ ์ญ์ ๊ฒ์ํด๊ฐ๋ฉฐ ๋ฐ์ ธ๋ณด์๋ค) - ์ค์ ์ฌํญ๋ค
- default value ์ด๊ธฐ๊ฐ ์ค์ ๊ฐ๋ฅ (ex. null, 0 )
- ํฑ๋๋ฐํด ๋๋ฌ์ ์นผ๋ผ๊ฐ์ array ๋ฐฐ์ด๋ก ํ ๊ฑด์ง, ๊ณ ์ ํ ๊ฐ์ผ๋ก ํ ๊ฑด์ง ๋ฑ ์ค์ ๊ฐ๋ฅ.
- primary key ๋ ์ฒดํฌํด์ ์ค์ ๊ฐ๋ฅ. (์ค๋ณต ๊ฐ๋ฅ)
์ด primary key ๊ฐ, ์ฌ๋ฌ ํ ์ด๋ธ ๊ฐ ์ฐ๊ฒฐ์ ์์ผ์ฃผ๋ foreign key (์ธ๋ํค)์ ์๊ด์ด ์๋ค!
์ฌ๋ฌ ํ ์ด๋ธ์ ์ฐ๊ฒฐ์์ผ์ฃผ๋ foreign keys (์ธ๋ํค)์ ๊ดํด์๋ ๋ค์์ ๊ธ์ ์ฐ๊ธฐ๋ก ํ๊ฒ ๋ค ..!
๊ทธ๋ฆฌ๊ณ ํ ์ด๋ธ์ ์์ฑํ๋ฉด ์ค๋ฅธ์ชฝ์ ๋จ๋ API Docs ๋ฅผ ๋๋ฅด๋ฉด ์น์ ํ๊ฒ ์ฌ์ฉ๋ฒ๋ ๋ค ๋์์์. ใ ใ
( + ์ฐธ๊ณ : ๊ทผ๋ฐ ์ด ๋ ์์ฑํ ๋ ๋ถํฐ ๋ ์๋์..ใ -ใ ์์๋ณด๋, CORS์๋ฌ๋ฅผ ์ ๋ฒ์ ์ ํด์ ๊ด๋ จ ํ์ฅํ๋ก๊ทธ๋จ์ ์ค์นํด์ ๋๋ฆฌ๊ณ ์์๋๋ฐ, ๊ทธ๊ฑฐ ๋๋ฌธ์ supabase์ patch request๋ฅผ ๋ฌดํจํํด์ ์๊ธด ๋ฌธ์ ์๋ ๊ฒ์ผ๋ก ๋ณด์๋ค. ๊ทธ๊ฑธ ๋๋๊น create table ์ฑ๊ณต!)
4 ) ๊ผญ! supabase ์์ฑํ ํ ์ด๋ธ์ ADD RLS policy ํด์ฃผ๊ธฐ!!!
๋ ์ด๊ฒ์ ์ํด์ค์ ๋์ค์ VSC์์ ์ฝ๋ ์ฐ๊ณ ๊ณ์ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค์ง ๋ชปํ์๋ค ... ใ ใ

์์ฑํ ํ ์ด๋ธ ์ฐฝ์์ Add RLS policy ํ๊ณ - New Policy - ๋ก ์๋ก์ด row ์์ค์ ๋ณด์์ ์ฑ ์ ์ถ๊ฐํด๋ณด์.
๋ณ๋์ ์ค์ ์ ํ ๊ฒ ์๋๋ผ๋ฉด Get started quickly -

Enable read access to everyone (This policy gives read access to your table for all users via the SELECT operation.)
(๋ฅผ ์ ํํ๋ฉด ๋ชจ๋๊ฐ ์ฝ์ ์ ์๋๋ก ๊ถํ์ ์ค์ ํ๋ ๊ฒ. ๋ฌผ๋ก ๋ค๋ฅธ ์ค์ ์ ์ ํํ ์๋ ์๋ค. authenticated ์ ์ ๋ง insert๋ฅผ ํ ์ ์๊ฒ ํ๋ค๋ ์ง..)
- Use this template ํด๋ฆญ
- Allowed operation ์ ๋ํด์๋ ALL๋ง ์ ํํ๊ณ Review - Save policy ๋ฒํผ ๋๋ฅด๊ธฐ!
5 ) supabase table editor์์ ํ ์ด๋ธ์ ๋ฐ์ดํฐ ์ง์ ๋ฃ์ด๋ณด๊ธฐ
ํ๋ฒ supabase์ฌ์ดํธ์์ ์ง์ ๋ฐ์ดํธ ๋ฃ์ด๋ณด๊ณ ์กฐํ๊ฐ ๋๋์ง ํ ์คํธ๋ฅผ ํด๋ณด์!
insert ๋ฒํผ -> insert row ํด์ฃผ๋ฉด ๋จ !
๋ํดํธ๊ฐ์ ์ค์ ํ๋ค๋ฉด ๊ฐ ์๋ฃ์ผ๋ฉด ์์์ ๋ํดํธ๊ฐ์ผ๋ก ์ค์ ๋จ.
์ดํ ์ง์ ํ ์ด๋ธํ์์์ ๊ฐ ์์ ์ ํด๋น ํ ์ด๋ธ ์นธ์ ๋๋ฌ์ฃผ๋ฉด ๋๋๋ฐ,
string - text,.. ๋ , number ๋ ๊ทธ๋ฅ ๋ฌธ์๋ง ์ซ์๋ง ๊ทธ๋๋ก ์จ์ฃผ๋ฉด ๋จ.
ํ์ง๋ง ๋ฌธ์string์ ๋ฐฐ์ด๊ณผ ๊ฐ์ ๊ฒฝ์ฐ, [" ", " "] ์ ๊ฐ์ ํํ๋ฅผ ์ง์ผ์ ์จ์ค์ผํ๋ค.


6 ) IDE : ์๋ฒ ์ปดํฌ๋ํธ์์ server.ts์ createClient ๋ถ๋ฌ์ ๋ฐ์ดํฐ ๋ค ๊ฐ์ ธ์ค๊ธฐ
์๊น ์ ๊ณต์๋ฌธ์๋๋ก ๊ทธ๋๋ก ํ๋ฉด ๋๋ค.
์๊น IDE -VS code ํฐ๋ฏธ๋๋ก next.js ํ์ ์์ฑํ๋ฉด์ supabase๋ ์ค์นํ๊ธฐ ๋๋ฌธ์,
utilsํด๋ - supabase ์์ server.ts๊ฐ ์์ฑ๋์ด์๋ค.
์ฌ๊ธฐ์๋ createClient ํจ์๋ฅผ ์ํ๋ ์๋ฒ์ปดํฌ๋ํธ์์ ๋ถ๋ฌ์์ 'supabase'์ ๊ฐ์ ๋ณ์์ ๋ด๊ณ ,
await supabase.from("ํ ์ด๋ธ๋ช ").select(); (ํน์ select('*') ๋ก ๋ชจ๋ ํ ์ด๋ธ ๋ด์ฉ ๋ถ๋ฌ์ค๊ธฐ)
ํ๋ฉด ๋์ !!
๐ก ์ถ๊ฐ : JS ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์๋ฒ / ํด๋ผ์ด์ธํธ ํ๊ฒฝ ๋ชจ๋์์ ์ฌ์ฉ๊ฐ๋ฅํ createClient ๋ฅผ ์ฌ์ฉํ๋ฉด ํธ๋ฆฌํ๋ค!
์ฐธ๊ณ : Supabase ๊ณต์๋ฌธ์ - javascript/installing
Installing | Supabase
_10
supabase.com
์์ 6๋ฒ ๊ณผ์ ์์,
๋ง์ฝ Javascript, (typescript) ๋ฅผ ์ด๋ค๋ฉด
@supabase/supabase-js ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ createClient ๋ฅผ import ํด์ ์ฐ๋ฉด ์๋ฒ/ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ๋ชจ๋์์ ์ธ ์ ์๋ค.
์ด๊ฑฐ ์ ๋ง ์์ ์ฅ์ ์ด๋ค !!!! ๐ถ
์ด๊ฑธ ๋ชจ๋ฅด๊ณ ;; ๊ทธ๋ฅ ์๋ฒ ์ปดํฌ๋ํธ์์๋ server.ts์ createClient ์ฐ๋ค๊ฐ,
ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์์๋ ๋จนํ์ง๋์๊ณ client.ts ๊ฑธ import ํด๋ ์๋ผ์.. ํํฐ๋๊ป ์ง๋ฌธํด๋ ์๋๊ณ . ์ง์ง ์ ๋จน์์๋ค....... ๐
๋ด ๊ฒฝ์ฐ ์๋ ์ฝ๋์ฒ๋ผ ๋ฐ๋ก createClientJs ๋ผ๊ณ ๊ทธ๋ฅ ๋ง๋ค๊ตฌ.. ๊ทธ๊ฑธ import ํด์ ํธ์ถํด์ ์ฐ๋๋ก ํ๋ค.
import { createClient } from '@supabase/supabase-js';
export const createClientJs = () =>
createClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!);
const supabase = createClientJs();
๋ค์ ๋ณธ๋ก ์ผ๋ก ๋์๊ฐ์, ์๋์ ๋ด๊ฐ ์ด ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์.
createClient ํจ์๋ฅผ ๋ณ์์ ๋ด๊ณ , -- const supabase = createClient();
์ด ๋ณ์๋ฅผ ํตํด from('ํ
์ด๋ธ').select(..) ๋ฅผ ํด์ค ๊ฒ. -- const { data, error } = await supabase.from('communityPosts').select('*');
๊ทธ๋ผ Supabase์ ํ ์ด๋ธ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ฌ ์ ์๊ฒ ๋๋ ๊ฒ !! ๐
// ์๋ฒ ์ปดํฌ๋ํธ
import { createClient } from '@/utils/supabase/server';
const CommunityDetailPage = async () => {
try {
const supabase = createClient();
const { data, error } = await supabase.from('communityPosts').select('*');
if (error) throw error
} catch (error) {
console.log(error);
}
return (
<div className="m-20">
<p>{data[0].userId}</p>
// ....
๊ทธ๋ฆฌ๊ณ ๊ฐ์ ธ์จ data ๊ฐ์ฒด์๋ ํ ์ด๋ธ ๋ฐ์ดํฐ๋ค์ด [{ }, { } ... ] ๋ฐฐ์ด ์์ ์ ๋ด๊ฒจ์์ผ๋,
data[0] ์ผ๋ก ์ฒซ๋ฒ์งธ ํ์ ๋ด์ฉ๋ค์ (ํ๋์ ๊ฐ์ฒด) ๊ฐ์ ธ์ฌ ์ ์๋ค.
๊ทธ๋์ ์ ์ฝ๋ return ๋ฌธ์์ ๋ณผ ์ ์๋ฏ, data[0].userId ์ ๊ฐ์ด ์จ์ค์ ์ํ๋ ๋ฐธ๋ฅ๊ฐ ํ๋๋ง ๊ฐ์ ธ์ฌ ์๋ ์๋ค.
๋ง์ฝ ํ ์ด๋ธ ์ ์ฒด ๋ฐ์ดํฐ- ๋ชจ๋ column์ด ์๋, ํน์ column ๋ค๋ง ๊ฐ์ ธ์ค๋ ค๋ฉด
let { data: communityPosts, error } = await supabase
.from('communityPosts')
.select('some_column,other_column')
select ('์นผ๋ผ๋ช ,์นผ๋ผ๋ช ') ์ฒ๋ผ ์์ ๊ฐ์ด ์จ์ฃผ๋ฉด๋๋ค.
๊ทธ ์ธ ๋ฐฉ๋ฒ๋ api docs ์ ์น์ ํ๊ฒ ๋์์์ผ๋ ์ฐธ๊ณ ํด๋ณด์!