
안녕하세요! 방구석에서 코딩이라는 무기로 저만의 자본주의 파이프라인을 개척하고 있는 1인 개발자입니다.
지난 7편과 8편에서 제 노트북 속에 있던 코드를 전 세계로 배포하고, 예쁜 썸네일까지 달아주는 마케팅 과정을 정말 신나게 이야기했었죠. 글만 보면 아주 순조롭게 탄탄대로를 걸어온 것 같지만... 사실 배포 버튼을 누르던 그 이면에는 제 심장을 철렁 내려앉게 만들었던 아주 무시무시한 에러와의 사투가 숨어있었습니다.
오늘은 제가 Netlify에 웹사이트를 배포하다가 마주친, 화면을 붉게 물들였던 공포의 Vite 배포 에러 해결기를 적어보려고 합니다. 아마 지금 이 글을 읽고 계신 분들 중 상당수는 구글에 저 길고 긴 에러 메시지를 복사해서 검색하다가 들어오셨을 겁니다. 너무 걱정하지 마세요. 아주 허무할 정도로 쉽고 완벽한 해결책을 제가 떠먹여 드리겠습니다!
"내 컴퓨터에선 잘 됐는데 왜 이래!" - 공포의 빨간 맛 로그
Github 연동을 마치고 넷플리파이에서 호기롭게 'Deploy Site(배포하기)' 버튼을 눌렀을 때였습니다. 평소 같으면 빙글빙글 돌다가 초록색으로 "Site is live"가 떠야 하는데, 갑자기 화면이 시뻘게지더니 터미널 창에 이런 무시무시한 에러 로그가 폭포수처럼 쏟아지기 시작했습니다.
8:31:21 AM: ✗ Build failed in 36ms
8:31:21 AM: error during build:
8:31:21 AM: [vite:build-html] Failed to resolve /assets/index-DQz0AbIk.js from /opt/build/repo/index.html
8:31:21 AM: file: /opt/build/repo/index.html
8:31:21 AM: "build.command" failed
8:31:21 AM: Command failed with exit code 1: npm run build
8:31:21 AM: Build failed due to a user error: Build script returned non-zero exit code: 2
개발자들이 가장 싫어하는 문장 1위, 바로 "Build failed(빌드 실패)"입니다. 아니, 제 노트북 터미널(VS Code)에서 개발 서버를 돌렸을 때는 아무 문제 없이 화면이 쌩쌩하게 잘 돌아갔거든요? 그런데 왜 서버에만 올리려고 하면 안 된다고 파업을 선언하는 걸까요? 등줄기에 식은땀이 흘렀지만, 개발자의 기본 소양은 에러 메시지를 찬찬히 읽어보는 것입니다. 쏟아진 에러 로그 중에서 가장 핵심이 되는 범인은 바로 이 문장이었습니다.
Failed to resolve /assets/index-DQz0AbIk.js from /opt/build/repo/index.html
해석하자면, "Vite야, 내가 index.html 파일을 열어봤는데, 거기 적혀있는 저 복잡한 이름의 assets/index-....js 파일을 도저히 못 찾겠어!"라며 뻗어버린 겁니다.

