Node.js ESM 해석 알고리즘(Resolution Algorithm)의 역할은 다음 두 가지뿐입니다:
import에 포함된 지정자(specifier)를 최종 URL로 해석- 해당 URL의 모듈 형식을 결정
예:
Node.js는 최종적으로 다음을 얻어야 합니다:
react -> file:///project/node_modules/react/index.js
./utils.js -> file:///project/src/utils.js
#config -> file:///project/src/config/index.js
그리고 다음과 같은 모듈 형식도 있습니다:
module
commonjs
json
wasm
ESM 규격 전체는 본질적으로 다음 과정을 설명합니다:
specifier
↓
resolved URL
↓
module format
↓
load
↓
execute
1. ESM_RESOLVE 전체 흐름
Node.js ESM의 진입 알고리즘:
ESM_RESOLVE(specifier, parentURL)
다음처럼 단순화할 수 있습니다:
전체 알고리즘의 핵심 목표:
specifier
↓
唯一 URL
CommonJS처럼 계속 추측하는 방식이 아닙니다.
2. 지정자 분류
Node.js는 지정자를 네 가지 유형으로 분류합니다.
1. URL 지정자
예를 들어:
또는:
자체적으로 유효한 URL이라면:
new URL(specifier)
성공하면 그대로 반환합니다.
2. 상대 지정자
예를 들어:
Node.js는 현재 모듈의 위치를 기준으로 해석합니다.
가정해 봅시다:
file:///app/src/main.js
실행하면:
결과는 다음과 같습니다:
file:///app/src/utils.js
본질적으로는 다음과 같습니다:
3. 패키지 imports
예를 들어:
또는:
해시 기호로 시작합니다.
다음 알고리즘으로 들어갑니다:
PACKAGE_IMPORTS_RESOLVE()
현재 패키지를 읽습니다:
예를 들어:
최종적으로 다음 경로를 얻습니다:
./src/db/index.js
4. 패키지명 지정자
예를 들어:
URL, 경로, #import 어느 것도 아니라면 패키지명 지정자입니다.
다음 알고리즘으로 들어갑니다:
PACKAGE_RESOLVE()
node_modules 검색을 시작합니다.
3. PACKAGE_RESOLVE
Node.js가 npm 패키지를 찾는 핵심 로직입니다.
예를 들어:
현재 파일이 다음과 같다면:
/app/src/pages/home/index.js
Node.js는 계속 상위 디렉터리로 올라가며 찾습니다:
/app/src/pages/home/node_modules/react
/app/src/pages/node_modules/react
/app/src/node_modules/react
/app/node_modules/react
/node_modules/react
찾을 때까지 반복합니다.
다음과 동등합니다:
while(currentDirectory){
查找 node_modules/packageName
找不到继续向上
}
4. package.json 읽기
패키지를 찾으면:
node_modules/react/package.json
Node.js가 구성을 읽기 시작합니다.
우선순위는 다음과 같습니다:
exports
↓
main
↓
直接路径
5. exports 메커니즘
최신 Node.js의 패키지 해석은 거의 완전히 exports에 의존합니다.
예를 들어:
다음과 같이 허용합니다:
다음에 대응합니다:
.
결과는 다음과 같습니다:
./dist/index.js
또한 다음과 같이 허용합니다:
다음에 대응합니다:
./jsx-runtime
결과는 다음과 같습니다:
./dist/jsx-runtime.js
하지만 다음 코드를 실행하면:
exports에 해당 항목이 없다면:
다음 오류가 발생합니다:
Package Path Not Exported
6. exports의 본질
exports는 다음과 같이 이해할 수 있습니다:
包对外暴露的公开 API
예를 들어:
다음과 같이 허용합니다:
다음 항목은 금지됩니다:
실제 파일이 존재하더라도 마찬가지입니다.
7. 조건부 exports
exports는 반드시 문자열일 필요는 없습니다. 객체일 수도 있습니다.
예를 들어:
Node.js는 조건에 따라 대상을 선택합니다.
ESM에서는:
다음과 같이 매칭됩니다:
결과는 다음과 같습니다:
./dist/index.mjs
CommonJS에서는:
다음과 같이 매칭됩니다:
결과는 다음과 같습니다:
./dist/index.cjs
8. PACKAGESELFRESOLVE
가정해 봅시다:
현재 코드가 다음 패키지 내부에 있다면:
my-lib
그러면:
외부 node_modules를 탐색하지 않습니다.
Node.js는 다음과 같이 확인합니다:
当前包名就是 my-lib
현재 package.json의 exports를 직접 사용합니다.
이것이 PACKAGESELFRESOLVE입니다:
PACKAGE_SELF_RESOLVE
9. imports 메커니즘
imports는 exports와 매우 비슷합니다.
차이는 다음과 같습니다:
exports 给别人用
imports 给自己用
예를 들어:
이후:
실제 해석 결과:
./src/db/index.js
다시 예를 들어:
결과는 다음과 같습니다:
./src/utils/string.js
10. 패턴 매칭
imports와 exports는 와일드카드를 지원합니다.
예를 들어:
실행하면:
다음과 같이 매칭됩니다:
*
결과는 다음과 같습니다:
user
최종 결과:
./src/features/user.js
11. PACKAGETARGETRESOLVE
exports/imports의 매핑이 실제로 실행되는 지점입니다.
네 가지 유형을 지원합니다.
문자열
그대로 해석합니다.
객체
conditions에 따라 선택합니다.
배열
앞의 항목이 실패하면 다음 항목을 계속 시도합니다.
null
내보내기를 명시적으로 차단합니다.
12. ESMFILEFORMAT
URL 위치가 확정된 후.
Node.js는 판단해야 합니다:
这个文件应该按什么格式加载?
.mjs
module
.cjs
commonjs
.json
json
.wasm
wasm
.node
addon
네이티브 확장 모듈입니다.
13. type 필드의 역할
다음 파일에 대해:
.js
Node.js는 가장 가까운 package.json을 찾습니다.
예를 들어:
그러면:
다음과 같이 해석됩니다:
ESM
만약:
그러면:
다음과 같이 해석됩니다:
CommonJS
따라서:
.mjs
항상 ESM입니다.
.cjs
항상 CommonJS입니다.
.js
type에 따라 달라집니다.
14. ESM이 디렉터리 가져오기를 지원하지 않는 이유
CommonJS에서는:
Node.js는 다음 항목들을 시도합니다:
foo.js
foo.json
foo.node
foo/index.js
foo/index.json
ESM에서는:
추측하지 않습니다.
다음이 디렉터리라면:
foo
즉시 오류가 발생합니다:
Unsupported Directory Import
올바른 작성 방법은 다음과 같습니다:
또는:
15. LOOKUPPACKAGESCOPE
Node.js는 가장 가까운 package.json을 어떻게 찾을까요?
알고리즘:
当前目录
↓
父目录
↓
继续向上
↓
直到根目录
예를 들어:
/app/src/pages/home/index.js
조회 경로는 다음과 같습니다:
/app/src/pages/home/package.json
/app/src/pages/package.json
/app/src/package.json
/app/package.json
첫 번째 package.json을 찾으면 멈춥니다.
16. 사용자 정의 ESM 리졸버
Node.js의 기본 해석은 다음과 같습니다:
다음과 같은 구문을 지원하려면:
어떻게 해야 할까요?
답은 다음과 같습니다:
Loader Hook
예를 들어:
실행:
node --loader ./loader.mjs app.js
그러면:
다음과 같이 자동으로 매핑됩니다:
src/utils.js
17. 전체 해석 흐름
Node.js ESM의 전체 해석 흐름은 다음과 같이 정리할 수 있습니다:
요약
Node.js ESM의 핵심은 “파일 찾기”가 아닙니다.
바로 다음과 같습니다:
specifier
↓
确定 URL
↓
确定模块格式
↓
加载执行
exports, imports, type, 조건부 exports, loader 메커니즘은 모두 본질적으로 이 목표를 중심으로 구축되었습니다.
ESM 해석 모델은 CommonJS보다 더 엄격하고 정적이며, 브라우저에 더 가깝고, 현대적인 툴체인(Vite, Webpack, Rspack, Rollup, Turbopack)의 분석과 최적화에도 더 적합합니다.