← 블로그 목록

Supabase 데이터 저장 안됨: 바이브코딩 프로젝트 점검 순서

Cursor, Lovable, Bolt로 만든 서비스에서 Supabase 연결은 된 것 같은데 데이터가 저장되지 않을 때 테이블, RLS, 환경 변수, 요청 값을 확인하는 순서를 정리했습니다.

Supabase는 바이브코딩 프로젝트에서 정말 자주 쓰입니다. 로그인, 데이터베이스, 파일 저장까지 한 번에 붙일 수 있어서 Lovable이나 Bolt로 만든 앱에도 많이 들어갑니다.

문제는 "연결된 것처럼 보이는데 저장은 안 되는" 순간입니다. 화면에서는 저장 완료라고 나오는데 테이블에는 데이터가 없거나, 로컬에서는 되는데 배포 후에는 조용히 실패하거나, 어떤 사용자는 되고 어떤 사용자는 안 됩니다.

이럴 때 바로 AI에게 "고쳐줘"를 반복하면 코드가 더 산만해질 수 있습니다. Supabase 저장 문제는 보통 코드 한 줄보다 설정, 권한, 데이터 모양이 함께 얽혀 있습니다.

먼저 실패가 보이는 곳을 나누기

데이터 저장 문제는 크게 세 군데로 나눠서 봐야 합니다.

  1. 화면에서 입력값이 제대로 만들어지는가
  2. Supabase로 요청이 실제로 보내지는가
  3. Supabase가 그 요청을 허용하고 저장하는가

비개발자 입장에서는 모두 "저장이 안 된다"로 보이지만, 개발자는 이 셋을 다르게 봅니다. 입력값이 비어 있으면 화면 문제이고, 요청이 안 나가면 코드 흐름 문제이고, 요청은 갔는데 거절되면 권한이나 테이블 설정 문제입니다.

이 구분만 해도 AI에게 훨씬 정확하게 물어볼 수 있습니다.

1. 테이블 이름과 컬럼 이름 확인하기

가장 단순하지만 가장 자주 나오는 문제입니다. AI가 코드에서는 orders 테이블에 저장한다고 만들어놨는데, Supabase에는 order 테이블만 있거나, 컬럼 이름이 userName과 user_name처럼 다를 수 있습니다.

Supabase는 테이블과 컬럼 이름이 정확히 맞아야 합니다. 화면에서는 별다른 에러가 보이지 않아도 브라우저 콘솔이나 네트워크 탭에는 실패 메시지가 남아 있을 수 있습니다.

확인할 것:

  • 코드의 테이블 이름과 Supabase 테이블 이름이 같은가
  • 저장하려는 컬럼이 실제로 존재하는가
  • 필수 컬럼에 값이 들어가는가
  • 숫자, 날짜, boolean 같은 타입이 맞는가

AI가 기능을 여러 번 고치다 보면 예전 테이블 이름이 코드에 남아 있는 경우도 많습니다.

2. RLS 때문에 막히는지 보기

Supabase에서 데이터 저장이 안 될 때 자주 나오는 단어가 RLS입니다. Row Level Security, 즉 행 단위 보안 설정입니다.

RLS가 켜져 있으면, 테이블이 있어도 아무나 데이터를 읽고 쓰지 못합니다. 어떤 사용자가 어떤 조건에서 insert, select, update를 할 수 있는지 정책이 있어야 합니다.

바이브코딩 프로젝트에서는 여기서 많이 막힙니다. AI는 화면과 저장 코드를 만들었지만, Supabase 정책까지 정확히 맞춰주지 못하는 경우가 있습니다. 특히 로그인 사용자만 저장해야 하는지, 익명 사용자도 문의를 남길 수 있는지 같은 조건이 분명하지 않으면 더 그렇습니다.

증상은 보통 이렇습니다.

  • 로그인하지 않으면 저장이 안 된다
  • 내 데이터는 보이는데 다른 사용자의 데이터는 안 보인다
  • 저장 요청이 401, 403 또는 policy 관련 에러로 실패한다
  • Lovable 미리보기에서는 됐는데 운영에서는 안 된다

RLS는 보안을 위해 필요한 장치입니다. 무작정 끄기보다, 서비스 흐름에 맞게 정책을 잡는 편이 안전합니다.

