본문 바로가기

React 앱 빌드

Vite가 개발 코드를 최적화된 정적 번들로 만드는 과정을 이해하고 dist 산출물을 로컬 서버에서 검증합니다.

11장에서는 만든 React 앱을 빌드하고 배포하는 방법과, 이 교재 다음에 이어 갈 학습 경로를 다룹니다. React 앱을 빌드한다는 것은 개발 환경에서 실행하던 코드를 실제 웹 서버에 배포할 수 있는 형태로 바꾸는 과정이며, 이 과정을 거치면 코드가 최적화된 번들 파일로 묶입니다. 이 글은 첫 번째 React 앱 만들기의 파일 연결과 SPA 이해에서 본 주소와 라우터의 역할을 알고 있다고 가정하며, Vite로 만든 클라이언트 SPA를 대상으로 합니다.

코드를 고치는 일, 빌드 산출물을 만드는 일, 그 산출물을 로컬에서 확인하는 일, 실제로 호스팅하는 일은 서로 다른 작업입니다. 개발 서버에서 새 문구가 보인다고 해서, 이미 만들어 둔 dist의 내용까지 바뀌지는 않습니다.

Vite가 정적 산출물을 만들고, preview로 확인한다 — 상태 추적

실제 Vite 소스 변경과 이미 만든 dist 파일/preview의 내용은 독립 상태다. build 전/후 산출물과 실행 주소를 추적해 개발 화면 변경이 기존 dist를 바꾸지 않음을 보여 줄 가치가 있다.

React JavaScript 또는 TypeScript 소스 → Vite production build → dist 파일 집합 → 로컬 preview 확인. digest 기록과 동일 파일 승격·롤백은 별도로 구성하는 릴리스 절차다.

SOURCE / BUILD / DIST / PREVIEW

Vite가 정적 산출물을 만들고, preview로 확인한다

Vite SPA의 기본 빌드는 index.html을 진입점으로 dist 파일을 만든다. 개발 서버와 구분해 실제 산출물을 로컬에서 확인하고, 별도로 구성한 릴리스 절차에서 검증한 파일을 고정한다.

Vite가 정적 산출물을 만들고, preview로 확인한다React JavaScript 또는 TypeScript 소스 → Vite production build → dist 파일 집합 → 로컬 preview 확인. digest 기록과 동일 파일 승격·롤백은 별도로 구성하는 릴리스 절차다.1. React 소스JavaScript / TypeScript2. vite build변환 · 번들 · 최소화3. dist/ 산출물HTML · JS · CSS4. 로컬 preview자산 · 경로 · 기능 확인별도 릴리스 절차검증한 파일 집합 고정
Vite의 소스·산출물·로컬 확인과 별도 릴리스React 소스→vite build→dist→로컬 preview→별도 릴리스 절차의 같은 다섯 노드와 네 간선이다. 마지막 간선은 직접 구성한 절차에서 확인한 산출물을 고정한다는 뜻이며 build나 preview의 자동 배포를 의미하지 않는다.1. React 소스JavaScript / TypeScript2. vite build변환 · 번들 · 최소화3. dist/ 산출물HTML · JS · CSS4. 로컬 preview자산 · 경로 · 기능 확인별도 릴리스 절차검증한 파일 집합 고정

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이나 이미지 최적화를 보장하지 않는다.

이 예의 조건

  • 원도표의 전체 구조와 설명은 위 관계도와 표에서 유지합니다. 아래 인쇄 표에도 원도표의 관계·조건·라벨·설명·주석을 보존합니다.
  • 두 관찰 칸의 위치는 고정입니다. 관찰 상태는 해당 순간의 값이며, 동작·이유는 그 조건에서의 판정과 변화 원인입니다. 독립 비교와 실패 분기는 별도 조건으로 읽고 모든 분기를 한 요청의 필수 실행 순서로 이어 읽지 않습니다.
