v0로 만든 예쁜 화면에 Supabase 데이터베이스 연결하기
٦ مايو ٢٠٢٦
0
Computing/SoftwareRelated Video
6:33البدء مع v0: من الفكرة إلى الإنتاج
Vercel
Comments (0)
Log in to leave a comment
No posts yet
6:33Vercel
Log in to leave a comment
No posts yet
Vercel의 v0는 멋진 Next.js 화면을 순식간에 그려주지만, 거기서 끝내면 그냥 쓸모없는 껍데기일 뿐입니다. 새로고침을 누르는 순간 사용자가 입력한 데이터는 흔적도 없이 사라집니다. 진짜 작동하는 서비스를 만들려면 데이터를 저장할 데이터베이스가 필요합니다.
개발자를 고용해 수백만 원을 쓰지 않고도, 혼자서 v0의 가짜 데이터를 걷어내고 Supabase를 붙여 작동하는 백엔드를 완성하는 단계를 정리했습니다.
v0가 만든 코드 안에는 보통 const mockData = [...] 형태의 가짜 데이터가 들어있습니다. 이 데이터의 구조를 파악하는 일이 첫 단추입니다. 화면에서 보여주는 정보와 사용자가 입력하는 필드를 그대로 데이터베이스 테이블로 옮겨야 합니다.
데이터 구조가 꼬여서 엉뚱한 값이 저장되는 일을 막으려면 데이터 타입을 명확히 정의해야 합니다. SQL을 몰라도 다음 다섯 가지 규칙만 알면 테이블을 설계할 수 있습니다.
uuid 타입을 사용하고 기본값으로 gen_random_uuid()를 설정해 자동으로 고유한 문자열이 생성되도록 만듭니다.text 타입을 지정하고, 중복 가입을 막기 위해 UNIQUE와 빈 값이 들어올 수 없도록 NOT NULL 설정을 켭니다.numeric 타입을 할당합니다.text 타입을 사용하되, 대기나 완료 같은 지정된 값만 들어오도록 제한합니다.timestamptz 타입을 지정하고, 데이터가 들어오는 시점의 시간이 입력되도록 기본값에 now()를 넣습니다.Supabase는 복잡한 서버 인프라 구축 없이 웹 브라우저에서 마우스 클릭 몇 번으로 데이터베이스를 만들 수 있게 돕습니다.
messages나 users로 정한 뒤, 위 매핑 기준에 맞춰 필요한 컬럼을 추가합니다.데이터베이스를 만들었다면 내 Next.js 프로젝트 폴더와 Supabase가 통신할 수 있는 길을 열어야 합니다. 이때 데이터베이스 관리자 비밀키가 깃허브 같은 공공장소에 유출되면 서비스 전체가 통제 불능 상태에 빠집니다. 환경 변수를 분리해 보관해야 하는 이유입니다.
Next.js 프로젝트의 루트 폴더에 .env.local 파일을 만들고 아래 코드를 입력합니다. 주소와 키 값은 Supabase 대시보드의 Settings > API 페이지에서 복사해 옵니다.
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key
브라우저가 접근해야 하는 변수에는 NEXT_PUBLIC_ 접두사를 붙입니다. RLS 권한을 무시하고 데이터를 강제로 수정할 수 있는 SUPABASE_SERVICE_ROLE_KEY에는 절대로 접두사를 붙이면 안 됩니다. 이 키는 오직 서버 환경에서만 작동하도록 숨겨두어야 보안 사고를 막을 수 있습니다.
프로젝트가 커질 때마다 데이터베이스 연결 객체를 중복해서 생성하면 연결 개수 초과 에러가 발생합니다. 프로젝트 전체에서 하나의 연결 인스턴스만 공유해 쓰도록 싱글톤 파일을 만듭니다.
lib 폴더를 만들고 supabase.ts 파일을 생성합니다.import { createClient } from '@supabase/supabase-js'
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
이제 데이터를 다룰 v0 컴포넌트 파일 맨 위에 import { supabase } from '@/lib/supabase'를 적어주면 데이터베이스와 통신할 준비가 끝납니다.
기존 웹 개발은 프론트엔드 데이터를 받아서 DB에 넘겨주는 백엔드 API API 엔드포인트(/api/save-data)를 따로 만들고 fetch 요청을 길게 작성해야 했습니다. Next.js의 Server Action을 사용하면 이런 번거로운 과정 없이 자바스크립트 함수 호출 한 번으로 데이터를 안전하게 서버로 보내 저장할 수 있습니다.
사용자가 입력 폼에 텍스트를 쓰고 전송 버튼을 누르면 DB에 즉시 저장되는 기능입니다.
app/actions.ts 파일을 만들고 맨 위에 'use server'라고 적습니다. 이 파일 안에 작성하는 함수는 브라우저가 아닌 보안이 유지되는 서버 컴퓨터 환경에서만 실행됩니다.'use server'
import { supabase } from '@/lib/supabase'
import { revalidatePath } from 'next/cache'
export async function submitForm(formData: FormData) {
const email = formData.get('email') as string
const message = formData.get('message') as string
const { error } = await supabase
.from('messages')
.insert([{ user_email: email, content: message }])
if (!error) {
revalidatePath('/')
}
}
<form> 태그를 <form action={submitForm}>으로 고쳐 함수를 연결합니다. 이제 사용자가 전송 버튼을 누르면 입력한 이메일과 메시지가 Supabase 테이블에 담깁니다.데이터가 서버에 잘 저장되어도 Next.js의 캐싱 기능 때문에 사용자 화면에는 바로 나타나지 않는 현상이 생깁니다. 사용자가 브라우저를 수동으로 새로고침하지 않아도 바뀐 데이터가 화면에 바로 나타나게 만드는 방법이 필요합니다.
데이터가 정상적으로 저장된 직후에 클라이언트 컴포넌트에서 useRouter 훅을 사용해 router.refresh()를 실행하도록 구성합니다. 화면 전체가 깜빡거리며 새로고침되는 불쾌한 경험 없이, 새로 추가된 데이터 영역만 부드럽게 화면에 동기화되는 앱 같은 사용성을 얻을 수 있습니다.
개발 컴퓨터(localhost)에서 잘 작동하던 기능이 Vercel에 배포하자마자 먹통이 되는 일은 흔합니다. 원인은 단순합니다. 배포된 서버가 우리가 비밀리에 적어둔 .env.local 파일의 존재를 모르기 때문입니다.
Vercel 대시보드에 접속해 프로젝트를 선택한 뒤 Settings > Environment Variables 메뉴로 들어갑니다.
로컬 환경에서 작성했던 환경 변수 이름과 값을 그대로 입력창에 넣고 추가합니다. Production, Preview, Development 모든 환경에 적용되도록 체크한 뒤 저장합니다. 설정을 마친 후 프로젝트를 다시 배포(Redeploy)해야 원격 서버가 새 환경 변수를 정상적으로 읽어 들입니다.
실제 배포된 도메인으로 접속해 다음 세 가지가 정상 작동하는지 확인해야 합니다.
| 확인 항목 | 테스트 방법 | 예상 결과 |
|---|---|---|
| 데이터 입력 및 저장 | 배포된 페이지에서 테스트 이메일로 폼을 제출합니다. | Supabase 대시보드의 Table Editor 뷰에 방금 입력한 값이 실시간으로 쌓여야 합니다. |
| API 통신 에러 검사 | 브라우저에서 F12 키를 눌러 개발자 도구의 Console 탭을 엽니다. | 데이터 전송 시 빨간색 글씨로 401 Unauthorized 에러가 뜨지 않는지 확인합니다. 에러 발생 시 Supabase의 RLS 정책을 재확인해야 합니다. |
| Vercel 실시간 로그 | Vercel 대시보드의 Deployments > Logs 메뉴를 켭니다. | 사용자가 폼을 전송할 때 백엔드 서버에서 환경 변수 누락으로 인한 Null Pointer 예외나 DB 연결 에러가 기록되지 않는지 모니터링합니다. |