사이트가 왜 이렇게 느리지?
— Vercel + Supabase 지연의 진짜 원인
바이브코딩으로 만든 사이트, 배포했더니 페이지 로딩이 3~4초. 코드 문제가 아니었습니다. 서버가 지구 반 바퀴를 돌아다니고 있었거든요.
Vercel + Supabase 조합에서 서버리스 함수의 실행 리전을 지정하지 않으면, 한국 사용자가 접속해도 요청이 미국(버지니아)을 거쳐 인도(뭄바이)까지 왕복하는 일이 벌어집니다.
DB 쿼리 한 번에 약 380ms. SSR 페이지에 쿼리가 5~10개면 최대 3~4초가 DB 대기시간에 쓰입니다. 함수 리전을 도쿄(hnd1)로, DB를 도쿄/서울로 맞추면 같은 쿼리가 약 35ms로 줄어듭니다. 설정 파일 몇 줄이 전부입니다.
처음엔 코드 문제인 줄 알았습니다
Vercel에 Next.js 프로젝트를 배포했습니다. 로컬에서는 빠른데, 배포하고 나서 SSR 페이지를 열 때마다 화면이 뜨기까지 3~4초가 걸렸습니다. 처음엔 당연히 코드 문제라고 생각했습니다.
Vercel을 사용하면 정적 파일(HTML, CSS, 이미지)은 전 세계 엣지 네트워크로 자동 배포됩니다. 서울 사용자가 접속하면 서울 엣지 서버에서 파일을 받아 빠릅니다.
그런데 서버리스 함수(API Routes, Server Actions, SSR)는 다릅니다. 함수는 특정 리전에 배포됩니다. 리전을 지정하지 않으면 Vercel은 기본값인 미국 버지니아(iad1)를 사용합니다. 서울 유저가 클릭해도 요청이 미국까지 날아가서 처리하고 돌아오는 것입니다.
왜 뭄바이가 문제였을까요
함수가 미국에 있는 것도 문제였지만, 더 큰 문제는 DB가 인도 뭄바이에 있었다는 점입니다.
FM대로 Supabase 프로젝트를 처음 만들게 되면 리전을 선택하는 화면이 나옵니다. 하지만 MCP로 연결로 승인처리 하면서 문제가 발생했었던 것이였습니다. Supabase의 기본 리전이 인도 뭄바이(ap-south-1)였던 것입니다.
인터넷 데이터는 광속으로 이동하지만, 지구는 큽니다. 미국 버지니아에서 인도 뭄바이까지 직선 거리는 약 13,000km입니다. 빛의 속도를 감안해도 왕복에만 이론적으로 80~100ms가 걸립니다. 실제로는 라우팅, 처리 시간 등이 더해져 180ms 이상이 됩니다.
SSR 페이지 하나를 렌더링하기 위해 DB 쿼리를 10번 실행한다면? 180ms × 10 = 1,800ms가 순수 DB 왕복에만 쓰입니다. 여기에 함수 실행 시간, 네트워크 오버헤드를 더하면 3~4초가 나오는 것입니다.
코드가 아무리 최적화돼 있어도, 요청이 지구를 반 바퀴 돌고 있다면 빠를 수가 없습니다.
해결 방법 — 리전을 같은 곳으로 맞춰주면 됩니다
해결책은 생각보다 단순했습니다. 함수 실행 리전과 DB 리전을 가능한 가깝게 맞추는 것입니다. 한국 사용자를 위한 서비스라면 일본 도쿄(Vercel hnd1) 또는 한국 서울(Supabase ap-northeast-2) 조합이 현실적인 최선입니다.
Supabase DB 리전은 프로젝트를 처음 만들 때만 선택할 수 있습니다. 이미 뭄바이로 만들었다면 새 프로젝트를 만들고 데이터를 마이그레이션해야 합니다. 처음 시작할 때 리전 선택이 얼마나 중요한지 알 수 있는 부분입니다.
1단계 — Supabase DB 리전 설정 (신규 프로젝트 기준)
Supabase에서 새 프로젝트를 생성할 때 리전 선택 화면에서 한국 서비스라면 아래 두 곳 중 하나를 선택합니다.
| 리전 이름 | 위치 | 특징 |
|---|---|---|
ap-northeast-1 |
일본 도쿄 | 한국과 약 5~10ms, 가장 일반적인 선택 |
ap-northeast-2 |
한국 서울 (베타) | 가장 가깝지만 가용성 확인 필요 |
2단계 — Vercel 함수 리전 설정
프로젝트 루트에 vercel.json 파일을 만들거나, 이미 있다면 아래 설정을 추가합니다.
// vercel.json 없거나 regions 설정 없음 // → 함수가 iad1 (미국 버지니아)에서 실행됨
{
"functions": {
"app/**/*.ts": {
"regions": ["hnd1"] // 도쿄
}
}
}
Next.js App Router를 사용하고 있다면, 특정 라우트의 런타임 설정으로도 지정할 수 있습니다.
// 해당 파일에 추가 export const preferredRegion = 'hnd1' // 도쿄 // 또는 배열로 여러 리전 지정 (가장 가까운 곳 자동 선택) export const preferredRegion = ['hnd1', 'icn1']
3단계 — 배포 후 확인
설정을 적용하고 배포한 뒤, Vercel 대시보드 → Functions 탭에서 실행 리전이 바뀌었는지 확인합니다. 브라우저 개발자 도구(F12) → Network 탭에서 API 응답 시간도 비교해 보면 효과를 직접 확인할 수 있습니다.
# 개선 전후 응답 시간 비교 curl -o /dev/null -s -w "\nTotal: %{time_total}s\n" \ https://your-site.vercel.app/api/your-endpoint
실제로 어떻게 달라졌나요
리전을 맞추고 나서 수치가 확실하게 달라졌습니다.
| 측정 항목 | 개선 전 | 개선 후 |
|---|---|---|
| DB 쿼리 1회 왕복 | 약 380ms | 약 35ms (약 10배 개선) |
| 함수 실행 리전 | iad1 미국 버지니아 | hnd1 일본 도쿄 |
| DB 리전 | ap-south-1 인도 뭄바이 | ap-northeast-1 일본 도쿄 |
| SSR 페이지 로드 (쿼리 5개) | 약 2~3초 | 약 300~500ms |
페이지가 열리기를 기다리던 3~4초가, 눈 깜짝할 사이에 뜨는 수준이 됐습니다. 코드를 한 줄도 건드리지 않고, 리전 설정 파일 몇 줄만 추가했을 뿐입니다.
처음부터 제대로 설정하기 — 체크리스트
바이브코딩이나 새 프로젝트를 시작할 때 아래 항목을 확인해 두면 나중에 같은 고생을 하지 않아도 됩니다.
- ✓ Supabase 프로젝트 생성 시 리전을 먼저 확인합니다. 한국 서비스라면 도쿄(ap-northeast-1) 또는 서울(ap-northeast-2)을 선택합니다. 기본값 그대로 넘어가지 않습니다.
- ✓ Vercel 배포 후 Functions 탭에서 실행 리전을 확인합니다. iad1이 보이면 vercel.json에 리전을 명시적으로 지정합니다.
- ✓ 함수 리전과 DB 리전을 같은 곳 또는 최대한 가깝게 맞춥니다. 리전이 다르면 DB 쿼리마다 불필요한 지연이 쌓입니다.
- △ SSR 페이지의 DB 쿼리 수를 파악해 둡니다. 쿼리가 많을수록 지연이 선형으로 늘어납니다. N+1 쿼리 문제가 없는지도 함께 확인합니다.
-
△
자주 바뀌지 않는 데이터는 캐싱을 고려합니다. 리전을 맞추는 것 다음으로 효과가 큰 최적화입니다. Next.js의
revalidate나 Vercel KV를 활용하면 DB를 아예 안 거칠 수 있습니다.
Vercel 자체가 미국 회사이고, 가장 많은 사용자가 미국·유럽에 있습니다. 기본값은 항상 가장 많은 사람에게 최적화된 설정입니다. 한국처럼 특정 지역 서비스를 만들 때는 개발자가 직접 지역에 맞게 설정을 바꿔줘야 합니다. 이건 Vercel의 잘못이 아니라, 글로벌 플랫폼의 기본 특성입니다.
AI 도구로 코드를 생성할 때도 마찬가지입니다. AI는 리전 설정까지 자동으로 최적화해주지 않습니다. 인프라 설정은 개발자가 직접 챙겨야 하는 영역입니다.
자주 묻는 질문
supabase db dump로 스키마와 데이터를 내보내고 새 프로젝트에 적용하면 됩니다. 번거롭지만 초기에 설정을 제대로 잡는 것이 나중에 훨씬 편합니다.unstable_cache로 캐싱하면 DB 쿼리 자체를 없앨 수 있습니다. 그 외에 N+1 쿼리 문제 해결, Supabase의 Connection Pooling 활성화, 인덱스 추가 등도 효과적입니다.핵심 요약표
| 항목 | 문제 상황 | 해결 방법 | 효과 |
|---|---|---|---|
| 함수 리전 | 기본값 미국 버지니아(iad1) | vercel.json에 hnd1(도쿄) 명시 | 한국↔함수 지연 대폭 감소 |
| DB 리전 | Supabase 기본값 인도 뭄바이 | 신규 프로젝트를 도쿄/서울로 생성 | 함수↔DB 지연 180ms → 5ms |
| DB 쿼리 수 | SSR 페이지에 5~10개 쿼리 | 리전 정렬 + 쿼리 수 최소화 | 페이지 로드 3~4초 → 수백ms |
| 캐싱 | 매 요청마다 DB 조회 | Vercel KV 또는 revalidate 적용 | DB 쿼리 자체를 제거 |
Vercel 공식 문서 — Regions & Edge Network · Supabase 공식 문서 — Project Regions · Next.js 공식 문서 — preferredRegion · IMLAB 자체 경험 기록