전체 상태와 변화 근거
장면현재 관찰값설명변화 이유
현재 소스와 distsource: 현재 소스 / dist: 이전 빌드 결과소스 수정 전 만든 dist는 별도 파일 집합이다개발 서버 표시와 preview 입력은 다르다
소스만 수정dev: 현재 소스 화면 / preview: 이전 dist 화면개발 화면은 바뀔 수 있어도 기존 dist는 그대로다저장이 production 산출을 자동 재생성하지 않는다
build 후 previewdist: 새 파일 집합 / preview: 그 산출물 확인production build의 새 dist를 preview에서 확인한다실제 호스팅과 digest 승격은 별도 릴리스 계약이다

Vite가 정적 산출물을 만들고, preview로 확인한다 — 상태 추적

실제 Vite 소스 변경과 이미 만든 dist 파일/preview의 내용은 독립 상태다. build 전/후 산출물과 실행 주소를 추적해 개발 화면 변경이 기존 dist를 바꾸지 않음을 보여 줄 가치가 있다.

React JavaScript 또는 TypeScript 소스 → Vite production build → dist 파일 집합 → 로컬 preview 확인. digest 기록과 동일 파일 승격·롤백은 별도로 구성하는 릴리스 절차다.

SOURCE / BUILD / DIST / PREVIEW

Vite가 정적 산출물을 만들고, preview로 확인한다

Vite SPA의 기본 빌드는 index.html을 진입점으로 dist 파일을 만든다. 개발 서버와 구분해 실제 산출물을 로컬에서 확인하고, 별도로 구성한 릴리스 절차에서 검증한 파일을 고정한다.

Vite가 정적 산출물을 만들고, preview로 확인한다React JavaScript 또는 TypeScript 소스 → Vite production build → dist 파일 집합 → 로컬 preview 확인. digest 기록과 동일 파일 승격·롤백은 별도로 구성하는 릴리스 절차다.1. React 소스JavaScript / TypeScript2. vite build변환 · 번들 · 최소화3. dist/ 산출물HTML · JS · CSS4. 로컬 preview자산 · 경로 · 기능 확인별도 릴리스 절차검증한 파일 집합 고정
Vite의 소스·산출물·로컬 확인과 별도 릴리스React 소스→vite build→dist→로컬 preview→별도 릴리스 절차의 같은 다섯 노드와 네 간선이다. 마지막 간선은 직접 구성한 절차에서 확인한 산출물을 고정한다는 뜻이며 build나 preview의 자동 배포를 의미하지 않는다.1. React 소스JavaScript / TypeScript2. vite build변환 · 번들 · 최소화3. dist/ 산출물HTML · JS · CSS4. 로컬 preview자산 · 경로 · 기능 확인별도 릴리스 절차검증한 파일 집합 고정

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이나 이미지 최적화를 보장하지 않는다.

이 예의 조건

  • 원도표의 전체 구조와 설명은 위 관계도와 표에서 유지합니다. 아래 인쇄 표에도 원도표의 관계·조건·라벨·설명·주석을 보존합니다.
  • 두 관찰 칸의 위치는 고정입니다. 관찰 상태는 해당 순간의 값이며, 동작·이유는 그 조건에서의 판정과 변화 원인입니다. 독립 비교와 실패 분기는 별도 조건으로 읽고 모든 분기를 한 요청의 필수 실행 순서로 이어 읽지 않습니다.
전체 상태와 변화 근거
장면현재 관찰값설명변화 이유
현재 소스와 distsource: 현재 소스 / dist: 이전 빌드 결과소스 수정 전 만든 dist는 별도 파일 집합이다개발 서버 표시와 preview 입력은 다르다
소스만 수정dev: 현재 소스 화면 / preview: 이전 dist 화면개발 화면은 바뀔 수 있어도 기존 dist는 그대로다저장이 production 산출을 자동 재생성하지 않는다
build 후 previewdist: 새 파일 집합 / preview: 그 산출물 확인production build의 새 dist를 preview에서 확인한다실제 호스팅과 digest 승격은 별도 릴리스 계약이다

