supabase insert 안됨 문제 해결 가이드와 실무 적용법
supabase insert 안됨 문제를 진단하고 실무에서 바로 적용할 수 있는 해결법을 정리합니다. 권한·RLS·스키마·클라이언트 이슈별 체크리스트와 코드 예제를 포함합니다. 실무 적용 흐름과 자주 하는 실수까지 함께 확인할 수 있습니다.
supabase insert 안됨이 필요한 상황
supabase insert 안됨 현상은 개발 중에 가장 빈번하게 마주치는 문제입니다. 이 글에서는 왜 insert가 실패하는지 개념을 이해하고, 실무에서 바로 적용 가능한 진단 흐름, 코드 예시, 권한·RLS·스키마 문제를 해결하는 방법을 제공합니다. 목적은 원인 분류와 우선순위 있는 해결 절차를 통해 빠르게 복구하는 것입니다.
supabase insert 안됨 핵심 개념
Supabase는 Postgres 위에서 동작하며 클라이언트 라이브러리(supabase-js)를 통해 insert 요청을 보냅니다. insert가 실패하는 전형적인 원인은 다음과 같습니다.
- 클라이언트 인증(ANON 키/서비스 키) 또는 세션 문제
- Row Level Security(RLS) 정책으로 인한 권한 거부
- 필드 타입/NOT NULL/제약조건 위반
- 외래키 제약으로 인한 무결성 오류
- 네트워크 또는 CORS 문제
먼저 서버로부터 반환되는 에러 메시지(status, message)를 확인하면 대부분 원인 식별이 가능합니다. 개발자는 supabase-js의 응답 객체({ data, error })를 반드시 검사해야 합니다.
supabase insert 안됨 실무 예제
다음은 supabase-js를 사용하는 간단한 insert 코드입니다. 에러를 로깅하고 조건별로 분기하는 방식으로 작성하세요.
// language: javascript import { createClient } from '@supabase/supabase-js' const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY) async function insertUser(user) { const { data, error } = await supabase .from('users') .insert(user) .select() // 반환값이 필요하면 select() 호출 if (error) { console.error('Insert error:', error) // 에러 타입별 대응 return { success: false, error } } return { success: true, data } } // 사용 예 insertUser({ email: 'test@example.com', name: 'Test' }) .then(res => console.log(res))
응답에서 error가 있으면 error.message, error.details, error.hint 등을 확인하세요. 서버 로그(만약 사용 가능한 경우)를 함께 보면 원인 파악이 빠릅니다.
권한, RLS와 관련된 문제 진단 (sub_keyword: row level security 설정)
RLS가 활성화되면 클라이언트 세션의 claim(예: user_id)과 정책이 일치하지 않으면 insert가 거부됩니다. RLS 문제를 진단하려면:
- supabase SQL 에디터에서 해당 테이블의 RLS 설정 확인
- 정책(policy)에서 사용되는 claim 키(예: auth.uid())와 클라이언트에서 전달되는 세션 정보 비교
- 관리자(서비스 롤)로 insert가 가능한지 테스트
예: RLS가 활성화된 users 테이블에 대한 정책이 auth.uid()로만 허용하면 익명 키로는 insert 불가합니다.
스키마·제약조건 문제 (sub_keyword: 필드 타입/제약조건)
insert 실패는 자주 타입 불일치, NOT NULL 제약, UNIQUE 제약에 의해 발생합니다. 다음 표는 원인별 판단 기준 예시입니다.
| 구분 | 항목1 | 항목2 | 항목3 |
|---|---|---|---|
| 내용 | 에러 메시지 확인 | 테이블 DDL 확인 | 예시 해결책 |
- 에러 메시지: "null value in column "x" violates not-null constraint"
- 테이블 DDL: NOT NULL 필드 또는 DEFAULT 값 확인
- 해결책: 클라이언트에서 필수 필드 제공 또는 DEFAULT 지정
업서트 vs insert: 언제 어떤 방식을 쓸까 (sub_keyword: 업서트(upsert) vs insert)
- insert: 새로운 레코드를 추가할 때 사용
- upsert: 충돌(예: UNIQUE 제약) 시 업데이트를 원할 때 사용
간단한 upsert 사용 예시:
await supabase .from('profiles') .upsert({ id: 'user-id', name: 'New Name' }, { onConflict: 'id' })
네트워크·클라이언트 설정 점검 (sub_keyword: supabase client 사용법)
- SUPABASE_URL과 키가 올바른지 확인
- 브라우저 콘솔의 네트워크 탭에서 request/response 확인
- CORS 에러는 프론트에서 발생하며 서버 설정으로 해결
실무 체크리스트
- supabase 응답에서 error 객체 확인하기
- 서버 로그(가능하면)와 에러 메시지 비교하기
- RLS 활성화 여부 확인 및 정책 검토하기
- 클라이언트에서 보내는 데이터와 테이블 DDL 비교하기
- 키(ANON vs SERVICE ROLE) 사용 적절성 검토하기
- 필요한 경우 upsert로 충돌 처리 고려하기
성능·보안·운영 주의점
- 성능: 대량 insert는 트랜잭션·배치 처리(batch insert)로 묶어 전송하세요. 동시에 많은 요청은 DB 부하를 유발합니다.
- 보안: 클라이언트에서 절대 SERVICE_ROLE 키를 사용하지 마세요. 서비스 키는 서버 전용입니다.
- 운영: RLS 정책 변경은 즉시 권한 영향이 크므로 스테이징에서 검증 후 배포하세요. 마이그레이션 시 기존 데이터와 정책 충돌을 점검하세요.
언제 쓰면 좋은가
- 클라이언트에서 간단한 CRUD로 사용자 데이터를 추가/갱신할 때
- 빠른 프로토타이핑 및 서버리스 백엔드가 필요할 때
언제 피해야 하는가
- 복잡한 트랜잭션이나 높은 일관성(복수 테이블 교차 업데이트)이 필요한 경우
- 대량 데이터 마이그레이션이나 정교한 권한 모델이 필수인 경우
비교표: insert 실패 원인별 판단 기준
| 구분 | 항목1 | 항목2 | 항목3 |
|---|---|---|---|
| 내용 | 인증/키 문제 | RLS/정책 | 제약조건/타입 |
- 인증 문제일 경우: 401/403 응답 및 anon/service 키 확인
- RLS 문제일 경우: 정책 확인 및 관리자 권한 테스트
- 제약조건 문제일 경우: 에러 메시지 및 DDL 비교
자주 묻는 질문
Q: supabase insert 안됨 에러에서 가장 먼저 확인할 것은?
A: 응답의 error 객체와 HTTP 상태, 그리고 RLS 활성화 여부를 먼저 확인하세요. 에러 메시지가 원인 단서를 줍니다.
Q: RLS가 활성화된 테이블에 익명 키로도 insert가 가능한가요?
A: 대부분 정책에 따라 다릅니다. 익명(anon) 키는 제한적 권한만 가집니다. 정책이 auth.uid()를 요구하면 세션 기반 사용자가 아니면 실패합니다.
Q: 클라이언트에서 어떤 키를 써야 하나요?
A: 브라우저/클라이언트에서는 ANON 키, 서버 측 안전한 환경에서는 SERVICE_ROLE 키(단 서버에서만 사용)를 사용하세요. SERVICE_ROLE을 클라이언트에 노출하면 안 됩니다.
Q: 에러 로그에 hint가 없을 때 어떻게 진단하나요?
A: SQL 에디터에서 직접 동일한 INSERT 쿼리를 실행해 보고 Postgres가 반환하는 상세 에러를 확인하세요. 또한 네트워크 요청/응답을 캡처해 비교하세요.
정리
- supabase insert 안됨 문제는 인증·RLS·제약조건·클라이언트 설정을 순차적으로 점검하면 대부분 해결됩니다.
- 에러 객체와 서버 로그를 우선 확인하고, RLS 정책을 검토하세요.
- 배치 insert와 upsert를 상황에 맞게 사용하고, 서비스 키는 클라이언트에 노출하지 마세요.
- 실무 체크리스트를 통해 재현 단계와 원인 분류를 일관되게 적용하세요.