React 교재 · 운영 24편

React 빌드와 배포

localhost 에서 보던 앱을 인터넷에. Vite build 한 줄 + Vercel·Cloudflare 한 클릭.

빌드 결과물이 클라우드로 배포되는 파이프라인 일러스트 — 배포 컨셉

23편까지 React 의 모든 패턴을 배웠다. 이제 진짜 — 인터넷에 올리기. 다행히 2026 년 현재 React 앱 배포는 5년 전과 비교할 수 없을 만큼 쉽다. Vite build + 정적 호스팅 = 5분.

이번 24편은 production build 의 작동 원리 + code splitting + 환경 변수 분리 + 3 대 호스팅 옵션 (Vercel·Cloudflare Pages·자체 nginx) 비교 + 박준성님 환경 권장.

1. vite build — 무엇이 일어나나

npm run build # = vite build # 결과 dist/ ├── index.html # 진입점, script src 자동 주입 ├── assets/ │ ├── index-a4f3b2c1.js # 메인 번들 (해시 포함 — 캐시 무효화) │ ├── index-9e2c1d3f.css # CSS │ └── react-7a8b9c0d.js # vendor (react·react-dom 분리) └── vite.svg

4가지 자동 — ① TypeScript 컴파일. ② JSX → JS. ③ tree shaking (사용 안 한 코드 제거). ④ minify + 해시 (캐시 busting). dist 폴더 그대로 어떤 정적 호스팅에 올려도 동작.

번들 크기 확인npm install -D rollup-plugin-visualizer 후 vite.config 에 추가. npm run build 시 stats.html 생성 → 어떤 라이브러리가 얼마나 차지하는지 시각화. React 19 + react-dom 만 약 45KB (gzip). 1MB 넘으면 모듈 줄여야.

2. Code splitting — lazy + Suspense

모든 코드를 한 번에 받으면 첫 로딩이 느림. 라우트별로 분할이 표준.

// App.tsx import { lazy, Suspense } from 'react'; import { Routes, Route } from 'react-router-dom'; const Dashboard = lazy(() => import('./pages/Dashboard')); const Settings = lazy(() => import('./pages/Settings')); const Report = lazy(() => import('./pages/Report')); function App() { return ( <Suspense fallback={<Spinner />}> <Routes> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/settings" element={<Settings />} /> <Route path="/report" element={<Report />} /> </Routes> </Suspense> ); }

이러면 사용자가 /dashboard 방문 시 Dashboard 청크만 로드. Settings·Report 는 가지 않으면 전송 안 됨. 첫 페이지 로드 = 메인 청크 + 현재 라우트 청크 2개만.

3. 환경 변수 — VITE_ prefix 필수

API 베이스 URL·분석 키 같은 값을 코드 안에 박지 말고 환경 변수로.

# .env.local (git ignore) VITE_API_URL=https://api.example.com VITE_SENTRY_DSN=https://[email protected]/... // 코드 안에서 사용 const apiUrl = import.meta.env.VITE_API_URL;
중요VITE_ prefix 가 붙은 변수만 클라이언트 번들에 포함. 그래서 secret (DB 비밀번호·서버 API 키) 은 절대 VITE_ prefix 로 두면 안 됨. 브라우저 콘솔에서 다 보인다. 진짜 secret 은 서버측 (Next.js 라면 RSC, Vite SPA 라면 별도 API 서버) 에서만 사용.

4. 호스팅 3 선택

옵션장점적합한 경우
Vercelgit push 만으로 자동 배포·preview URL·Edge·무료 티어 넉넉Next.js 면 사실상 첫 선택
Cloudflare Pages무제한 bandwidth·Workers 통합·전 세계 CDN·무료 티어 더 큼정적 SPA·트래픽 많은 사이트·박준성님 회사 stack 에 있음
자체 Nginx (VPS)완전 제어·기존 인프라 재사용·비용 예측 가능junai.ai 같이 이미 nginx 가 도메인 관리 중인 환경. dist/ 를 /var/www/ 에 복사 + nginx try_files

Vercel 5분 배포

npm install -g vercel vercel # GitHub 연결 → 자동 빌드 → URL 발급 # 이후 git push origin main 마다 자동 재배포

Cloudflare Pages

npm install -g wrangler wrangler pages deploy ./dist --project-name=my-app # 또는 GitHub 연결로 자동화

자체 Nginx (박준성님 환경 패턴)

scp -r dist/* user@server:/var/www/my-app/ # /etc/nginx/sites-available/my-app server { server_name app.junai.ai; root /var/www/my-app; index index.html; location / { try_files $uri $uri/ /index.html; # SPA 라우팅 — 모든 경로를 index.html 로 } }

SPA 의 핵심 — try_files ... /index.html. 사용자가 /dashboard URL 을 직접 입력해도 nginx 가 index.html 을 반환 → React Router 가 클라이언트에서 라우팅. 안 그러면 404.

박준성님 환경 권장 — junai.ai 가 이미 Nginx + Cloudflare 라 새 React 앱을 같은 Nginx 에 server_name 추가하는 게 깨끗. app.junai.ai · admin.junai.ai 같은 서브도메인으로. Cloudflare 가 앞단에서 CDN·SSL 자동 처리.

24편으로 production 까지 완성. 25편 마지막 — 운영 중 만나는 디버깅 + 옛 코드 마이그레이션 패턴.

다음 글 (시리즈 마지막)

React 교재 25편 — DevTools 디버깅 + 마이그레이션 패턴. Class → Hooks, JS → TS, 시리즈 완결.

© 2026 주나이테크(주) @JUNAITECH