위 그림은 Vite가 정적 산출물을 만들고 preview로 확인하는 흐름을 보여 줍니다. 그림의 요약처럼 Vite SPA의 기본 빌드는 index.html을 진입점으로 dist 파일을 만들며, 개발 서버와 구분해 실제 산출물을 로컬에서 확인하고, 따로 구성한 릴리스 절차에서 검증한 파일을 고정합니다. 순서는 JavaScript나 TypeScript로 쓴 React 소스, 변환·번들·최소화를 하는 vite build, HTML·JS·CSS로 이루어진 dist/ 산출물, 자산과 경로, 기능을 확인하는 로컬 preview이며, 마지막의 별도 릴리스 절차는 검증한 파일 집합을 고정하는 단계입니다. 그림의 캡션이 밝히듯 이 마지막 화살표는 직접 구성한 절차를 뜻할 뿐, build나 preview가 자동으로 배포한다는 뜻이 아닙니다.

그림 아래의 네 칸은 단계마다 확인할 것을 정리합니다. 입력으로는 React 소스와 스타일, public 파일, 커밋과 lockfile, 빌드 설정을 함께 관리하며, TypeScript는 선택 사항이고 Vite 8은 Rolldown 기반으로 번들링합니다. 기본 출력은 dist/로, index.html과 해시가 붙은 JS·CSS 자산, 필요하면 동적 import의 청크가 만들어지고, public/ 파일은 그대로 복사되므로 robots.txt는 원본이 있을 때만 들어갑니다. 확인 단계에서는 npm run preview나 serve -s dist로 파일을 서빙해 base와 자산 경로, 공개 환경 값, 대표적인 사용자 흐름을 보며, vite preview는 운영 서버가 아니므로 호스트의 깊은 URL 재작성은 따로 확인합니다. 릴리스 단계에서는 검증한 파일마다 digest를 기록합니다. digest는 SHA-256 같은 해시 함수로 파일 내용에서 계산한 값으로, 내용이 한 바이트만 달라도 사실상 다른 값이 나옵니다. 그리고 다시 빌드하지 않고 검증한 바로 그 파일을 운영 환경으로 옮기는 승격(promotion) 절차를 마련하며, HTML의 재검증과 해시 자산의 장기 캐시, 이전 청크의 보존과 롤백 정책도 함께 구성합니다. 그림의 마지막 설명처럼 VITE_로 시작하는 환경 값은 클라이언트 번들에 노출되고, build와 preview는 비밀 저장소나 자동 배포·롤백 도구가 아니며, 브라우저 target에 맞춘 변환이 모든 Web API의 polyfill이나 이미지 최적화를 보장하지도 않습니다.


왜 빌드를 해야 하는가?

개발하는 동안에는 npm run dev로 개발 서버를 실행했습니다. 개발 서버는 코드를 고치면 바로 반영하는 HMR(Hot Module Replacement) 같은 기능으로 개발 속도를 높이고, 소스 맵(Source Map)처럼 디버깅에 필요한 정보를 담고 있으며, 빠른 수정과 디버깅을 위한 방식으로 모듈을 제공합니다. 그래서 개발 서버의 응답을 프로덕션 빌드 산출물과 같은 파일로 보지는 않습니다.

반면 프로덕션 환경에 배포하기 위한 빌드(Build)는 다른 목표를 가집니다. JavaScript와 CSS, HTML을 최소화(Minification)해 파일 크기를 줄이고 개발용 코드를 없애며, 여러 작은 파일을 하나 또는 몇 개의 파일로 묶는 번들링으로 브라우저의 네트워크 요청 수를 줄입니다. 설정한 build target에 맞춰 JavaScript 문법도 변환하지만, Vite의 기본 빌드가 모든 구형 브라우저나 새 Web API의 polyfill까지 보장하지는 않습니다. 코드 분할 같은 방법으로 처음 로딩의 비용을 줄일 수 있으며, 이미지의 압축이나 형식 변환은 Vite가 저절로 해 주는 일이 아니므로 별도의 도구나 서비스가 필요합니다. 결국 빌드는 웹 서버가 그대로 서빙할 수 있는 HTML, CSS, JavaScript, 이미지 같은 정적 파일을 만들어, 개발한 애플리케이션을 사용자에게 빠르고 안정적으로 제공하기 위한 꼭 필요한 단계입니다.