범인은 '나'였다: 원본 코드를 덮어써버린 치명적 실수
원인을 찾기 위해 제 프로젝트의 최상위 폴더(Root)에 있는 index.html 파일을 열어보았습니다. 그리고 파일 맨 아래쪽에서 아주 기가 막힌 코드를 발견하게 됩니다.
<!-- 에러가 났던 당시 제 index.html의 끔찍한 모습 -->
<body>
<div id="root"></div>
<script type="module" crossorigin src="/assets/index-DQz0AbIk.js"></script>
</body>
아차! 이 코드를 보자마자 이마를 탁 쳤습니다. 사실 저 <script> 태그 안에 있는 /assets/... 경로는 제가 개발할 때 쓴 코드가 아닙니다. 개발을 다 끝내고 npm run build를 돌리면, Vite가 코드를 싹 다 압축해서 dist (결과물) 폴더 안에 자동으로 만들어주는 일종의 완성품 이름이거든요. 사건의 전말은 이렇습니다. 제가 예전에 배포 세팅을 이리저리 만지다가, 혹은 썸네일(OG 태그)을 추가한다고 복사 붙여넣기를 하다가... 실수로 dist 폴더 안에 있는 '이미 빌드된 결과물 index.html' 코드를 복사해서, 제 프로젝트 최상위 경로에 있는 '개발용 원본 index.html'에 통째로 덮어씌워 버린 겁니다.
Vite 입장에서는 정말 황당했을 겁니다. "이제부터 코드들을 압축해서 조립해 볼까~" 하고 원본 index.html을 딱 열었는데, 아직 만들지도 않은 /assets/... 파일이 떡하니 내놓으라고 적혀 있으니 "어? 아직 assets 폴더 안 만들었는데 이 파일이 어디 있지?" 하면서 길을 잃고 뻗어버린 것이죠.
허무할 정도로 완벽한 해결책: 원본으로 되돌려라
원인을 알았으니 해결은 3초면 충분합니다. 꼬여버린 스크립트 태그를 원래 Vite가 처음에 만들어주었던 순수한 '개발용 진입점(Entry point)'으로 되돌려주기만 하면 됩니다.
프로젝트 최상위 폴더에 있는 index.html 파일을 열고, <body> 태그 안쪽에 있는 이상한 스크립트 줄을 싹 지운 다음, 아래의 코드로 완벽하게 교체해 줍니다.
👉 해결 코드:
<body>
<div id="root"></div>
<!-- 핵심 수정 사항: assets가 아닌 원본 src 폴더의 main을 가리켜야 합니다! -->
<script type="module" src="/src/main.jsx"></script>
</body>
(참고: 만약 프로젝트에서 jsx가 아니라 js 확장자를 쓰신다면 /src/main.js 로 적어주시면 됩니다!)
이렇게 코드를 원상 복구한 뒤에 파일 저장을 꾹 누릅니다. 그리고 깃허브에 코드를 새로 Push(업로드) 했습니다.

붉은 에러 뒤에 찾아오는 짜릿한 초록불의 쾌감
넷플리파이 화면을 띄워놓고 손에 땀을 쥐며 지켜보았습니다. "Building..." 글씨가 돌기 시작하더니, 아까는 36밀리초 만에 새빨간 에러를 뱉어내던 녀석이 스무스하게 다음 단계로 넘어가더라고요.
그리고 마침내 터미널 창에 ✓ built in 1.25s 라는 눈부시게 아름다운 초록색 체크 마크가 떴습니다! 이어서 넷플리파이에도 "Published"라는 메시지가 뜨며 배포가 100% 완벽하게 성공했습니다.
혼자 코딩을 독학하고 사이드 프로젝트를 만들다 보면, 이런 붉은색 에러 로그 앞에서 멘탈이 붕괴될 때가 정말 많습니다. 영어로 된 에러 메시지가 마치 나를 꾸짖는 것 같아 무섭기도 하죠. 하지만 이번 경험을 통해 다시 한번 깨달았습니다. 컴퓨터는 거짓말을 하지 않으며, 에러 메시지는 나를 괴롭히는 적이 아니라 정답으로 가는 길을 정확히 가리키고 있는 아주 친절한 내비게이션이라는 사실을요.
혹시 저처럼 Failed to resolve /assets/... 에러의 늪에 빠져 이 글을 찾아오신 분이 계신다면, 당장 여러분의 index.html 파일로 달려가서 <script> 태그를 확인해 보세요. 분명 1분 만에 쾌재를 부르며 해결하실 수 있을 겁니다!
자, 이제 진짜 진짜 프로젝트의 끝이 보입니다. 로직도 완벽하고 배포도 완벽한데... 제 핸드폰으로 사이트를 열어보니 화면비율이 살짝 묘하게 찌그러져 있네요?
다음 10편, 이 기나긴 메이킹 로그 시리즈의 대장정을 마무리하는 [올인원 배당 파이어족 은퇴 시뮬레이터 메이킹 로그 #10] 모바일 반응형 깨짐 현상과 슬라이더 터치 오류 해결기로 돌아오겠습니다. 마지막까지 함께해 주세요!
[올인원 배당 파이어족 은퇴 시뮬레이터 메이킹 로그 #10] 모바일 반응형 깨짐 현상과 슬라이더
안녕하세요! 방구석에서 시작한 작은 아이디어를 세상에 쏘아 올린 1인 개발자입니다.드디어 길고 길었던 [파이어족 은퇴 시뮬레이터] 메이킹 로그 시리즈의 마지막, 10편에 도착했습니다! 지난
code-bricks.tistory.com