Vercel 환경변수가 적용 안 될 때, 비개발자가 점검할 5가지
로컬에서는 멀쩡한데 Vercel에 배포한 사이트만 흰 화면이 뜨거나 process.env가 undefined로 나올 때, 코드를 고치기 전에 먼저 봐야 할 환경변수 설정을 정리했습니다.
Vercel에 배포하고 사이트를 열었는데 화면이 비어 있거나, 콘솔에 빨간 글씨로 "Cannot read properties of undefined" 같은 메시지가 줄줄이 떠 있는 적이 있을 겁니다.
로컬에서는 분명히 잘 돌아갔는데, 왜 배포만 하면 깨질까요?
답은 거의 항상 같습니다. 환경변수가 배포에 반영되지 않았거나, 반영됐지만 의도대로 적용되지 않은 경우입니다. Cursor, Lovable, Bolt로 만든 프로젝트에서 특히 자주 보입니다. AI는 .env 파일에 키를 잘 넣어주지만, 그 값이 Vercel 운영 환경으로 자동으로 옮겨가지는 않습니다.
로컬과 배포는 환경변수가 사는 곳이 다르다
먼저 이해해야 하는 건, 로컬과 배포 환경의 환경변수가 완전히 분리되어 있다는 점입니다.
로컬에서는 프로젝트 폴더의 .env, .env.local 같은 파일에서 값을 읽습니다. Vercel은 이 파일을 읽지 않습니다. 배포된 사이트는 Vercel 대시보드의 Settings → Environment Variables에 등록된 값만 봅니다.
그래서 .env에는 SUPABASE_URL이 있는데 Vercel에는 없으면, 배포된 사이트는 그 값을 영원히 모릅니다. 코드는 멀쩡한데 코드가 참조하는 값이 비어 있는 상태인 거죠.
가장 먼저 할 일은 Vercel 프로젝트의 Settings → Environment Variables 화면을 열어보는 것입니다. 로컬 .env 파일에 있는 키 이름이 거기에도 그대로 들어가 있어야 합니다.
NEXT_PUBLIC_ 접두어가 붙어 있는지
Next.js를 쓰고 있다면 이 부분이 핵심입니다.
환경변수는 두 종류로 나뉩니다. 서버에서만 쓰이는 값과, 브라우저에서도 읽혀야 하는 값입니다. 브라우저(클라이언트)에서 사용해야 하는 값은 이름 앞에 반드시 NEXT_PUBLIC_ 이 붙어 있어야 합니다.
예를 들어 Supabase의 anon key는 클라이언트에서도 호출하기 때문에 NEXT_PUBLIC_SUPABASE_ANON_KEY 같은 이름으로 정의되어야 하지만, service role key처럼 서버에서만 쓰는 값에는 절대 NEXT_PUBLIC을 붙이면 안 됩니다. 보안 이슈로 이어집니다.
흔한 증상은 이렇습니다.
- 같은 값을 서버 쪽에서는 잘 읽는데 화면 컴포넌트에서는 못 읽는다
- 콘솔에 process.env.X is undefined가 클라이언트에서만 찍힌다
이런 패턴이면 NEXT_PUBLIC을 빠뜨렸거나, 반대로 노출되면 안 되는 키에 NEXT_PUBLIC을 붙여놓은 경우입니다. 이름을 한 번씩 다시 읽어보세요.
환경변수를 바꿨다면 반드시 재배포
많이 놓치는 부분입니다.
Vercel 대시보드에서 환경변수를 추가하거나 수정해도, 이미 배포되어 있는 사이트에는 자동으로 반영되지 않습니다. 환경변수는 빌드 시점에 코드 안으로 들어가기 때문에, 새로 빌드를 돌려야 새 값이 적용됩니다.
방법은 두 가지 중 하나입니다.
- Vercel의 Deployments 탭에서 최신 배포의 점 세 개 메뉴를 누르고 Redeploy를 실행한다
- 코드를 한 줄이라도 바꿔서 GitHub에 push한다
환경변수를 저장만 하고 사이트를 새로고침하면 옛날 값이 그대로 보입니다. "분명히 저장했는데 왜 안 되지?" 라는 의문이 들 때 가장 먼저 의심할 지점입니다.
Production / Preview / Development 환경 구분
Vercel의 환경변수 입력 화면에는 체크박스 세 개가 있습니다. Production, Preview, Development.
어느 환경에서 이 값을 쓸지 고르는 옵션인데, 하나만 체크하고 저장하면 다른 환경에서는 그 값이 비어 있습니다.
자주 보이는 실수:
- Production만 체크해두고 PR 미리보기 도메인(Preview)에서 화면이 깨진다
- Development만 체크해서 정작 운영 도메인에서는 값이 비어 있다
- 결제 키처럼 환경별로 달라야 하는 값을 세 환경에 모두 같은 값으로 넣어 운영에 테스트 키가 들어간다
원칙은 단순합니다. 환경별로 달라야 하는 값(결제 키, 도메인 주소)은 따로 등록하고, 그 외 일반 키는 세 환경 모두 체크해두는 편이 안전합니다.
이름 오타와 따옴표, 공백
가장 어이없지만 실제로 자주 보이는 원인입니다.
- 로컬에서는 SUPABASE_URL인데 Vercel에는 SUPABABASE_URL로 등록한 경우 (오타)
- 값을 붙여넣을 때 큰따옴표를 함께 입력해버린 경우 ("https://xxx.supabase.co" 처럼)
- 값 끝에 공백이나 줄바꿈이 따라 들어간 경우
Vercel은 입력한 값을 그대로 저장합니다. 따옴표를 같이 넣으면 따옴표까지가 값으로 인식돼서, 코드에서는 그 주소로 API를 호출하지 못합니다.
값을 붙여넣은 직후 한 번 클릭해서 어떤 모양으로 저장됐는지 확인해 보세요. 의심스러우면 값을 지우고 손으로 다시 입력하는 것도 방법입니다.
AI에게 물어볼 때 주의할 점
환경변수 문제를 AI에게 던질 때는 "코드를 고쳐서 동작하게 만들어줘" 보다 "내 환경변수 설정과 코드 호출이 일치하는지 확인해줘" 가 낫습니다.
AI는 Vercel 대시보드 화면을 직접 볼 수 없습니다. 그래서 "동작하게 만들겠다" 는 방향으로 가다 보면, .env에 있는 값을 코드에 기본값으로 박아놓는 식의 위험한 수정을 하기도 합니다. 이러면 Supabase 키나 Stripe 키가 GitHub에 그대로 올라갑니다. 한 번 올라가면 git history에서 완전히 지우기도 까다롭고요.
물어볼 때는 다음 정보를 같이 주세요.
- 로컬에서는 정상 동작한다는 사실
- Vercel에 등록한 환경변수 이름 목록 (값은 가리고)
- 코드에서 process.env.X를 호출하는 위치
- 콘솔에 찍히는 정확한 에러 메시지
이 정도가 있으면 AI도 코드와 설정 중 어느 쪽이 어긋나 있는지 좁혀줄 수 있습니다.
그래도 안 풀린다면
환경변수 문제는 코드 버그처럼 보이지만 거의 대부분 설정 문제입니다. 위 다섯 가지를 먼저 확인하면 같은 화면을 두세 시간 들여다보는 일은 줄어듭니다.
그래도 풀리지 않는다면 보통 한 가지가 더 있습니다. 모노레포 구조라 빌드 컨텍스트가 다르거나, Edge Runtime을 쓰고 있어서 일반 환경변수 접근 방식이 다르거나, Next.js의 middleware에서 환경변수를 참조하는 경우입니다. 이 경우는 단순한 설정 점검만으로 해결되지 않습니다.
혼자 너무 오래 붙잡지 말고, 짧게라도 코드 구조를 같이 봐줄 사람과 점검하는 편이 빠릅니다.
관련 글: Bolt.new 배포 오류 해결: Vercel에서 실패하는 대표 원인, 비개발자의 바이브코딩, 왜 배포에서 자주 막힐까?