3. 환경 변수가 배포에도 있는지 확인하기

로컬에서는 저장되는데 Vercel 배포 후에는 안 된다면 환경 변수를 먼저 봐야 합니다.

Supabase 프로젝트 URL과 anon key는 로컬 .env에만 있으면 배포 환경에서는 사용할 수 없습니다. Vercel, Netlify 같은 배포 서비스의 Environment Variables에 같은 값이 등록되어 있어야 합니다.

확인할 것:

  • Supabase URL이 배포 서비스에 등록되어 있는가
  • anon key가 빠지지 않았는가
  • 변수 이름이 코드에서 읽는 이름과 정확히 같은가
  • NEXT_PUBLIC_ 접두사가 필요한 값에 붙어 있는가
  • 환경 변수 수정 후 다시 배포했는가

환경 변수 이름 하나가 다르면, 화면에서는 그냥 "저장 실패"처럼만 보일 수 있습니다.

4. 요청 값이 비어 있지 않은지 보기

AI가 만든 폼에서는 버튼을 눌렀을 때 입력값이 제대로 모이지 않는 경우도 있습니다. 화면에는 이름과 이메일을 쓴 것처럼 보이지만, 실제 저장 요청에는 빈 문자열이나 undefined가 들어갈 수 있습니다.

이 문제는 특히 폼 컴포넌트를 여러 번 수정했거나, 입력창 이름을 바꿨거나, 상태 관리 코드를 AI가 다시 만든 뒤에 잘 생깁니다.

비개발자도 확인할 수 있는 방법은 있습니다. 저장 버튼을 누른 뒤 브라우저 개발자 도구의 Network 탭을 보면 어떤 값이 서버나 Supabase로 보내졌는지 볼 수 있습니다. 어렵다면 AI에게 "저장 직전에 payload를 console.log로 확인하게 해줘"라고 요청해도 됩니다.

다만 운영 서비스에서는 콘솔 로그에 개인정보가 남지 않게 주의해야 합니다. 확인 후에는 제거하는 것이 좋습니다.

5. 저장은 됐는데 화면이 안 바뀌는 경우

가끔은 데이터가 실제로 저장됐는데 화면만 그대로인 경우도 있습니다. 이때는 Supabase 문제가 아니라 화면 갱신 문제입니다.

예를 들어 문의를 저장한 뒤 목록을 다시 불러오지 않거나, 캐시된 데이터를 계속 보여주거나, 저장 성공 후 이동할 페이지가 잘못되어 있을 수 있습니다.

이 경우에는 Supabase 테이블을 직접 열어보면 데이터가 들어와 있습니다. 데이터가 있다면 저장 로직이 아니라 화면 표시 로직을 봐야 합니다.

AI에게 물어볼 때도 "저장이 안 된다"가 아니라 "Supabase에는 저장되는데 화면 목록이 갱신되지 않는다"라고 말해야 합니다. 이 한 문장 차이로 수정 방향이 완전히 달라집니다.

정리

Supabase 데이터 저장이 안 될 때는 아래 순서로 확인하세요.

  1. 테이블 이름과 컬럼 이름이 맞는지
  2. 필수 값과 데이터 타입이 맞는지
  3. RLS 정책이 insert를 허용하는지
  4. 배포 환경 변수에 Supabase 값이 들어 있는지
  5. 저장 요청의 payload가 비어 있지 않은지
  6. 실제로는 저장됐지만 화면만 갱신되지 않는 것은 아닌지

Supabase는 좋은 도구지만, 데이터베이스와 권한이 들어가는 순간부터는 단순 UI 수정과 다릅니다. 같은 저장 오류를 AI가 여러 번 고치지 못한다면, 코드보다 테이블과 정책을 함께 봐야 할 가능성이 큽니다.

관련 글: AI로 만든 서비스 유지보수 맡기기 전 확인할 것, Cursor가 같은 에러를 반복할 때

AI·바이브코딩으로 해결되지 않는 개발 이슈, 먼저 원인부터 확인하세요

Cursor 에러, Vercel·Next.js 배포 실패, 결제·예약 연동 오류, 소규모 기능 개발을 단건 중심으로 진단합니다. 월 구독 파트너는 정식 상품을 준비 중입니다.