JooTC
nodejs-logo-2019-gray

자바스크립트 ESM (ES Module)에서 __dirname 사용하기

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
)

__dirnameNodeJS에서 기본으로 제공되는 환경 변수입니다. 유사한 변수는 __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 is not defined 해결 방법

이 문제는 아래와 같은 방법으로 ESM 모듈에서 __dirname을 직접 선언하여 해결할 수 있습니다.

import { dirname } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));

여기서 pathurl 모듈을 사용하는데, pathdirname 메소드는 주어진 파일 경로에서 디렉토리 경로만 리턴하는 메소드이고, urlfileURLToPath 메소드는 올바른 파일 경로로 컨버팅하고 퍼센트 인코딩을 디코딩해주는 역할을 합니다.

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);
구독
알림
guest

0 Comments
Inline Feedbacks
모든 댓글 보기
0
이 포스트에 대한 의견을 남겨주세요!x