Vite 기반 프로젝트 빌드하기

지금 React 실무에서는 Vite 기반 프로젝트가 널리 쓰입니다. Vite는 명령 하나로 프로덕션 빌드를 만들 수 있고, 개발과 빌드가 빠르며 설정을 넓히기도 간결합니다. React 프로젝트의 루트 디렉터리에서 다음 명령을 실행합니다.

npm run build
# 또는
yarn build

이 명령을 실행하면, 이 글의 기준인 Vite 8은 Rolldown 기반의 번들링을 거쳐 프로젝트 루트에 dist 폴더를 만듭니다(Vite 문서의 프로덕션 빌드).

dist 폴더의 내용 살펴보기

기본 설정으로 빌드하면 프로젝트 루트에 dist/가 생깁니다. 아래는 구성의 예이며, robots.txt는 public/ 같은 곳에 원본이 있을 때만 복사됩니다. TypeScript는 선택 사항이고 JavaScript 소스도 그대로 빌드할 수 있습니다.

index-<hash>.css # CSS 파일 (최소화 및 해싱)
index-<hash>.js # JavaScript 파일 (최소화, 번들링, 해싱)
<이름>-<hash>.js # 코드 분할로 나뉜 청크 파일 (필요 시)
...
index.html # 앱의 진입점 역할을 하는 HTML 파일
robots.txt # 검색 엔진 크롤러 제어

index.html은 애플리케이션의 단일 진입점으로, 이 파일을 불러오면 그 안에 연결된 JavaScript 파일이 실행되어 React 앱이 렌더링됩니다. assets/에는 빌드된 CSS와 JavaScript, 이미지 같은 정적 리소스가 해시가 붙은 파일 이름으로 저장됩니다. Vite는 index-<hash>.js처럼 이름 뒤에 내용에서 계산한 해시 값을 붙이므로, 내용이 바뀐 자산에는 새 URL이 생겨 장기 캐시를 쓸 수 있습니다. 다만 최신 HTML을 다시 확인하는 정책과 이전 청크를 얼마나 남길지 같은 배포 정책도 함께 맞아야 합니다.

빌드 설정에 따라 JavaScript와 CSS를 최소화하고 모듈을 묶지만, 동적 import와 출력 설정에 따라 여러 청크가 생길 수 있으므로 모든 코드가 반드시 하나의 파일이 되는 것은 아닙니다. 동적 import(import())를 기준으로 청크를 나누면 처음 로딩의 비용을 줄일 수 있습니다. Vite의 기본 템플릿은 서비스 워커를 저절로 만들지 않으므로, PWA가 필요하다면 vite-plugin-pwa 같은 플러그인을 더해 직접 설정합니다.


빌드된 앱을 로컬에서 테스트하기

이 장의 클라이언트 SPA 빌드는 정적 서버로 서빙할 수 있습니다. 다만 BrowserRouter의 깊은 URL을 주소창으로 직접 열려면, 서버가 앱의 경로를 index.html로 돌려주는 재작성(rewrite) 설정도 필요합니다. 로컬에서 빌드된 앱을 시험할 때는 간단한 정적 파일 서버를 쓸 수 있으며, 흔한 방법은 serve 패키지입니다. 먼저 serve를 설치합니다. 프로젝트 단위로 쓰려면 -g 없이 npm install serve로 설치한 뒤 npx serve로 실행합니다.

npm install -g serve
# 또는 Yarn 1(Classic)이라면
yarn global add serve

serve는 폴더의 파일을 그대로 내주는 작은 HTTP 서버입니다. 빌드한 index.html을 더블클릭해 file:// 주소로 열면 /assets/...처럼 사이트 루트를 기준으로 연결된 자산을 찾지 못하는 등 실제 배포와 다르게 동작할 수 있으므로, 이렇게 HTTP 서버로 확인합니다. 그다음 프로젝트 루트 디렉터리에서 dist 폴더를 서빙합니다.

