"__dirname is not defined in ES module scope" 오류의 원인과 해결방법

Juice-Han·2024년 2월 6일
0
post-thumbnail

__dirname 오류

vite를 통해 react앱을 만들고 로컬 환경에서 express로 서버를 구축하던 중 오류가 발생했다.

바로 __dirname이 정의되지 않았다는 것이다.

	app.use(express.static(path.join(__dirname, '/dist')))

이 코드에서 문제가 발생했는데, dist라는 디렉터리를 express에 등록하는 코드이다.

vite로 build를 할 경우 루트 디렉터리 내에 dist라는 디렉터리가 생기고,
그 안에는 index.html, 이미지 파일과 같은 정적인(static) 파일이 저장된다.
이 디렉터리를 express가 전송해주기 위해선 먼저 등록하는 과정이 필요한데,
나는 그 과정에서 오류가 발생한 것이다.

원인

구글링 하던 중 원인과 해결방법을 찾을 수 있었다.

ES module을 사용하면 __dirname을 '그냥' 사용할 수 없다는 것이다.

"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,

tsconfig.json파일의 내용 중 compilerOptions 일부분을 가져온 것이다.
코드를 보면 ESNext라는 module을 사용하고 있다는 것을 알 수 있다.

해결방법

코드 2줄을 server.js파일 상단에 추가했다.

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

파일이나 디렉터리 경로를 다루는 path모듈과
일반적인 파일 url을 Node.js 파일 path로 바꿔주는 fileURLToPath 함수를 가져온다.

fileURLToPath 함수란?

다음은 fileURLToPath 함수에 관한 공식문서이다.

fileURLToPath 함수

url을 입력받으면 (완전히 플랫폼 문제가 해결된) 특정한 Node.js 파일 경로를 리턴해준다고 한다.


그 다음 하단에 코드 2줄을 추가한다.

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
  1. server.js의 파일url을 가져와서 fileURLToPath로 경로 변환해서 __filename에 저장하고
  2. 변환된 경로의 디렉터리 경로를 __dirname에 저장한다.

이렇게 코드를 작성하면 오류가 해결되는데, 도대체 어떤 과정을 거쳐 해결되는지 궁금해서 더 알아봤다.

import.meta.url은 어떤 값일까?

import.meta.url값

server.js의 경로를 저장하고 있는건 맞는데, 앞에 file:///가 붙어있다.
아마 이를 제거하기 위해 fileURLToPath함수를 사용하는 것 같다.

그럼 __filename, __dirname에는 어떤 값이 저장될까?

console.log로 __filename__dirname을 출력해보면 다음과 같은 결과를 얻는다.

출력결과

  • __filename에 저장된 값
    C:\Users\user\Desktop\Programing\nodejs-study\my-blog-app\server.js

  • __dirname에 저장된 값
    C:\Users\user\Desktop\Programing\nodejs-study\my-blog-app

결론적으로 fileURLToPath(import.meta.url)을 통해 서버 파일의 경로, 즉 server.js의 경로를 가져온 후, path.dirname(__filename)을 통해 그 파일이 포함된 디렉토리를 찾아서 경로를 반환하는 것을 알 수 있다.

오류 해결

이를 통해 정상적으로 __dirname을 사용할 수 있게 됐다.


참고자료

profile
배우고 기록하고

0개의 댓글