React + Vite 프로젝트를 개발하던 중, 다음과 같이 이미지 경로를 설정했다.
// ChuViewer.tsx (초기 코드)
const chuImagePath = `/src/assets/images/chu/happy/${mainChu.lang}.png`;
const backgroundImagePath = `/src/assets/images/backgrounds/${mainChu.background}.png`;
로컬에서는 됐지만, 배포 환경에서 경로가 깨지는 현상이 있었다.
Vite 개발 서버는 /src/...
경로를 파일 시스템 기준으로 직접 매핑해줬다. 그래서 개발 중에는 위 코드가 동작했다.
그러나 빌드 시 Vite는 src/assets
의 파일을 dist/assets
로 복사하면서 해시 파일명으로 변환했다.
예시:
happy/en.png → happy/en.4a6c21ef.png
코드에 남아 있던 /src/...
경로는 빌드 후 실제 파일 위치와 일치하지 않았고, 그 결과 배포 환경에서 자산을 찾지 못했다.
new URL(..., import.meta.url)
동적으로 구성되는 자산 경로에는 Vite가 빌드 타임에 추적·치환할 수 있는 문법을 사용했다.
new URL(path, import.meta.url).href
를 사용하니 빌드 시 해시가 반영된 실제 경로로 자동 변환됐다.
// 수정된 ChuViewer.tsx
const chuImagePath = new URL(
`../../assets/images/chu/happy/${mainChu.lang}.png`,
import.meta.url
).href;
const backgroundImagePath = new URL(
`../../assets/images/backgrounds/${mainChu.background}.png`,
import.meta.url
).href;
이렇게 수정하니:
import.meta.glob
로 폴더 일괄 매핑여러 개의 이미지를 조건에 따라 불러와야 하는 경우, import.meta.glob
를 사용하면 폴더 전체를 객체 형태로 매핑할 수 있었다.
이 방법은 반복적인 new URL
작성 없이도 모든 이미지를 한 번에 불러올 수 있었다.
// chu 폴더 내 모든 이미지 매핑
const chuImages = import.meta.glob('../../assets/images/chu/happy/*.png', {
eager: true,
import: 'default',
});
// backgrounds 폴더 내 모든 이미지 매핑
const backgroundImages = import.meta.glob('../../assets/images/backgrounds/*.png', {
eager: true,
import: 'default',
});
// 사용 예시
const chuImagePath =
chuImages[`../../assets/images/chu/happy/${mainChu.lang}.png`];
const backgroundImagePath =
backgroundImages[`../../assets/images/backgrounds/${mainChu.background}.png`];
eager: true
로 즉시 로드되도록 했다.import: 'default'
로 URL 문자열만 가져오도록 했다.new URL
vs import.meta.glob
구분 | new URL(..., import.meta.url) | import.meta.glob |
---|---|---|
쓰임새 | 개별 파일 경로를 동적으로 구성할 때 | 폴더 전체를 일괄 매핑해 키로 접근할 때 |
코드 양 | 파일마다 1줄씩 선언 | 폴더당 1번 선언 후 재사용 |
타입 안전성 | 문자열 경로 조합 중심 | 매핑된 키 집합이 고정돼 비교적 안전 |
빌드 추적 | 명시적 URL로 확실히 추적됨 | 글로브 패턴으로 폴더 단위 추적 |
런타임 비용 | 매우 낮음 | eager 사용 시 초기에 메모리 로드 증가 가능 |
지연 로드 | 기본 없음 | eager: false 로 분할/지연 로드 가능(동적 import) |
유지보수 | 소량 자산에 단순 | 다수 자산, 스킨/테마처럼 목록 접근에 유리 |
new URL
이 가장 직관적이다.import.meta.glob
가 깔끔하다.import.meta.glob
에서 eager: false
로 코드 스플리팅을 활용한다.// 지연 로드(코드 스플리팅) 예시
const chuImages = import.meta.glob('../../assets/images/chu/happy/*.png'); // eager 미사용
async function getChuImage(lang: string) {
const loader = chuImages[`../../assets/images/chu/happy/${lang}.png`];
if (!loader) return null;
const mod = await loader(); // 동적 import
return mod.default as string; // 해시 반영된 URL
}
/src/...
직접 경로 표기는 개발 서버에서만 우연히 동작했다.- 빌드 후에는 자산 파일명이 해시로 변경되므로, 빌드 타임에 치환 가능한 방식이 필요했다.
- 동적 이미지 경로 →
new URL(..., import.meta.url).href
- 여러 이미지 일괄 로드 →
import.meta.glob
- 지연 로드/코드 스플리팅이 필요하면
import.meta.glob
에서eager
를 생략해 동적 import로 처리했다.