대니
danny's blog@dannywon_dev
발행 94 · 대기 164

1인 개발자. 클로드 코드를 팀처럼 굴린다. 매일 겪은 것만 쓴다.

버그와 함정

supabase db push 400 — 옆 프로젝트에선 그냥 됐다

CLI 가 400 으로 죽어 20KB SQL 을 만들었다. 범위를 잘못 잰 탓이었고, 답은 .env 한 줄이었다.

마이그레이션을 올리려던 것뿐이다. 평범한 명령이다.

supabase db push --linked

접속도 못 해보고 죽었다.

Initialising login role...
POST /v1/projects/<ref>/cli/login-role → 400
  permission denied to alter role
  Only roles with the CREATEROLE attribute and the ADMIN option on role
  "cli_login_postgres" may alter this role.

CLI 는 원격 DB 에 붙기 전에 임시 역할(cli_login_postgres)을 하나 만든다. 그걸 만드는 API 가 서버 쪽에서 거부당했다. 내가 고칠 수 있는 자리가 아니다.

다섯 번 시도하고 CLI 를 버렸다

2026-08-12 세션에서 이것저것 해봤다.

  • db push 말고 db query · migration up · migration list전부 같은 자리에서 죽는다
  • CLI 버전을 2.113 → 2.109 → 2.99 → 2.88 → 2.75 로 내려봤다 — 똑같거나, 더 옛 버전은 --linked 옵션 자체가 없었다
  • --experimental 플래그, 프로젝트 재연결 — 변화 없음

그래서 결론이 났다. "CLI 로는 안 된다. 대시보드 SQL 편집기에 붙여넣자." 스키마 전체를 한 장으로 합친 20KB짜리 SQL 파일을 만들고, 여러 번 돌려도 안전하게 if not exists 를 다 붙이고, 마이그레이션 이력에 넣는 줄까지 달아서 클립보드에 복사해 뒀다.

복사까지 끝난 걸 보다가 물었다.

"너가 마이그레이션 만들어서 CLI로 배포하면 되잖아?"

다섯 번 해도 표본은 하나였다

틀린 건 "막혔다"가 아니라 "얼마나 막혔냐" 였다.

한 프로젝트에서 한 명령이 죽는 걸 보고 "CLI 가 안 된다" 로 넓혔다. 다섯 가지를 시도했으니 충분히 확인했다고 느꼈는데, 다섯 개가 전부 같은 프로젝트·같은 계정·같은 경로였다. 비교군이 하나도 없었다.

옆 프로젝트에서 똑같은 명령을 돌려봤다. 명령 한 줄, 3초.

current_user: postgres
version: PostgreSQL 17.6

그냥 됐다.

Postgres 만든 날 결과
잘 되는 프로젝트 17.6 2026-04
막힌 프로젝트 17.4 2025-09 ❌ 400

이 순간 문제 이름이 바뀐다. "CLI 가 안 된다"가 아니라 "옛 프로젝트 하나가 이 경로를 못 쓴다" 다. 그러면 다음 질문도 바뀐다 — "CLI 를 포기할 방법" 이 아니라 "이 경로를 안 지나는 방법" 이다.

CLI 바이너리 안을 뒤졌더니 비번을 찾는 순서가 그대로 있었다.

--password 플래그  →  환경변수 SUPABASE_DB_PASSWORD  →  .env 파일  →  빈 값

환경변수가 있으면 임시 역할을 아예 안 만든다. 가짜 비번을 넣고 확인해 보니 죽던 그 단계를 지나쳐서 password authentication failed 까지 갔다. 경로가 열려 있었다는 뜻이다.

바꾼 건 .env 한 줄

SUPABASE_DB_PASSWORD=<대시보드의 Database password>

그걸로 끝이었다. 20KB짜리 SQL 파일은 버렸고, 12개 테이블은 supabase db push 로 평범하게 올라갔다.

곁다리로 두 가지가 더 갈렸다.

하나 — 키체인이 담고 있는 건 DB 비번이 아니었다. CLI 를 돌릴 때 맥이 키체인 접근을 묻는 게 DB 비번 때문인 줄 알았는데, 바이너리를 열어보니 저장 항목 이름이 이거였다.

서비스 = "Supabase CLI"   ·   계정 = "access-token"

로그인 토큰이다. DB 비번은 키체인을 아예 안 본다. 덤으로 "npx supabase 는 왜 매번 물어보나" 도 풀렸다 — npx 는 버전마다 설치 경로가 달라서 키체인이 매번 다른 앱으로 본다. 경로가 고정된 전역 설치를 쓰면 안 묻는다.

둘 — CLI 는 .env.local 을 안 읽는다. .envsupabase/.env 만 읽는다. 둘 다 가짜 값으로 직접 확인했다. 앱(Next.js)이 읽는 파일과 CLI 가 읽는 파일이 다르다는 걸 모르면, 비번을 넣어놓고도 계속 같은 에러를 보게 된다.

남은 건 순서 하나

"안 된다" 고 말하기 전에 같은 명령을 옆 프로젝트에서 한 번 돌려본다. 3초짜리다.

시도를 몇 번 했느냐는 근거가 안 된다. 다섯 번을 해도 전부 같은 환경이면 표본은 하나다. 비교군 하나가 「내 문제」와 「저 환경 문제」를 가르고, 그 둘은 처방이 완전히 다르다. 앞쪽은 우회로를 찾아야 하고, 뒤쪽은 그 환경만 피하면 된다.

← 목록으로