ESM 모듈 시스템을 사용하여 자바스크립트를 개발하는 도중 한가지 난관에 부딪힐 때가 있습니다. 그건 바로 기존의 commonjs 환경에서 사용되던 __dirname
이 ESM 코드에서 undefined
값이 되는 문제입니다. 주요 에러는 다음과 같습니다.
ReferenceError: __dirname is not defined in ES module scope at file:///C://Users/test/Project/index.js:14:13 at ModuleJob.run (node:internal/modules/esm/module_job:198:25) at async Promise.all (index 0) at async ESMLoader.import (node:internal/modules/esm/loader:385: 24) at async loadESM (node:internal/process/esm_loader:88:5) at async handleMainPromise (node:internal/modules/run_main:61:12 )
__dirname
은 NodeJS에서 기본으로 제공되는 환경 변수입니다. 유사한 변수는 __filename
이 있는데 이 두가지 변수가 리턴하는 값은 다음과 같습니다.
__dirname
: 현재 스크립트를 실행한 프로젝트의 디렉토리 경로__filename
: 현재 스크립트를 실행한 프로젝트의 전체 파일 경로예를 들어 node
명령을 C:\Users\test\Desktop\Project
에서 실행했다면, __dirname
과 __filename
의 값은 다음과 같습니다.
$ node index.js __dirname is 'C:\Users\test\Desktop\Project' __filename is 'C:\Users\test\Desktop\Project\index.js'
__dirname
을 별도 선언 없이 사용했었지만 ESM에서는 이러한 변수가 NodeJS에서 기본 지원되지 않습니다. 따라서 위와 같은 에러 메시지가 출력되는 것입니다. 이는 __filename
변수도 마찬가지입니다.
이 문제는 아래와 같은 방법으로 ESM 모듈에서 __dirname
을 직접 선언하여 해결할 수 있습니다.
import { dirname } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url));
여기서 path와 url 모듈을 사용하는데, path
의 dirname
메소드는 주어진 파일 경로에서 디렉토리 경로만 리턴하는 메소드이고, url
의 fileURLToPath
메소드는 올바른 파일 경로로 컨버팅하고 퍼센트 인코딩을 디코딩해주는 역할을 합니다.
import.meta의 경우 현재 실행 중인 스크립트의 정보를 표시하는데, 아래와 같이 JSON 데이터로 값을 반환합니다.
console.log(JSON.stringify(import.meta)); // Result: {"url":"file:///C:/Users/test/Desktop/Project/index.js"}
여기서 url
키 정보를 사용하기 위해 위 코드에서 import.meta.url
을 사용하였습니다. 이렇게 조합하여 나온 리턴값은 기존에 사용하던 __dirname
의 값과 같아집니다.
마찬가지로 __filename
을 사용하고 싶은 경우 위 예시에서 dirname
메소드를 빼고 사용하시면 됩니다.
import { dirname } from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename);
Xcode에서 iOS 애플리케이션을 빌드(Archive)하고 App Store Connect에 앱을 업로드하는 도중, 아래와 같은 에러가 발생하면서 더…
INSTALL_FAILED_INSUFFICIENT_STORAGE 문제 안드로이드 스튜디오에서 에뮬레이터를 실행하고 개발중인 애플리케이션을 실행하려 하면 로그 창에 아래와 같이 표시되면서…
리눅스 명령어 - kill, killall 리눅스 kill 명령어는 특정 프로세스를 종료해주는 명령어입니다. 백그라운드에서 실행되고 있는…
JavaScript는 역사가 긴 스크립트 프로그래밍 언어입니다. 세월이 흐르면서 많은 자바스크립트 표준이 만들어졌고, 현재는 많은 문법적…
NodeJS 테스트 프레임워크인 Mocha는 비동기 테스트를 지원합니다. 간혹 특정 테스트 스크립트를 작성하고 실행하면 아래와 같이…