Part 5.1 배포편: 로컬에선 됐는데?
제가 가장 도와드리기가 어려웠던 부분이었습니다. 제가 교육생분들의 환경, 처한 정확한 상황, 에러내용을 잘 모르니, 원인 파악이 쉽지 않았던 기억이 나네요.
"로컬에서 되는데, Vercel에 배포하니까 안되요."
"로컬에서는 API 호출이 잘 됐는데, 배포하니까 에러가 떠요."
"이미지도 다 보이고 로그인도 됐는데, 배포 후에는 아무것도 안 돼요."
로컬 환경과 프로덕션 환경은 다릅니다. 이 차이를 모르면 배포 후 예상치 못한 문제에 당황하게 됩니다.
이번 챕터에서는 로컬에서 프로덕션으로 넘어갈 때 꼭 알아야 할 차이점과 흔한 문제 해결법을 다룹니다.
로컬과 프로덕션의 5가지 차이
1. localhost vs 프로덕션: 근본적인 차이
localhost란?
localhost는 내 컴퓨터에서만 접근 가능한 주소입니다.
http://localhost:3000
//이 주소를 휴대폰에서 들어가 보세요. 접속이 안됩니다. 즉, 현재 구동 중인 로컬에서만 접근이 가능하다는거죠!
-
내 컴퓨터에서만 열림
-
다른 사람은 이 주소로 접근 불가
-
개발 서버가 실행 중일 때만 작동
프로덕션이란?
프로덕션은 전 세계 누구나 접근 가능한 실제 서버입니다.
https://my-app.vercel.app
//google.com을 생각해보세요!
-
인터넷에 연결된 누구나 접근 가능
-
24시간 작동
-
실제 사용자가 사용하는 환경
주요 차이점
| 항목 | localhost | 프로덕션 |
|---|---|---|
| 접근 | 내 컴퓨터만 | 전 세계 |
| 주소 | http://localhost:3000 | https://도메인.com |
| 프로토콜 | HTTP | HTTPS |
| 파일 | 내 컴퓨터에 있음 | 서버에 업로드됨 |
| 환경 변수 | .env 파일 | 플랫폼에서 설정 |
| 에러 | 상세하게 표시 | 간략하게 표시 |
2. 환경 변수 분리: 로컬과 프로덕션 설정 나누기
직전 연재에서 환경 변수를 배웠습니다. 하지만 로컬과 프로덕션에서 다른 값을 써야 할 때가 있습니다.
왜 분리가 필요한가?
로컬: 테스트용 DB, 테스트용 API 키
프로덕션: 실제 DB, 실제 API 키
테스트 중에 실수로 실제 데이터를 삭제하면 안 되니까요.
환경별 .env 파일
# .env.local (로컬 개발용)
NEXT_PUBLIC_SUPABASE_URL=https://test-xxx.supabase.co
NEXT_PUBLIC_API_URL=http://localhost:3001
# .env.production (프로덕션용) - 또는 배포 플랫폼에서 직접 설정
NEXT_PUBLIC_SUPABASE_URL=https://prod-xxx.supabase.co
NEXT_PUBLIC_API_URL=https://api.myapp.com
배포 플랫폼에서 환경 변수 설정
Vercel:
-
프로젝트 대시보드 → Settings → Environment Variables
-
각 변수 추가
-
"Production", "Preview", "Development" 환경 선택 가능
중요: .env 파일은 배포할 때 자동으로 안 올라갑니다. 반드시 배포 플랫폼에서 직접 설정해야 합니다.
흔한 실수
// ❌ 환경 변수가 undefined
console.log(process.env.NEXT_PUBLIC_SUPABASE_URL);
// 결과: undefined (배포 플랫폼에서 설정 안 함)
// 화면: 하얀 화면 또는 에러
해결: 배포 플랫폼에서 환경 변수 설정 → 재배포
3. CORS 이슈: 브라우저 보안 정책
**CORS(Cross-Origin Resource Sharing)**는 바이브코더를 가장 당황하게 만드는 에러 중 하나입니다.
CORS 에러 예시
Access to fetch at 'https://api.example.com/data'
from origin 'https://my-app.vercel.app'
has been blocked by CORS policy
왜 로컬에서는 되고 프로덕션에서는 안 되나?
| 상황 | CORS 체크 |
|---|---|
| localhost → localhost | 같은 출처, 문제 없음 |
| localhost → 외부 API | 개발 모드에서 우회되기도 함 |
| 프로덕션 → 외부 API | 엄격하게 체크됨 |
브라우저는 다른 도메인에서 데이터를 가져오는 것을 기본적으로 막습니다.
내 앱: https://my-app.vercel.app
API: https://api.example.com
→ 도메인이 다름 → CORS 체크!
해결 방법
방법 1: API 서버에서 CORS 허용 (권장)
API를 직접 만들었다면, 응답 헤더에 허용할 도메인을 추가합니다. 내가 만든거니까 내꺼 허용해주는거죠
// Next.js API 라우트 예시
export async function GET(request) {
return new Response(JSON.stringify(data), {
headers: {
'Access-Control-Allow-Origin': 'https://my-app.vercel.app',
'Content-Type': 'application/json',
},
});
}
방법 2: 프록시 사용
외부 API를 직접 호출하지 않고, 내 서버를 거쳐서 호출합니다.
// 클라이언트에서 직접 호출 ❌
fetch('https://external-api.com/data')
// 내 API를 거쳐서 호출 ✅
fetch('/api/proxy-data')
// /api/proxy-data 에서
const data = await fetch('https://external-api.com/data');
return Response.json(data);
4. 데이터베이스 연결: 환경별 DB 분리
로컬 vs 프로덕션 DB
| 환경 | 데이터베이스 |
|---|---|
| 로컬 | 테스트 데이터, 마음대로 삭제 OK |
| 프로덕션 | 실제 사용자 데이터, 삭제하면 큰일 |
권장: 개발용 DB와 프로덕션 DB를 분리하세요.
Supabase에서는 프로젝트를 2개 만들면 됩니다: 무료플랜으로 다 만들 수 있어요.
-
my-app-dev(개발용) -
my-app-prod(프로덕션용)
흔한 문제들
문제 1: 프로덕션에서 DB 연결 안 됨
// 에러: connection refused 또는 timeout
원인:
-
환경 변수에 DB URL이 설정 안 됨
-
프로덕션 DB의 접근 권한 설정 안 됨
-
DB URL이 로컬용 주소임 (
localhost:5432)
문제 2: RLS 정책으로 데이터 접근 차단
로컬에서 RLS를 끄고 개발했다면, 프로덕션에서 데이터가 안 보일 수 있습니다.
-- 개발 중 RLS 끄기 (편의상)
ALTER TABLE todos DISABLE ROW LEVEL SECURITY;
-- 프로덕션에서는 RLS 켜고 정책 설정
ALTER TABLE todos ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can access own data" ON todos
FOR ALL USING (auth.uid() = user_id);
5. 빌드 프로세스: 개발 모드 vs 프로덕션 빌드
개발 모드 (npm run dev)
npm run dev
# 또는
npm start
-
코드 변경하면 바로 반영 (Hot Reload)
-
상세한 에러 메시지
-
최적화 안 됨 (느림)
-
개발용으로만 사용
프로덕션 빌드 (npm run build)
npm run build
-
코드를 최적화하고 압축
-
불필요한 코드 제거
-
에러 메시지 간략화
-
배포 전 반드시 실행해야 함
빌드 에러: 로컬에서는 되는데 빌드가 안 돼요
개발 모드에서는 넘어가던 문제가 빌드할 때 터지는 경우가 많습니다.
흔한 빌드 에러들:
# 1. 타입 에러 (TypeScript)
Type error: Property 'name' does not exist on type 'never'
# 2. import 에러
Module not found: Can't resolve './components/Button'
# 3. 환경 변수 에러
Error: Missing required env variable: NEXT_PUBLIC_API_URL
해결: 배포 전에 로컬에서 빌드 테스트하세요.
# 빌드 테스트
npm run build
// 만약 문제가 있다면 build는 멈추고, 어디서 에러가 터졌는지 표시될거에요
빌드가 성공하면 배포해도 대부분 문제없습니다.
Related Articles
Thank you for reading.