
Supabase를 Mumbai에서 Tokyo로 이전하여 DB 레이턴시를 1/3로 줄인 이야기 (삽질 포인트 전부 공개)
요약
Supabase 프로젝트의 리전을 Mumbai에서 Tokyo로 이전하여 DB 레이턴시를 1/3로 단축한 경험담입니다. 리전 변경이 불가능하여 새 프로젝트를 생성해야 하는 과정과 환경 변수 설정 및 신규 API 키 형식 적용 시 주의할 점을 다룹니다.
핵심 포인트
- Supabase는 기존 프로젝트의 리전 변경이 불가능하여 새 프로젝트 생성이 필요함
- 리전 이전을 통해 DB 레이턴시를 약 1/3 수준으로 대폭 개선 가능
- 환경 변수 설정 시 대시보드 URL이 아닌 실제 Project URL을 사용해야 함
- 신규 프로젝트는 변경된 API 키 형식(sb_publishable_/sb_secret_)을 권장함
서론
개인 개발 중인 일본 주식 분석 서비스 「주식 AI 분석」을 운영하고 있는 21세 대학생입니다.
서비스 공개 후 프로파일링을 해보니, **Supabase의 리전(Region)이 Mumbai (인도)**로 설정되어 있다는 것을 깨달았습니다.
일본 사용자 대상 서비스인데, API → DB 왕복 과정에서 매번 130-150ms가 추가로 소요되는 상태였습니다.
Tokyo 리전으로 이전했더니 DB 레이턴시(Latency)가 약 1/3로 개선되었습니다. 본 기사에서는 그 이전 절차와, 은근히 여러 번 막혔던 삽질 포인트(ハマりポイント)를 전부 공개합니다.
이전 계기
어느 날 Supabase 대시보드에서 자신의 프로젝트 리전을 확인해보니:
Region: ap-south-1 (Mumbai)
…언제 선택했는지 기억이 나지 않습니다 (프로젝트 생성 시 기본값으로 선택되었거나, 아무거나 눌렀던 것 같습니다).
일본 사용자로부터 API 요청 → Render origin (미국 또는 싱가포르) → Supabase Mumbai → DB → ... 와 같이, 지구를 반 바퀴 돌고 있는 상태였습니다.
레이턴시 참고치:
| 경로 | RTT |
|---|---|
| 일본 ↔ Tokyo | 5-10ms |
| ... |
포트폴리오 화면 등 여러 쿼리를 호출하는 화면에서 체감되는 느림. 사용자가 0명인 지금이 최적의 타이밍이기에 즉시 이전을 결정했습니다.
이전 절차 (개요)
Supabase는 기존 프로젝트의 리전 변경이 불가능하므로, 새 프로젝트를 만들어 수동으로 전환해야 합니다.
1. Tokyo 리전에서 새 프로젝트 생성
2. 스키마 (schema.sql) 적용
3. RLS 정책 적용
...
사용자가 0명이었기 때문에 데이터 이전은 스킵하고 빈 DB로 전환하기만 하면 되었습니다. 이 점이 편리했습니다.
삽질 포인트 전부 공개
1. NEXT_PUBLIC_SUPABASE_URL에 대시보드 URL을 붙여넣는 실수
- Supabase 새 프로젝트 생성 후, API 키 화면을 연 브라우저의 URL이 다음과 같습니다:
https://supabase.com/dashboard/project/fpxwajrdiwsvyyhcoook/settings/api
이것을 Project URL이라고 생각하고 Render의 env(환경 변수)에 붙여넣었습니다. 당연히 API 호출이 모두 실패했습니다.
정답은 이것입니다:
https://fpxwajrdiwsvyyhcoook.supabase.co
대시보드 URL에서 프로젝트 ref (fpxwajrdiwsvyyhcoook)를 추출하여 .supabase.co를 붙이거나, Project Settings → API → Project URL의 값을 복사해야 합니다.
이는 개인 개발자라면 한 번쯤 겪을 수 있는 함정이니 주의하십시오.
2. API 키가 신규 형식 (sb_publishable_/sb_secret_)으로 변경됨
신규 프로젝트의 「Project Settings → API Keys」를 열면, 두 개의 탭이 있습니다:
Publishable and secret API keys← 신규 형식 (기본값)Legacy anon, service_role API keys← JWT 형식 (구형)
처음에는 구 프로젝트와 마찬가지로 JWT 형식 (eyJ...)을 사용하려고 Legacy 탭에서 복사했더니, 설정이 미묘하게 어긋나 「Invalid API key」 에러가 연발되었습니다.
신규 프로젝트는 신규 형식을 사용하는 것이 무난합니다:
NEXT_PUBLIC_SUPABASE_ANON_KEY=sb_publishable_JdYJJ...
SUPABASE_SERVICE_ROLE_KEY=sb_secret_8CxSv...
둘 다 📋 버튼으로 복사하십시오. 수동으로 선택하면 줄바꿈이나 공백이 포함될 원인이 됩니다.
JWT 키가 올바른지 진단하는 원라이너 (One-liner)
브라우저 Console에서:
JSON.parse(atob("PASTE_KEY_HERE".split('.')[1]))
→ { ref: "<project-ref>", role: "service_role", ... }
와 같은 내용이 나옵니다.
ref가 프로젝트와 일치하는지role이service_role인지anon인지
를 확인할 수 있습니다.
3. 「Automatically expose new tables」를 OFF로 설정하면 발생하는 permission denied 지옥
새 프로젝트 생성 시, 보안 설정에서:
| 항목 | 권장 |
|---|---|
| Enable Data API | ON |
| Automatically expose new tables | OFF |
| Enable automatic RLS | ON |
「Automatically expose new tables」를 OFF로 설정하면 확실히 안전하지만, 신규 테이블에 대한 GRANT가 자동으로 부여되지 않는다.
그대로 INSERT INTO watchlist ...를 실행하면:
DB error: {
code: '42501',
message: 'permission denied for table watchlist',
...
정공법을 통한 해결 SQL:
-- service_role (백엔드 API 역할) に 전권한 부여
GRANT ALL ON ALL TABLES IN SCHEMA public TO service_role;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO service_role;
...
RLS (Row Level Security)가 모든 테이블에 활성화되어 있으므로, authenticated/anon에 GRANT를 넓게 설정하더라도 행 레벨(row level)에서 차단되기 때문에 안전하다.
권한 확인 SQL
SELECT grantee, privilege_type
FROM information_schema.table_privileges
WHERE table_schema = 'public'
...
INSERT/SELECT/UPDATE/DELETE 4가지가 갖춰져 있으면 OK.
4. Confirm signup 템플릿이 OTP 코드를 내보내지 않는 문제
이전 프로젝트에서는 Magic Link 또는 OTP 템플릿을 수정하여 8자리 숫자 코드로 설정했었지만, 신규 계정의 첫 사인업(Sign up) 시에는 Confirm signup 템플릿이 사용된다.
이 부분을 수정하는 것을 잊었기 때문에, 첫 로그인 시 사용자에게 "링크를 클릭하세요"라는 메일이 발송되어 예상과 다른 동작을 했다.
→ Magic Link 템플릿과 Confirm signup 템플릿 모두에서 {{ .ConfirmationURL }}을 {{ .Token }}으로 교체해야 한다.
<!-- Confirm signup의 Body -->
<div style="...">
<h2 style="...">주식 AI 분석 사인업 확인</h2>
...
이렇게 하면 Apple Mail의 프리페치(prefetch) 문제도 회피할 수 있다 (링크가 없으므로 소비되지 않음).
이전 후의 효과
| API | 이전 전 (Mumbai) | 이전 후 (Tokyo) | 개선 |
|---|---|---|---|
/api/watchlist (GET) | 380ms | 130ms | 3배 속도 |
/api/portfolio (GET) | 520ms | 200ms | 2.5배 속도 |
| 인증 (signInWithOtp) | 1.6s | 0.7s | 2배 속도 |
/api/trending (DB 캐시 Hit) | 600ms | 230ms | 2.5배 속도 |
체감도 확실히 다르다. "리스트 계열의 화면이 순식간에 뜨는" 느낌으로 바뀌었다.
특히 여러 쿼리를 호출하는 /portfolio나 /journal에서 효과가 크다.
요약
- 리전(Region)은 초기 선택 시 주의할 것. 기본값에 맡기면 지구 반대편에 배치된다.
- Supabase는 기존 프로젝트의 리전 변경이 불가능하다. 새 프로젝트를 만들어 이전해야 한다.
- 사용자 0명인 지금이 최적의 타이밍이다 (데이터 이전 불필요).
- 신규 형식 API 키 (
sb_publishable_*/sb_secret_*)를 사용한다. - 「Automatically expose new tables」를 OFF로 설정한 경우 수동 GRANT가 필요하다.
- Confirm signup 템플릿도 반드시 수정한다.
앞으로 Supabase로 개인 개발을 시작하려는 사람은, 처음에 Tokyo 리전을 선택하는 것만으로 이 글의 함정들을 모두 회피할 수 있다.
리전을 나중에 바꾸는 것은 번거로우므로 처음이 중요하다.
🔗 서비스: https://jp-stock-analyzer.onrender.com
🔗 X (진척 상황·매출·실패를 전부 공개): https://x.com/tomato112924
이 계정에서 개인 개발의 생생한 기록을 발신할 예정이니,
괜찮으시다면 팔로우해 주세요.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기