Import Maps — 빌드 없이 브라우저에서 bare specifier 사용하기
브라우저 네이티브 Import Maps API로 bare specifier를 URL에 매핑하는 방법, scopes·integrity 필드, 폴리필 패턴까지 정리합니다.
지난 글에서 번들러가 사용하지 않는 코드를 제거하는 트리 쉐이킹을 살펴봤습니다. 그런데 번들러 없이, 브라우저가 직접 "react" 같은 짧은 경로를 실제 URL로 변환할 수 있다면 어떨까요? Import Maps는 바로 그 문제를 해결하는 브라우저 네이티브 기능입니다.
bare specifier 문제
ES 모듈을 브라우저에서 직접 사용하려면 경로가 항상 명확해야 합니다.
// 브라우저: 불가 — bare specifier
import _ from 'lodash';
// 브라우저: 가능 — 상대·절대 URL
import _ from '/libs/lodash.js';
import _ from 'https://esm.sh/lodash@4.17.21/lodash.js';
Node.js나 번들러는 node_modules 규약을 알고 있어서 'lodash'를 해석하지만, 브라우저는 그 규약을 모릅니다. Import Maps는 이 해석 테이블을 HTML 안에 직접 선언해서 브라우저에게 전달합니다.
Import Maps 기본 문법
<script type="importmap">
{
"imports": {
"lodash": "/libs/lodash.js",
"lodash/": "/libs/lodash/",
"react": "https://esm.sh/react@18"
}
}
</script>
<script type="module">
import _ from 'lodash'; // → /libs/lodash.js
import chunk from 'lodash/chunk'; // → /libs/lodash/chunk.js
</script>
"lodash/" 처럼 트레일링 슬래시를 붙이면 서브패스 전체를 prefix로 매핑할 수 있습니다. "lodash/chunk"는 "/libs/lodash/" + "chunk"로 변환됩니다.
scopes — 경로별 매핑 오버라이드
전역 "imports" 말고도 특정 경로 하위에만 적용되는 매핑을 선언할 수 있습니다.
{
"imports": {
"lodash": "/libs/lodash-4.js"
},
"scopes": {
"/legacy/": {
"lodash": "/libs/lodash-3.js"
}
}
}
/legacy/app.js에서 import _ from 'lodash'를 호출하면 /libs/lodash-3.js로, 다른 경로에서는 /libs/lodash-4.js로 해석됩니다. 점진적 마이그레이션 때 유용합니다.
integrity 필드 — SRI 결합
Chrome 119부터 "integrity" 필드로 CDN 파일의 해시를 검증할 수 있습니다.
{
"imports": {
"react": "https://esm.sh/react@18.3.1"
},
"integrity": {
"https://esm.sh/react@18.3.1": "sha384-abc123xyz..."
}
}
해시가 일치하지 않으면 브라우저가 로드를 차단합니다. CDN이 변조된 파일을 반환해도 실행을 막을 수 있습니다.
동적 import와의 호환
Import Maps는 정적 import 선언뿐 아니라 동적 import()에도 동일하게 적용됩니다.
// importmap에 "utils": "/lib/utils.js" 선언되어 있을 때
const mod = await import('utils'); // → /lib/utils.js
import.meta.resolve()로 실제 URL을 미리 확인할 수도 있습니다.
import.meta.resolve('lodash'); // → "https://example.com/libs/lodash.js"
폴리필 패턴
브라우저 지원(Chrome 89+, Firefox 108+, Safari 16.4+)이 넓어졌지만, 구형 환경을 위해 es-module-shims 폴리필을 사용할 수 있습니다.
<script async src="https://ga.jspm.io/npm:es-module-shims@1.10.0/dist/es-module-shims.js"></script>
<script type="importmap"> ... </script>
<script type="module"> ... </script>
es-module-shims는 네이티브 ESM을 지원하는 브라우저에서도 Import Maps를 파싱·처리해주므로 기능 감지 없이 안전하게 사용 가능합니다.
제약 사항
Import Maps는 편리하지만 몇 가지 제약이 있습니다.
- HTML 문서당 importmap은 하나만 허용 (복수 선언 불가)
- 모듈 로드가 시작된 뒤에 선언하면 무시됨 —
<head>최상단에 위치해야 함 - 트리 쉐이킹, 코드 스플리팅 같은 번들 최적화는 제공하지 않음
node_modules패키지를 그대로 매핑하면 각 파일이 별도 HTTP 요청으로 처리됨
프로덕션 대규모 앱에서는 여전히 번들러가 유리하지만, 프로토타입·소규모 도구·개발 환경에서는 빌드 단계 없이 ESM을 편하게 쓸 수 있는 강력한 옵션입니다.
지난 글: 트리 쉐이킹 — 사용하지 않는 코드를 제거하는 기술
다음 글: 모듈 캐시와 순환 의존성
읽어주셔서 감사합니다. 😊