serve -s dist
# 또는 전역 설치 없이 실행
npx serve -s dist
# Yarn 2 이후에는 yarn global이 없으므로 설치 없이 실행
yarn dlx serve -s dist

이 명령은 dist 폴더의 내용을 정적 파일 서버로 제공하고, 터미널에 나온 로컬 주소(http://localhost:<PORT>)로 들어갈 수 있게 해 줍니다. -s는 찾을 수 없는 경로를 index.html로 돌려주는 단일 페이지 앱 모드입니다. Vite의 기본 프리뷰를 쓰려면 npm run preview를 실행하며, 기본 주소는 http://localhost:4173입니다.

로컬 서버로 빌드된 앱에 들어가 모든 기능이 제대로 동작하는지, 스타일이 깨지지 않는지를 마지막으로 확인합니다. 빌드된 앱에서는 개발 서버와 달리 콘솔에 개발용 경고가 줄어든 것도 볼 수 있습니다. 빌드 결과를 확인할 때는 실제 배포 경로와 자산, 공개 환경 값을 함께 점검해야 하며, 그림의 digest 고정과 같은 바이트의 승격은 릴리스 절차일 뿐 vite build나 preview가 저절로 검증과 배포, 롤백을 해 준다는 뜻은 아닙니다.

빌드 전후를 한 번 따라가기

먼저 프로젝트의 package.json에서 build와 preview가 각각 Vite의 빌드·프리뷰 명령으로 연결되어 있는지 확인합니다. 아래 절차는 독자의 실습 프로젝트에서 하며, 호스팅 서비스에 올리거나 공개하는 단계는 아닙니다.

App의 화면 문구를 “빌드 확인 A”로 정해 저장한 뒤 빌드하고, 명령이 성공했는지와 dist/index.html을 확인합니다. 그 HTML이 참조하는 assets의 JS와 CSS 파일이 실제로 있는지도 찾아보며, 해시 값은 프로젝트마다 다르므로 위의 예시 이름과 같을 필요는 없습니다. 이어서 npm run preview로 프리뷰를 실행해 표시된 로컬 주소에서 A를 확인합니다. 프리뷰는 지금의 dist를 확인하는 로컬 서버일 뿐 운영 서버로 쓰는 명령이 아니므로, 첫 화면만 보지 말고 링크와 입력, 깊은 앱 경로의 새로고침도 확인합니다.

마지막으로 소스를 “빌드 확인 B”로 바꾸어 저장하되 아직 다시 빌드하지 않습니다. 이때 개발 서버에는 B가, 프리뷰에는 A가 보일 수 있습니다. 프리뷰는 이전에 만든 dist를 서빙하기 때문입니다. 다시 빌드한 뒤 프리뷰를 새로 확인하면 B가 반영됩니다. Vite의 정적 배포 안내도 build와 dist, preview의 역할을 나누어 설명합니다. 정적 파일은 브라우저가 그대로 읽을 수 있으므로, 빌드에 포함되는 공개 환경 값에는 비밀 키를 넣지 않으며, 비밀이 필요한 작업은 서버 쪽에서 따로 처리합니다.


빌드 설정 바꾸기 (고급)

Vite는 vite.config.js(TypeScript 템플릿이라면 vite.config.ts)로 빌드 동작을 직접 제어할 수 있습니다. Vite 8에서는 build.outDir, build.sourcemap, build.rolldownOptions로 출력 경로와 소스 맵, 번들 옵션을 다룹니다. @vitejs/plugin-react나 vite-plugin-pwa 같은 플러그인으로 JSX 처리와 PWA, 압축, 분석 기능을 조합할 수도 있습니다. SPA가 중심이라면 Vite가 알맞고, 서버 렌더링이나 풀스택 라우팅이 핵심이라면 Next.js 같은 프레임워크가 더 알맞을 수 있습니다. 특별히 바꿀 이유가 없다면 Vite의 기본 빌드 설정을 유지하는 것이 가장 안전합니다.

더 깊이: Vite 8의 기본 빌드 도구와 브라우저 대상

Vite 8의 빌드 옵션 문서를 보면, 번들링은 Rolldown이, JavaScript의 변환과 최소화는 Oxc가, CSS의 최소화는 Lightning CSS가 기본으로 맡습니다. 그래서 예전 자료의 build.rollupOptions는 지금 build.rolldownOptions의 사용 중단된 별칭으로만 남아 있고, build.minify의 기본값도 terser가 아니라 Oxc 최소화기입니다. 문서는 Oxc 최소화기가 terser보다 30배에서 90배 빠르다고 소개합니다.

build.target의 기본값은 'baseline-widely-available'이라는 특별한 값입니다. 이 값은 2026년 1월 1일 기준으로 Baseline Widely Available에 해당하는 브라우저 버전, 곧 ['chrome111', 'edge111', 'firefox114', 'safari16.4', 'ios16.4']를 뜻합니다. Vite는 이 대상에 맞춰 문법을 변환하며, Oxc가 안전하게 바꿀 수 없는 기능이 코드에 있으면 빌드할 때 경고를 출력합니다. 이보다 오래된 브라우저까지 지원해야 한다면 이 기본값에 기대지 말고 대상을 직접 정합니다.


정리

  • 빌드는 개발 코드를 최소화하고 묶어 웹 서버가 그대로 서빙할 수 있는 정적 파일로 만드는 과정이며, 개발 서버의 응답과는 다른 산출물입니다.
  • npm run build로 만든 dist에는 index.html과 해시가 붙은 JS·CSS 자산이 들어가고, public/의 파일은 그대로 복사됩니다.
  • npm run preview나 serve -s dist로 산출물을 로컬에서 확인하되, 이것은 운영 서버가 아니며 호스트의 경로 재작성은 따로 확인합니다.
  • 소스를 고친 뒤 다시 빌드하지 않으면 프리뷰에는 이전 dist가 보입니다.
  • VITE_ 환경 값은 클라이언트 번들에 노출되므로 비밀 키를 넣지 않습니다.

연습 문제

1. 두 버전의 파일

버전 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 주소, 호스트의 재작성까지 확인해 주지는 않습니다. Network 탭에서 실패한 자산의 URL과 상태, 응답의 종류를 보고 배포한 파일 목록과 대조합니다. 해시가 붙은 이름이 있다고 원자적 배포나 자동 롤백이 갖춰지는 것도 아닙니다.

2. 개발 서버와 프리뷰의 차이

소스의 문구를 “빌드 확인 B”로 바꾸어 저장했지만 다시 빌드하지 않았습니다. 개발 서버와 npm run preview는 각각 어떤 문구를 보여 줄까요? B를 프리뷰에서 보려면 무엇을 해야 할까요?

해설 보기

개발 서버는 소스 파일을 바로 읽어 변환하므로 B를 보여 주고, 프리뷰는 이전에 만든 dist를 서빙하므로 A를 보여 줍니다. B를 프리뷰에서 보려면 npm run build로 dist를 다시 만든 뒤 프리뷰를 다시 확인합니다.

3. 깊은 경로의 새로고침

React Router의 BrowserRouter를 쓰는 앱을 빌드해 /posts/1에서 새로고침했습니다. serve -s dist와, -s 없이 serve dist로 서빙한 경우는 어떻게 다를까요?

해설 보기

-s를 주면 서버가 dist에 없는 /posts/1 경로를 index.html로 돌려주므로, 앱이 다시 실행되어 React Router가 그 경로의 화면을 그립니다. -s 없이 서빙하면 dist/posts/1이라는 파일이 없으므로 서버가 404 같은 응답을 돌려주어 앱이 실행되지 않을 수 있습니다.

실제 호스팅에서도 같은 문제가 생기므로, 서비스마다 SPA 경로를 index.html로 돌려주는 재작성 설정을 따로 해야 합니다. 이는 다음 글에서 다룹니다.

다음 글 정적 호스팅 배포에서는 빌드 산출물을 정적 호스팅 서비스에 올리고, Git 연동 자동 배포와 SPA 경로의 새로고침 문제를 해결하는 방법을 알아봅니다.