본문으로 건너뛰기
← Journal
웹 개발 / 배포 운영

작성: COZYGONO 개발·편집팀 · 수정:

배포했더니 화면이 하얗게: MIME 타입 오류가 알려준 것

주소는 열리는데 본문이 비어 있고, 뒤로 가기를 눌러도 그대로였습니다. 콘솔에 남은 한 줄이 원인을 정확히 가리키고 있었습니다.

VISUAL NOTE 08 · SPA DEPLOYMENT CACHE & PRERENDER DEFENSEno-cache HTML + immutable Hashed Assets + Prerendered DOM
1층 · HTTP 캐시 분리진입 HTML vs 해시 번들

진입 HTML은 항상 최신 해시를 가리키도록 no-cache로 두고, /assets/* 해시 파일만 1년 장기 캐시합니다.

2층 · 빌드 시점 프리렌더초기 HTML에 본문·계산기 포함

자바스크립트 실행 전에도 모든 공개 경로의 본문과 계산 엔진 초기 결과가 HTML 안에 완성된 상태로 내려갑니다.

3층 · 런타임 복구모듈 로드 실패 감지 & 404

청크 불일치 발생 시 1회 자동 새로고침으로 최신 번들을 받아오고, 정의되지 않은 경로는 전용 404 화면으로 안내합니다.

배포 운영 노트에서 한 건만 옮깁니다. 원인이 둘이었고, 둘 다 흔한 구성에서 생깁니다.

1. 증상

사이트의 특정 주소로 들어가면 상단 메뉴와 하단 푸터는 보이는데 가운데 본문이 완전히 비었습니다. 새로고침해도, 뒤로 가기를 눌러도 마찬가지였습니다. 서버 응답 코드는 200이었습니다.

2. 첫 번째 원인: 없는 주소를 위한 자리가 없었다

싱글 페이지 애플리케이션은 주소마다 보여 줄 화면을 목록으로 갖고 있습니다. 그런데 목록의 어디에도 걸리지 않는 주소가 들어오면, 라우터는 아무것도 렌더링하지 않습니다. 오류를 내는 것이 아니라 조용히 빈 화면을 그립니다.

오타가 섞인 주소나 예전 링크가 딱 이 경우였습니다. 어디에도 매칭되지 않는 주소를 위한 404 화면을 만들고, 목록 맨 끝에 "그 외 모든 주소"를 받는 자리를 두어 해결했습니다.

3. 두 번째 원인: 콘솔에 남은 한 줄

그런데 배포본에서는 404 화면조차 뜨지 않았습니다. 콘솔을 열어 보니 이렇게 적혀 있었습니다.

Failed to load module script: Expected a JavaScript-or-Wasm module script but the server responded with a MIME type of "text/html"

자바스크립트를 요청했는데 HTML을 받았다는 뜻입니다. 경위는 이렇습니다.

  • 빌드할 때마다 자바스크립트 파일 이름에 새 해시가 붙습니다.
  • 그런데 진입 HTML이 브라우저에 캐시되어 있었습니다. 유효기간은 한 시간이었습니다.
  • 캐시에 남은 옛 HTML은 이미 삭제된 파일 이름을 가리킵니다.
  • 그 파일을 요청하면 서버에는 없으니, "모든 주소를 진입 HTML로 넘긴다"는 규칙이 걸려 HTML이 돌아옵니다.
  • 브라우저는 자바스크립트 자리에 온 HTML을 거부합니다.

결과적으로 프레임워크 자체가 시작되지 못합니다. 앱 안에 만들어 둔 오류 처리 장치는 이 시점에 아무 소용이 없습니다. 코드가 한 줄도 실행되지 않았기 때문입니다.

4. 세 겹으로 막기

- 서버: 진입 HTML은 매번 최신을 확인하도록 하고, 이름에 해시가 붙는 파일만 장기 캐시로 돌렸습니다. - HTML: 화면이 채워지기 전에도 빈 흰 화면이 보이지 않도록 진입 HTML 안에 로딩 화면을 미리 넣었습니다. 일정 시간이 지나도 앱이 시작되지 않으면 한 번만 다시 불러오고, 그래도 실패하면 안내 문구와 버튼을 보여 줍니다. - 앱: 앱이 뜬 뒤에 생기는 오류는 기존 오류 처리 장치가 받습니다.

5. 설정 하나에서 걸린 함정

캐시 규칙을 넣을 때 자산 규칙을 먼저 쓰고 전체 규칙을 나중에 썼더니, 자바스크립트와 CSS까지 캐시가 꺼져 버렸습니다. 사용하던 호스팅은 여러 규칙이 겹칠 때 마지막에 매칭된 것이 이기는 방식이었습니다. 넓은 규칙을 먼저, 구체적인 규칙을 나중에 두어야 했습니다.

배포 후에는 추측하지 말고 응답 헤더를 직접 확인하는 편이 빠릅니다. 실제로 확인해 보고서야 순서가 뒤집혔다는 것을 알았습니다.

5. 화면 복구와 본문 전달은 다른 점검이다

2026년 9월 4일 홈페이지를 다시 확인했을 때 브라우저에서는 글이 열렸지만 최초 HTML에는 로딩 문구만 있었습니다. 그래서 공개 페이지의 React 본문을 빌드 때 HTML로 함께 생성하는 방식으로 개선했습니다. 글 URL의 제목·설명·canonical도 같은 콘텐츠 데이터에서 만듭니다.

점검은 두 단계로 나눕니다. 먼저 JavaScript를 실행하지 않는 HTTP 응답에서 글 제목과 본문을 찾습니다. 다음으로 브라우저에서 같은 URL을 직접 열고 메뉴 이동과 언어 전환을 확인합니다. 정적 본문이 있다는 이유만으로 동작 검증을 생략하거나, 브라우저가 정상이라는 이유만으로 최초 응답을 확인하지 않는 실수를 피하려는 것입니다. 이 개선은 소스와 로컬 빌드에 적용하며 실제 운영 반영 여부는 배포 후 확인해야 합니다.