path.resolve()와 __dirname의 차이

Seonup·2023년 11월 14일
0

본 시리즈는 정재남님의 풀스택 리액트 라이브코딩 - 간단한 쇼핑몰 만들기 강의 내용을 기반으로, 추가적인 학습을 통해 습득한 지식 또는 강의 코드를 다른 방법으로 구현한 경험을 작성하고 있습니다. 강의 코드(GitHub)를 확인하세요.

강의에서 shopping-mall/server/src/dbController.ts 파일에서 db 위치를 읽어올 때 basePath를 추출하기 위해 path.resolve() 함수를 사용했다. 나는 resolve() 대신 Node.js에서 제공하는 전역변수 __dirname을 활용하여 함수 호출을 줄일 수 있을 것이라고 판단했고 로직을 변경했다. 하지만 이 변경으로 경로를 올바르게 인식하지 못하는 문제가 발생했다. 문제가 발생한 코드를 살펴보며, path.resolve()__dirname의 차이에 대해 알아보자.

문제 발생

path.resolve() 사용했을 때

import fs from "fs";
import { resolve } from "path";

enum DBField {
  PRODUCTS = "products",
}

const basePath = resolve(); // __dirname으로 바꾸기 전;

const filenames = {
  [DBField.PRODUCTS]: resolve(basePath, "src/db/products.json"),
};

const readDB = (target: DBField) => {
  try {
    return JSON.parse(fs.readFileSync(filenames[target], "utf-8"));
  } catch (err) {
    console.error(err);
  }
};

console.log(readDB(DBField.PRODUCTS));

path.resolve()를 사용한 코드는 위와 같으며, readDB(DBField.PRODUCTS)를 호출했을 때 shopping-mall/server/src/db/products.json에 작성된 데이터를 정상적으로 읽어왔다.

__dirname를 사용했을 때

하지만, resolve()를 아래와 같이 __dirname으로 변경하자 에러 메세지를 띄웠다.

// const basePath = resolve();
const basePath = __dirname;

Error: ENOENT: no such file or directory, open 'shopping-mall/server/src/src/db/products.json'

__dirnamepath.resolve()에서 읽어왔던 디렉토리 경로와 달리 shopping-mall/server/src/src/db/products.json를 출력한 것이다.

문제 원인 분석

그렇다면, 왜 __dirnamepath.resolve()는 서로 다른 경로를 제공하는걸까?

path.resolve(): the current working directory is used.

Node API 문서를 읽어보면, 인수를 전달하지 않은 path.resolve는 현재 작업 중인 디렉토리, 즉 명령어를 실행하거나 스크립트 파일이 위치하는 디렉토리를 반환하고,

__dirname: The directory name of the current module.

__dirname은 현재 실행하고 있는(runnding) 디렉토리를 제공한다.

즉, 문제가 발생된 원인은는 애초부터 __dirnamepath.resolve()는 제공하는 디렉토리의 기준이 명확하게 달랐기 때문이다.

문제 해결

따라서, __dirname을 사용하기 위해서는 아래의 코드처럼 기존의 코드에서 참조할 정적파일 위치 또한 변경해줘야 문제를 해결할 수 있다.
(__dirname은 전역 변수 참조의 개념으로 path.resolve()는 변수에 저장하지 않으면 매 참조마다 메소드를 호출하는 코드 중복의 개념이 아니기 때문에 basePath라는 변수 선언을 생략했다.)

const filenames = {
  [DBField.PRODUCTS]: resolve(__dirname, "db/products.json"),
};

결론

  • 인수를 전달하지 않은 path.resolve는 현재 작업 중인 디렉토리를 제공한다.
  • __dirname은 현재 실행하고 있는(runnding) 디렉토리를 제공한다.
  • 결국 resolve 메서드를 사용했기 때문에,
profile
박선우

1개의 댓글

comment-user-thumbnail
2023년 11월 14일

유익한 글이었습니다.

답글 달기