NodeJS

자바스크립트 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);
JooTC

안녕하세요. 테크놀로지에 관심이 많은 블로거입니다.

Recent Posts

Zalgo 텍스트와 이를 방지하는 방법

인터넷 커뮤니티 사이트에서 게시글이나 댓글에 간혹 장난을 목적으로 작성된 특이한 글자를 볼 수 있습니다. 위…

1개월 ago

리눅스 kill, killall 명령어 – 특정 프로세스 종료하기

리눅스 명령어 - kill, killall 리눅스 kill 명령어는 특정 프로세스를 종료해주는 명령어입니다. 백그라운드에서 실행되고 있는…

1개월 ago

JavaScript typeof null이 ‘object’인 이유

JavaScript는 역사가 긴 스크립트 프로그래밍 언어입니다. 세월이 흐르면서 많은 자바스크립트 표준이 만들어졌고, 현재는 많은 문법적…

1개월 ago

Mocha Error: Resolution method is overspecified. 해결 방법

NodeJS 테스트 프레임워크인 Mocha는 비동기 테스트를 지원합니다. 간혹 특정 테스트 스크립트를 작성하고 실행하면 아래와 같이…

1개월 ago

윈도우 11 설치 시 Microsoft 계정 로그인 없이 로컬 계정 만들기

언제부턴가 윈도우 11을 처음 설치할 때 마이크로소프트(Microsoft) 계정 로그인을 강제로 요구하게 되었습니다. 물론 마이크로소프트 계정이…

7개월 ago

에어팟 프로 2 케이스 스피커 소리를 완전히 끄는 방법

애플 에어팟 프로 2 (AirPods Pro 2) 케이스에는 스피커가 내장되어 있습니다. 그런데 간혹 아무 것도…

9개월 ago