
React + TypeScript 기반 사내 대시보드의 프론트엔드 빌드 시스템을 Webpack에서 Vite로 전환했다. 이 프로젝트는 다음과 같은 특징을 가진, 마이그레이션 난이도가 낮지 않은 구조였다:
CRA(react-scripts) 잔재 + 커스텀 Webpack 설정이 혼재 — react-scripts, react-app-rewired를 devDependencies로 두고 있으면서, 동시에 webpack.config.js(공통) / webpack.dev.js / webpack.prod.js 등 커스텀 설정 파일을 직접 운용
7개의 배포 환경이 각각 별도 빌드 스크립트로 관리됨
jQuery 기반 레거시 라이브러리(daterangepicker, slick-carousel) 사용
Sentry 소스맵 업로드가 Webpack 플러그인에 강하게 결합
Kotlin/Gradle 백엔드와 같은 저장소에서 프론트엔드를 빌드하고, 결과물을 Thymeleaf 템플릿(index.html)으로 서빙하는 구조
Webpack 기반 빌드/HMR 속도 개선
CRA 의존성(구버전 TypeScript 강제, 느린 재시작)에서 벗어나기
최신 프론트엔드 생태계(Vite 플러그인 생태계) 활용

CRA 관례상 public/index.html에 있던 파일을 루트로 이동 시켰음. vite는 <script 태그> 직접 파싱해서 진입점 인식하기 때문에 HtmlWebpackPlugin이 자동으로 넣어주던것과 달리 엔트리 스크립트 태그를 ㅜ동으로 추가.
Thymeleaf 속성은 Vite의 파서가 손대지않고 그대로 통과시킴
Typescript 설정변경 : moduleResolution bundler로 변경
최신 패키지들은 package.json의 exports 필드로 타입 경로를 지정하는데 moduleResoluton: node 는 ㅇ ㅣ필드를 무시해서 타입선언을 못찾는 문제.
daterangepicker가 내부적으로 window.moment, window.$를 참조하는 구조라 vite 환경에서 별도 전역 할당이 필요했음.
마크업 팀에서 넘어온 css 파일에 실제로 존재하지 않는 .map 파일을 가리키는 주석이 남아 콘솔 경고 발생
vite 플러그인 파일에서 load ㅜㄱ에서 파일을 직접 읽어 주석 제거한 문자열 반환하도록 해결
swiper/swiper-react → swiper/react (swiper 버전업에 따른 export 경로 변경)
sentry.config.js: CommonJS(module.exports) → ESM(export default) 전환 (Vite/ESM 환경에서 default import 호환을 위해)