Vercel 배포 오류 가이드: 로컬에서는 되는데 운영에서 깨질 때 체크리스트
Dev
마지막 업데이트

Vercel 배포 오류 가이드: 로컬에서는 되는데 운영에서 깨질 때 체크리스트


“로컬에서는 잘 되는데 Vercel에 올리면 깨진다”는 말은 막연해 보이지만, 실제 원인은 대개 몇 가지 반복 패턴 안에 들어갑니다.

가장 빨리 푸는 방법은 배포 실패를 전부 같은 문제로 보지 않는 것입니다. 먼저 어디서 실패하는지부터 나눠야 합니다.

  • 빌드 단계 실패
  • 런타임 단계 실패
  • 정적 자산이나 라우팅 문제
  • 도메인이나 DNS 문제

이 글은 그 구분부터 빠르게 하는 실전 체크리스트입니다.


먼저 실패 유형부터 나누기

코드를 바로 고치기 전에 먼저 확인할 질문은 하나입니다. “빌드 자체가 실패했는가, 아니면 빌드는 성공했는데 배포 후 깨지는가?”

이 구분이 중요한 이유는 원인 후보가 완전히 달라지기 때문입니다.

  • 빌드 실패는 환경 변수, Node 버전 차이, 의존성 분류, 프레임워크 설정 문제인 경우가 많습니다.
  • 런타임 실패는 서버 전용 코드 유입, API 시크릿 누락, 실행 환경 가정 오류, 외부 서비스 장애인 경우가 많습니다.
  • 도메인 실패는 앱 코드보다 DNS, SSL, 전파 상태 문제일 가능성이 높습니다.

이걸 구분하지 않으면 같은 가설로 재배포만 반복하게 됩니다.

환경 변수부터 확인하기

로컬 성공이 배포 실패로 바뀌는 가장 흔한 이유는 여전히 환경 변수입니다.

로컬의 .env.local 값은 자동으로 Vercel에 올라가지 않습니다. 또 preview와 production 값이 다를 수도 있습니다.

확인할 것:

  • Settings -> Environment Variables에 필요한 값이 모두 있는지
  • 올바른 환경에 값이 들어갔는지
  • 코드가 정확한 변수명을 읽고 있는지
  • 공개 가능한 클라이언트 변수는 프레임워크 규칙에 맞는 prefix를 쓰는지

개발 머신에 이미 값이 있어서 로컬에서는 문제를 숨기고 있을 수 있습니다.

Node와 패키지 매니저 버전 비교하기

같은 저장소라도 실행 환경 가정이 다르면 배포는 실패할 수 있습니다.

확인 포인트:

  • 로컬 Node 버전
  • Vercel Node 버전
  • lockfile 상태
  • 패키지 매니저 버전

특히 이런 경우에 자주 드러납니다.

  • 의존성이 더 최신 런타임 기능을 기대할 때
  • lockfile이 다른 버전에서 생성됐을 때
  • 네이티브 패키지 동작이 환경마다 다를 때

의존성 관련 오류가 애매하게 보이면 먼저 버전 드리프트부터 제거하는 게 좋습니다.

런타임 패키지가 devDependencies에 들어가 있지 않은지 확인하기

로컬에서는 다 설치돼 있으니 괜찮아 보이지만, 배포 환경은 필요한 것만 기대하는 방식으로 동작합니다.

실제로 실행이나 빌드에 필요한 패키지가 개발 전용으로 잘못 분류돼 있으면 배포에서만 터질 수 있습니다.

대표 예시:

  • 프레임워크 adapter
  • 빌드 과정에서 실제로 쓰이는 markdown 또는 content 처리 패키지
  • 인증, 스토리지, DB 관련 SDK

설치 후 실행에 필요하거나 빌드에 직접 필요하다면 개발 편의 도구처럼 취급하면 안 됩니다.

파일 경로 대소문자 문제 보기

이 문제는 어떤 환경에서는 조용히 지나가고, 어떤 환경에서는 바로 실패합니다.

예를 들어 Component.tsx 파일을 두고 import는 component.tsx처럼 쓰면 로컬에서는 지나가도 Linux 기반 환경에서는 깨질 수 있습니다.

확인할 것:

  • 컴포넌트 import 대소문자
  • asset 파일명
  • route 파일명
  • markdown/frontmatter 이미지 경로

이건 “로컬에선 되는데 운영에서만 안 되는” 대표 패턴입니다.

브라우저 코드와 서버 전용 코드를 분리하기

클라이언트 번들에 서버 전용 코드가 섞이면 배포가 실패하거나 런타임에서 깨질 수 있습니다.

