React 앱 빌드
Vite가 개발 코드를 최적화된 정적 번들로 만드는 과정을 이해하고 dist 산출물을 로컬 서버에서 검증합니다.
React 앱을 빌드하는 것은 개발 환경에서 실행하던 코드를 실제 웹 서버에 배포할 수 있는 형태로 변환하는 과정입니다.
이 과정을 거치면 코드는 최적화된 번들 파일로 묶이게 됩니다.
Vite가 정적 산출물을 만들고, preview로 확인한다 — 상태 추적
실제 Vite 소스 변경과 이미 만든 dist 파일/preview의 내용은 독립 상태다. build 전/후 산출물과 실행 주소를 추적해 개발 화면 변경이 기존 dist를 바꾸지 않음을 보여 줄 가치가 있다.
SOURCE / BUILD / DIST / PREVIEW
Vite가 정적 산출물을 만들고, preview로 확인한다
Vite SPA의 기본 빌드는 index.html을 진입점으로 dist 파일을 만든다. 개발 서버와 구분해 실제 산출물을 로컬에서 확인하고, 별도로 구성한 릴리스 절차에서 검증한 파일을 고정한다.
INPUT / REPRODUCIBLE
소스와 설정을 함께 기록한다
React 소스·스타일·public 파일, commit과 lockfile, 빌드 설정을 입력으로 관리한다. TypeScript는 선택 사항이며 Vite 8은 Rolldown 기반으로 번들링한다.
OUTPUT / DIST
필요한 파일들의 집합
기본 출력은 dist/다. index.html과 해시가 붙은 JS·CSS 자산, 필요한 경우 동적 import 청크가 생성된다. public/ 파일은 복사되므로 robots.txt는 원본이 있을 때 포함된다.
CHECK / PREVIEW
실제 산출물을 로컬 서버에서 확인한다
npm run preview 또는 serve -s dist로 파일을 서빙한다. base·자산 경로·공개 환경 값·대표 사용자 흐름을 확인한다. vite preview는 운영 서버가 아니며, 호스트의 깊은 URL rewrite는 별도 확인한다.
RELEASE / CONFIGURE
digest와 캐시 정책은 직접 구성한다
검증한 파일의 digest를 기록하고 같은 바이트를 승격할 릴리스 절차를 마련한다. HTML 재검증과 해시 자산의 장기 캐시, 이전 청크 보존·롤백 정책도 함께 구성한다.
VITE_ 환경 값은 클라이언트 번들에 노출된다. build·preview는 비밀 저장소나 자동 배포·롤백 도구가 아니다. 브라우저 target 변환은 모든 Web API polyfill이나 이미지 최적화를 보장하지 않는다.
이 예의 조건
- 원도표의 전체 구조와 설명은 위 관계도와 표에서 유지합니다. 아래 인쇄 표에도 원도표의 관계·조건·라벨·설명·주석을 보존합니다.
- 두 관찰 칸의 위치는 고정입니다. 관찰 상태는 해당 순간의 값이며, 동작·이유는 그 조건에서의 판정과 변화 원인입니다. 독립 비교와 실패 분기는 별도 조건으로 읽고 모든 분기를 한 요청의 필수 실행 순서로 이어 읽지 않습니다.
| 장면 | 현재 관찰값 | 설명 | 변화 이유 |
|---|---|---|---|
| 현재 소스와 dist | source: 현재 소스 / dist: 이전 빌드 결과 | 소스 수정 전 만든 dist는 별도 파일 집합이다 | 개발 서버 표시와 preview 입력은 다르다 |
| 소스만 수정 | dev: 현재 소스 화면 / preview: 이전 dist 화면 | 개발 화면은 바뀔 수 있어도 기존 dist는 그대로다 | 저장이 production 산출을 자동 재생성하지 않는다 |
| build 후 preview | dist: 새 파일 집합 / preview: 그 산출물 확인 | production build의 새 dist를 preview에서 확인한다 | 실제 호스팅과 digest 승격은 별도 릴리스 계약이다 |
Vite가 정적 산출물을 만들고, preview로 확인한다 — 상태 추적
실제 Vite 소스 변경과 이미 만든 dist 파일/preview의 내용은 독립 상태다. build 전/후 산출물과 실행 주소를 추적해 개발 화면 변경이 기존 dist를 바꾸지 않음을 보여 줄 가치가 있다.
SOURCE / BUILD / DIST / PREVIEW
Vite가 정적 산출물을 만들고, preview로 확인한다
Vite SPA의 기본 빌드는 index.html을 진입점으로 dist 파일을 만든다. 개발 서버와 구분해 실제 산출물을 로컬에서 확인하고, 별도로 구성한 릴리스 절차에서 검증한 파일을 고정한다.
INPUT / REPRODUCIBLE
소스와 설정을 함께 기록한다
React 소스·스타일·public 파일, commit과 lockfile, 빌드 설정을 입력으로 관리한다. TypeScript는 선택 사항이며 Vite 8은 Rolldown 기반으로 번들링한다.
OUTPUT / DIST
필요한 파일들의 집합
기본 출력은 dist/다. index.html과 해시가 붙은 JS·CSS 자산, 필요한 경우 동적 import 청크가 생성된다. public/ 파일은 복사되므로 robots.txt는 원본이 있을 때 포함된다.
CHECK / PREVIEW
실제 산출물을 로컬 서버에서 확인한다
npm run preview 또는 serve -s dist로 파일을 서빙한다. base·자산 경로·공개 환경 값·대표 사용자 흐름을 확인한다. vite preview는 운영 서버가 아니며, 호스트의 깊은 URL rewrite는 별도 확인한다.
RELEASE / CONFIGURE
digest와 캐시 정책은 직접 구성한다
검증한 파일의 digest를 기록하고 같은 바이트를 승격할 릴리스 절차를 마련한다. HTML 재검증과 해시 자산의 장기 캐시, 이전 청크 보존·롤백 정책도 함께 구성한다.
VITE_ 환경 값은 클라이언트 번들에 노출된다. build·preview는 비밀 저장소나 자동 배포·롤백 도구가 아니다. 브라우저 target 변환은 모든 Web API polyfill이나 이미지 최적화를 보장하지 않는다.
이 예의 조건
- 원도표의 전체 구조와 설명은 위 관계도와 표에서 유지합니다. 아래 인쇄 표에도 원도표의 관계·조건·라벨·설명·주석을 보존합니다.
- 두 관찰 칸의 위치는 고정입니다. 관찰 상태는 해당 순간의 값이며, 동작·이유는 그 조건에서의 판정과 변화 원인입니다. 독립 비교와 실패 분기는 별도 조건으로 읽고 모든 분기를 한 요청의 필수 실행 순서로 이어 읽지 않습니다.
| 장면 | 현재 관찰값 | 설명 | 변화 이유 |
|---|---|---|---|
| 현재 소스와 dist | source: 현재 소스 / dist: 이전 빌드 결과 | 소스 수정 전 만든 dist는 별도 파일 집합이다 | 개발 서버 표시와 preview 입력은 다르다 |
| 소스만 수정 | dev: 현재 소스 화면 / preview: 이전 dist 화면 | 개발 화면은 바뀔 수 있어도 기존 dist는 그대로다 | 저장이 production 산출을 자동 재생성하지 않는다 |
| build 후 preview | dist: 새 파일 집합 / preview: 그 산출물 확인 | production build의 새 dist를 preview에서 확인한다 | 실제 호스팅과 digest 승격은 별도 릴리스 계약이다 |
첫 React 앱의 파일 연결과 주소·라우터의 역할을 먼저 확인하세요. 이 절은 Vite로 만든 클라이언트 SPA가 대상입니다. 코드 수정, 빌드 산출물 생성, 그 산출물의 로컬 확인, 실제 호스팅은 서로 다른 작업입니다. 개발 서버에서 새 문구가 보인다는 사실만으로 이미 만든 dist의 내용까지 바뀌지는 않습니다.
왜 빌드를 해야 하는가?
개발 중에는 npm run dev (또는 yarn dev) 명령어를 사용하여 개발 서버를 실행했습니다.
이 개발 서버는 다음과 같은 특징을 가집니다.
- 빠른 개발 환경: 코드 변경 시 즉시 반영되는 HMR(Hot Module Replacement) 기능 등을 제공하여 개발 생산성을 높입니다.
- 다양한 개발 도구 포함: 소스 맵(Source Map) 등 디버깅에 필요한 정보가 포함되어 있습니다.
- 개발 우선 동작: 빠른 수정·디버깅을 위한 모듈 제공 방식과 도구가 포함됩니다. 개발 서버의 응답을 프로덕션 빌드 산출물과 같은 파일로 보지는 않습니다.
반면, 프로덕션 환경에 배포하기 위한 빌드(Build) 과정은 다음과 같은 목표를 가집니다.
- 최적화: JavaScript, CSS, HTML 파일을 최소화(Minification)하여 파일 크기를 줄이고, 불필요한 코드(예: 개발자 도구 관련 코드)를 제거합니다.
- 번들링: 여러 개의 작은 파일들을 하나 또는 몇 개의 큰 파일로 묶어 브라우저의 네트워크 요청 수를 줄입니다.
- 브라우저 호환성: 설정한 build target에 맞춰 JavaScript 문법을 변환합니다. Vite 기본 빌드가 모든 구형 브라우저나 새 Web API의 polyfill까지 보장하지는 않습니다.
- 성능 향상: 코드 스플리팅 등으로 초기 로딩 비용을 줄일 수 있습니다. 이미지 압축·형식 변환은 Vite가 자동으로 해 주는 작업이 아니므로 별도 도구나 서비스가 필요합니다.
- 정적 파일 생성: 웹 서버가 직접 서빙할 수 있는 HTML, CSS, JavaScript, 이미지 등의 정적 파일을 생성합니다.
결론적으로, 빌드 과정은 개발된 애플리케이션을 최종 사용자에게 빠르고 안정적으로 제공하기 위한 필수적인 단계입니다.
Vite 기반 프로젝트 빌드하기
현재 리액트 실무에서는 Vite 기반 프로젝트가 널리 사용됩니다.
Vite 역시 단일 명령어로 프로덕션 빌드를 생성할 수 있고, 개발/빌드 속도가 빠르며 설정 확장이 간결합니다.
빌드 명령여러분의 리액트 프로젝트 루트 디렉터리에서 다음 명령어를 실행합니다.
npm run build
# 또는
yarn build이 명령어를 실행하면, 이 그림의 기준인 Vite 8은 Rolldown 기반 번들링을 수행해 프로젝트 루트에 dist 폴더를 생성합니다.
dist 폴더의 내용물 탐색
기본 설정으로 빌드하면 프로젝트 루트에 dist/가 생성됩니다. 아래는 구성 예시이며 robots.txt는 public/ 등에 원본이 있을 때 복사됩니다. TypeScript는 선택 사항이고 JavaScript 소스도 빌드할 수 있습니다.
index.html: 애플리케이션의 단일 진입점입니다. 이 파일이 로드되면 그 안에 링크된 JavaScript 파일이 실행되어 리액트 앱이 렌더링됩니다.assets/: 빌드된 정적 리소스(CSS, JavaScript, 이미지 등)가 해시 파일명으로 저장됩니다.- 해시된 파일 이름 (
.<hash>.js,.<hash>.css): 파일 이름에 해시 값(예:main.d2a3f5b7.js)이 포함됩니다. 내용이 바뀐 자산에 새 URL을 부여해 장기 캐시를 사용할 수 있게 합니다. 최신 HTML의 재검증과 이전 청크의 보존·배포 정책도 함께 맞아야 합니다. - 최소화 및 번들링: 빌드 설정에 따라 JavaScript·CSS를 최소화하고 모듈을 묶습니다. 동적 import와 출력 설정에 따라 여러 청크가 생길 수 있으므로 모든 코드가 반드시 하나의 파일이 되는 것은 아닙니다.
- 코드 스플리팅 (Code Splitting): 동적 임포트(
import()) 경계 기준으로 청크를 분리하여 초기 로딩 비용을 줄입니다. - 서비스 워커 (선택): Vite는 기본 템플릿에서 서비스 워커를 자동 생성하지 않습니다. PWA가 필요하면
vite-plugin-pwa를 추가해 명시적으로 설정합니다.
빌드된 앱 로컬에서 테스트하기
이 장의 클라이언트 SPA 빌드는 정적 서버로 서빙할 수 있습니다. BrowserRouter의 깊은 URL을 직접 열려면 서버의 앱 경로 rewrite 설정도 필요합니다.
로컬에서 빌드된 앱을 테스트하려면 간단한 정적 파일 서버를 사용할 수 있습니다.
가장 흔한 방법은 serve 패키지를 사용하는 것입니다.
serve 패키지 설치 (전역 또는 프로젝트)npm install -g serve
# 또는
yarn global add serve(프로젝트 단위로 설치하려면 -g를 제거하고 npm install serve 후 npx serve 사용)
dist 폴더 서빙:
프로젝트 루트 디렉터리에서 다음 명령어를 실행합니다.
serve -s dist
# 또는 (yarn 사용 시)
npx serve -s dist이 명령어는 dist 폴더의 내용을 정적 파일 서버로 제공하고, 로컬 주소(http://localhost:<PORT>)로 접근할 수 있게 해줍니다.
Vite 기본 프리뷰를 쓰려면 npm run preview를 사용하며 기본 주소는 http://localhost:4173입니다.
로컬 서버로 빌드된 앱에 접속하여 모든 기능이 정상적으로 동작하는지, 스타일이 깨지지 않는지 등을 최종적으로 확인해야 합니다.
개발 서버와는 다르게 빌드된 앱에서는 개발자 도구 콘솔에 개발 관련 경고나 에러가 줄어든 것을 확인할 수 있습니다.
빌드 결과를 확인할 때는 실제 배포 경로와 자산·공개 환경 값을 함께 점검해야 합니다. 그림의 digest 고정과 동일 바이트 승격은 릴리스 절차이며, vite build나 preview가 자동으로 검증·배포·롤백을 수행한다는 뜻은 아닙니다.
빌드 전후를 한 번 따라가기
프로젝트의 package.json에서 build와 preview가 각각 Vite 빌드·프리뷰 명령으로 연결돼 있는지 먼저 봅니다. 아래 절차는 독자의 실습 프로젝트에서 수행합니다. 호스팅 서비스에 업로드하거나 공개하는 단계는 아닙니다.
- App의 화면 문구를 '빌드 확인 A'로 정하고 저장합니다. build 명령의 종료 결과와 dist/index.html을 확인합니다. HTML이 참조한 assets의 JS·CSS 파일도 실제로 존재하는지 찾습니다. 해시 값은 프로젝트마다 다르므로 위 예시 이름과 같을 필요는 없습니다.
- preview를 실행해 표시된 로컬 주소에서 A를 확인합니다. preview는 현재 dist를 확인하는 로컬 서버이며 운영 서버로 쓰기 위한 명령이 아닙니다. 첫 화면만 보는 대신 사용한 링크·입력·깊은 앱 경로의 새로고침도 확인합니다.
- 소스를 '빌드 확인 B'로 바꾸고 저장하되 아직 다시 빌드하지 않습니다. 개발 서버의 B와 프리뷰의 A가 다를 수 있는 이유를 설명합니다. 다시 빌드한 뒤 프리뷰를 새로 확인해 B가 반영됐는지 관찰합니다.
Vite의 빌드 안내와 정적 배포 안내는 build·dist·preview의 역할을 나누어 설명합니다. 정적 파일을 브라우저가 읽을 수 있으므로 빌드에 포함된 공개 환경 값에 비밀 키를 넣지 않습니다. 비밀이 필요한 작업은 서버의 별도 경계에서 수행합니다.
두 버전의 파일을 독립적으로 판단하기
버전 A의 HTML은 assets/a.js를, 새 버전 B의 HTML은 assets/b.js를 참조한다고 가정합니다. B를 배포하면서 a.js를 즉시 삭제했습니다. 이미 A를 연 사용자가 뒤늦게 a.js를 요청하면 어떤 일이 생기나요? B의 HTML과 a.js만 올린 배포는 어떨까요? 빌드 성공만으로 이 두 경우를 정상이라고 판단할 수 있나요?
산출물과 요청 시점의 풀이
첫 경우에는 옛 HTML이 참조한 a.js가 없어 요청이 실패할 수 있습니다. 새 HTML을 받게 하는 캐시 정책과 옛 페이지가 필요한 청크를 얼마나 보존할지 함께 정합니다. 두 번째는 B의 HTML이 요구하는 b.js가 없어 새 사용자에게도 문제가 생깁니다. HTML과 그 HTML이 참조한 자산을 같은 릴리스 묶음으로 확인해야 합니다.
빌드 성공은 해당 소스에서 산출물을 생성했다는 증거입니다. 업로드 누락, 캐시, API 주소, 호스트의 rewrite까지 증명하지 않습니다. Network에서 실패한 자산의 URL·상태·응답 종류를 확인하고 배포한 파일 목록과 대조합니다. 해시 이름이 있다는 사실만으로 원자적 배포나 자동 롤백이 완성되는 것은 아닙니다.
빌드 설정 커스터마이징 (고급)
Vite는 vite.config.ts를 통해 빌드 동작을 직접 제어할 수 있습니다.
- 출력 제어: Vite 8에서는 build.outDir, build.sourcemap, build.rolldownOptions로 출력 경로·소스맵·번들 옵션을 제어합니다.
- 플러그인 확장:
@vitejs/plugin-react,vite-plugin-pwa등으로 JSX 처리, PWA, 압축, 분석을 조합할 수 있습니다. - 프레임워크 선택: SPA 중심이면 Vite, SSR/풀스택 라우팅이 핵심이면 Next.js 같은 프레임워크가 더 적합할 수 있습니다.
빌드 단계 핵심 정리와 다음 학습 포인트
React 앱 빌드하기는 개발된 애플리케이션을 프로덕션 환경에 배포하기 위한 필수적인 단계입니다.
npm run build(또는yarn build) 명령어로 최적화된 정적 파일을dist폴더에 생성합니다.dist폴더는 웹 서버가 직접 서빙할 수 있고,serve같은 도구로 로컬 검증이 가능합니다.- 특별한 커스터마이징이 필요 없으면 Vite 기본 빌드 설정을 유지하는 것이 가장 안전합니다.
이제는 리액트 애플리케이션을 배포 가능한 형태로 만드는 방법을 이해하셨습니다.