대표 신호:

  • 브라우저 코드에서 process.env 직접 사용
  • 공유 유틸에 fs, path 같은 Node 전용 모듈 포함
  • 클라이언트까지 내려가는 컴포넌트에서 서버 시크릿 참조

지원되지 않는 모듈이나 client bundle 오류가 보이면, 다른 설정보다 import graph부터 확인하는 게 빠릅니다.

asset 경로와 출력 구조 가정 다시 보기

정적 자산 문제는 처음엔 라우팅 문제처럼 보이기도 합니다.

살펴볼 것:

  • markdown 내부 상대 경로
  • 로컬 디렉터리 구조를 가정한 이미지 참조
  • 하드코딩된 출력 경로
  • 생성된 asset의 base path 가정

로컬 preview가 멀쩡하다고 해서 운영에서 같은 경로로 해석된다는 뜻은 아닙니다.

빌드 중 외부 API 호출은 실패 지점이 될 수 있습니다

정적 빌드가 외부 API에 의존하면, 배포 품질도 그 외부 시스템 상태에 묶입니다.

다음 이유로 실패할 수 있습니다.

  • API가 느리거나 다운됨
  • rate limit 도달
  • 응답 스키마 변경
  • Vercel에 필요한 자격 증명이 없음

빌드 타임에 원격 데이터를 가져온다면, 프레임워크를 의심하기 전에 그 요청 자체가 실패했는지부터 봐야 합니다.

프레임워크 출력 모드와 플랫폼 가정 확인하기

Vercel 배포 실패는 플랫폼 버그보다 설정 불일치인 경우가 더 많습니다.

확인할 것:

  • static과 server 출력 모드가 맞는지
  • adapter나 배포 타깃이 맞는지
  • 지원되지 않는 런타임 가정이 없는지
  • 출력 디렉터리나 라우팅 가정을 잘못 두지 않았는지

Astro, Next.js, Vite 계열을 오가면서 호스팅 모델도 비슷할 것이라 가정하면 여기서 자주 틀어집니다.

빌드가 성공했다면 런타임 로그로 넘어가기

빌드 성공은 앱 정상과 다릅니다.

배포는 됐는데 사이트가 깨지면 다음 순서로 봅니다.

  1. runtime 또는 function 로그 확인
  2. preview와 production 시크릿 비교
  3. 외부 서비스 접근 가능 여부 확인
  4. 로컬 파일 시스템 가정이 코드에 없는지 확인

이 시점부터는 build log보다 request 시점 오류가 더 중요합니다.

도메인 문제와 앱 문제를 분리하기

앱은 멀쩡한데 커스텀 도메인만 깨져 보이는 경우도 많습니다.

확인 포인트:

  • DNS 레코드
  • SSL 인증서 상태
  • 전파가 아직 끝나지 않았는지
  • 도메인이 올바른 프로젝트에 연결돼 있는지

배포 URL은 열리는데 커스텀 도메인만 안 되면, 그건 더 이상 앱 코드 문제가 아닙니다.

실전 점검 순서

시간이 없을 때는 이 순서가 가장 효율적입니다.

  1. 빌드 실패인지 런타임 실패인지 도메인 문제인지 먼저 구분
  2. 재배포 전에 로그를 한 번 정확히 읽기
  3. env와 런타임 버전 비교
  4. import, 의존성, 경로 대소문자 확인
  5. 외부 API와 출력 모드 확인

여러 군데를 한꺼번에 바꾸고 다시 배포하는 것보다 훨씬 빠릅니다.

빠른 체크리스트

  • 실패 유형을 먼저 구분했다
  • 필요한 환경 변수가 올바른 Vercel 환경에 존재한다
  • Node와 패키지 매니저 버전이 맞는다
  • 필요한 패키지가 devDependencies에 숨어 있지 않다
  • import와 asset 경로 대소문자가 정확하다
  • 서버 전용 코드가 클라이언트로 새지 않는다
  • 빌드 중 호출하는 외부 API가 안정적이다
  • 빌드 성공 후에는 런타임 로그를 확인했다
  • DNS와 SSL을 앱 문제와 분리해서 봤다

FAQ

Q. 제일 먼저 뭘 봐야 하나요?

실패 유형을 먼저 나누고, 그 다음 로그와 환경 변수를 확인하세요.

Q. 왜 로컬 빌드는 되는데 배포는 실패하나요?

대부분은 production 환경 변수 누락, 버전 차이, 경로 대소문자, 의존성 분류, 서버 전용 코드 유입 때문입니다.

Q. 배포는 성공했는데 사이트가 안 열리면요?

런타임 로그를 먼저 보고, 그 다음 커스텀 도메인, DNS, SSL 상태를 확인하세요.

먼저 읽어볼 가이드

검색 유입이 많은 핵심 글부터 이어서 보세요.